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.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
20 
21 import static java.lang.Math.max;
22 
23 import android.animation.AnimatorInflater;
24 import android.animation.StateListAnimator;
25 import android.annotation.CallSuper;
26 import android.annotation.ColorInt;
27 import android.annotation.DrawableRes;
28 import android.annotation.FloatRange;
29 import android.annotation.IdRes;
30 import android.annotation.IntDef;
31 import android.annotation.IntRange;
32 import android.annotation.LayoutRes;
33 import android.annotation.NonNull;
34 import android.annotation.Nullable;
35 import android.annotation.Size;
36 import android.annotation.TestApi;
37 import android.annotation.UiThread;
38 import android.content.ClipData;
39 import android.content.Context;
40 import android.content.ContextWrapper;
41 import android.content.Intent;
42 import android.content.res.ColorStateList;
43 import android.content.res.Configuration;
44 import android.content.res.Resources;
45 import android.content.res.TypedArray;
46 import android.graphics.Bitmap;
47 import android.graphics.Canvas;
48 import android.graphics.Color;
49 import android.graphics.Insets;
50 import android.graphics.Interpolator;
51 import android.graphics.LinearGradient;
52 import android.graphics.Matrix;
53 import android.graphics.Outline;
54 import android.graphics.Paint;
55 import android.graphics.PixelFormat;
56 import android.graphics.Point;
57 import android.graphics.PorterDuff;
58 import android.graphics.PorterDuffXfermode;
59 import android.graphics.Rect;
60 import android.graphics.RectF;
61 import android.graphics.Region;
62 import android.graphics.Shader;
63 import android.graphics.drawable.ColorDrawable;
64 import android.graphics.drawable.Drawable;
65 import android.hardware.display.DisplayManagerGlobal;
66 import android.net.Uri;
67 import android.os.Build;
68 import android.os.Bundle;
69 import android.os.Handler;
70 import android.os.IBinder;
71 import android.os.Message;
72 import android.os.Parcel;
73 import android.os.Parcelable;
74 import android.os.RemoteException;
75 import android.os.SystemClock;
76 import android.os.SystemProperties;
77 import android.os.Trace;
78 import android.text.InputType;
79 import android.text.TextUtils;
80 import android.util.AttributeSet;
81 import android.util.FloatProperty;
82 import android.util.LayoutDirection;
83 import android.util.Log;
84 import android.util.LongSparseLongArray;
85 import android.util.Pools.SynchronizedPool;
86 import android.util.Property;
87 import android.util.SparseArray;
88 import android.util.StateSet;
89 import android.util.SuperNotCalledException;
90 import android.util.TypedValue;
91 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
92 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
93 import android.view.AccessibilityIterators.TextSegmentIterator;
94 import android.view.AccessibilityIterators.WordTextSegmentIterator;
95 import android.view.ContextMenu.ContextMenuInfo;
96 import android.view.accessibility.AccessibilityEvent;
97 import android.view.accessibility.AccessibilityEventSource;
98 import android.view.accessibility.AccessibilityManager;
99 import android.view.accessibility.AccessibilityNodeInfo;
100 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
101 import android.view.accessibility.AccessibilityNodeProvider;
102 import android.view.accessibility.AccessibilityWindowInfo;
103 import android.view.animation.Animation;
104 import android.view.animation.AnimationUtils;
105 import android.view.animation.Transformation;
106 import android.view.autofill.AutofillId;
107 import android.view.autofill.AutofillManager;
108 import android.view.autofill.AutofillValue;
109 import android.view.inputmethod.EditorInfo;
110 import android.view.inputmethod.InputConnection;
111 import android.view.inputmethod.InputMethodManager;
112 import android.widget.Checkable;
113 import android.widget.FrameLayout;
114 import android.widget.ScrollBarDrawable;
115 
116 import com.android.internal.R;
117 import com.android.internal.view.TooltipPopup;
118 import com.android.internal.view.menu.MenuBuilder;
119 import com.android.internal.widget.ScrollBarUtils;
120 
121 import com.google.android.collect.Lists;
122 import com.google.android.collect.Maps;
123 
124 import java.lang.annotation.Retention;
125 import java.lang.annotation.RetentionPolicy;
126 import java.lang.ref.WeakReference;
127 import java.lang.reflect.Field;
128 import java.lang.reflect.InvocationTargetException;
129 import java.lang.reflect.Method;
130 import java.lang.reflect.Modifier;
131 import java.util.ArrayList;
132 import java.util.Arrays;
133 import java.util.Calendar;
134 import java.util.Collection;
135 import java.util.Collections;
136 import java.util.HashMap;
137 import java.util.List;
138 import java.util.Locale;
139 import java.util.Map;
140 import java.util.concurrent.CopyOnWriteArrayList;
141 import java.util.concurrent.atomic.AtomicInteger;
142 import java.util.function.Predicate;
143 
144 /**
145  * <p>
146  * This class represents the basic building block for user interface components. A View
147  * occupies a rectangular area on the screen and is responsible for drawing and
148  * event handling. View is the base class for <em>widgets</em>, which are
149  * used to create interactive UI components (buttons, text fields, etc.). The
150  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
151  * are invisible containers that hold other Views (or other ViewGroups) and define
152  * their layout properties.
153  * </p>
154  *
155  * <div class="special reference">
156  * <h3>Developer Guides</h3>
157  * <p>For information about using this class to develop your application's user interface,
158  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
159  * </div>
160  *
161  * <a name="Using"></a>
162  * <h3>Using Views</h3>
163  * <p>
164  * All of the views in a window are arranged in a single tree. You can add views
165  * either from code or by specifying a tree of views in one or more XML layout
166  * files. There are many specialized subclasses of views that act as controls or
167  * are capable of displaying text, images, or other content.
168  * </p>
169  * <p>
170  * Once you have created a tree of views, there are typically a few types of
171  * common operations you may wish to perform:
172  * <ul>
173  * <li><strong>Set properties:</strong> for example setting the text of a
174  * {@link android.widget.TextView}. The available properties and the methods
175  * that set them will vary among the different subclasses of views. Note that
176  * properties that are known at build time can be set in the XML layout
177  * files.</li>
178  * <li><strong>Set focus:</strong> The framework will handle moving focus in
179  * response to user input. To force focus to a specific view, call
180  * {@link #requestFocus}.</li>
181  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
182  * that will be notified when something interesting happens to the view. For
183  * example, all views will let you set a listener to be notified when the view
184  * gains or loses focus. You can register such a listener using
185  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
186  * Other view subclasses offer more specialized listeners. For example, a Button
187  * exposes a listener to notify clients when the button is clicked.</li>
188  * <li><strong>Set visibility:</strong> You can hide or show views using
189  * {@link #setVisibility(int)}.</li>
190  * </ul>
191  * </p>
192  * <p><em>
193  * Note: The Android framework is responsible for measuring, laying out and
194  * drawing views. You should not call methods that perform these actions on
195  * views yourself unless you are actually implementing a
196  * {@link android.view.ViewGroup}.
197  * </em></p>
198  *
199  * <a name="Lifecycle"></a>
200  * <h3>Implementing a Custom View</h3>
201  *
202  * <p>
203  * To implement a custom view, you will usually begin by providing overrides for
204  * some of the standard methods that the framework calls on all views. You do
205  * not need to override all of these methods. In fact, you can start by just
206  * overriding {@link #onDraw(android.graphics.Canvas)}.
207  * <table border="2" width="85%" align="center" cellpadding="5">
208  *     <thead>
209  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
210  *     </thead>
211  *
212  *     <tbody>
213  *     <tr>
214  *         <td rowspan="2">Creation</td>
215  *         <td>Constructors</td>
216  *         <td>There is a form of the constructor that are called when the view
217  *         is created from code and a form that is called when the view is
218  *         inflated from a layout file. The second form should parse and apply
219  *         any attributes defined in the layout file.
220  *         </td>
221  *     </tr>
222  *     <tr>
223  *         <td><code>{@link #onFinishInflate()}</code></td>
224  *         <td>Called after a view and all of its children has been inflated
225  *         from XML.</td>
226  *     </tr>
227  *
228  *     <tr>
229  *         <td rowspan="3">Layout</td>
230  *         <td><code>{@link #onMeasure(int, int)}</code></td>
231  *         <td>Called to determine the size requirements for this view and all
232  *         of its children.
233  *         </td>
234  *     </tr>
235  *     <tr>
236  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
237  *         <td>Called when this view should assign a size and position to all
238  *         of its children.
239  *         </td>
240  *     </tr>
241  *     <tr>
242  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
243  *         <td>Called when the size of this view has changed.
244  *         </td>
245  *     </tr>
246  *
247  *     <tr>
248  *         <td>Drawing</td>
249  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
250  *         <td>Called when the view should render its content.
251  *         </td>
252  *     </tr>
253  *
254  *     <tr>
255  *         <td rowspan="4">Event processing</td>
256  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
257  *         <td>Called when a new hardware key event occurs.
258  *         </td>
259  *     </tr>
260  *     <tr>
261  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
262  *         <td>Called when a hardware key up event occurs.
263  *         </td>
264  *     </tr>
265  *     <tr>
266  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
267  *         <td>Called when a trackball motion event occurs.
268  *         </td>
269  *     </tr>
270  *     <tr>
271  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
272  *         <td>Called when a touch screen motion event occurs.
273  *         </td>
274  *     </tr>
275  *
276  *     <tr>
277  *         <td rowspan="2">Focus</td>
278  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
279  *         <td>Called when the view gains or loses focus.
280  *         </td>
281  *     </tr>
282  *
283  *     <tr>
284  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
285  *         <td>Called when the window containing the view gains or loses focus.
286  *         </td>
287  *     </tr>
288  *
289  *     <tr>
290  *         <td rowspan="3">Attaching</td>
291  *         <td><code>{@link #onAttachedToWindow()}</code></td>
292  *         <td>Called when the view is attached to a window.
293  *         </td>
294  *     </tr>
295  *
296  *     <tr>
297  *         <td><code>{@link #onDetachedFromWindow}</code></td>
298  *         <td>Called when the view is detached from its window.
299  *         </td>
300  *     </tr>
301  *
302  *     <tr>
303  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
304  *         <td>Called when the visibility of the window containing the view
305  *         has changed.
306  *         </td>
307  *     </tr>
308  *     </tbody>
309  *
310  * </table>
311  * </p>
312  *
313  * <a name="IDs"></a>
314  * <h3>IDs</h3>
315  * Views may have an integer id associated with them. These ids are typically
316  * assigned in the layout XML files, and are used to find specific views within
317  * the view tree. A common pattern is to:
318  * <ul>
319  * <li>Define a Button in the layout file and assign it a unique ID.
320  * <pre>
321  * &lt;Button
322  *     android:id="@+id/my_button"
323  *     android:layout_width="wrap_content"
324  *     android:layout_height="wrap_content"
325  *     android:text="@string/my_button_text"/&gt;
326  * </pre></li>
327  * <li>From the onCreate method of an Activity, find the Button
328  * <pre class="prettyprint">
329  *      Button myButton = findViewById(R.id.my_button);
330  * </pre></li>
331  * </ul>
332  * <p>
333  * View IDs need not be unique throughout the tree, but it is good practice to
334  * ensure that they are at least unique within the part of the tree you are
335  * searching.
336  * </p>
337  *
338  * <a name="Position"></a>
339  * <h3>Position</h3>
340  * <p>
341  * The geometry of a view is that of a rectangle. A view has a location,
342  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
343  * two dimensions, expressed as a width and a height. The unit for location
344  * and dimensions is the pixel.
345  * </p>
346  *
347  * <p>
348  * It is possible to retrieve the location of a view by invoking the methods
349  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
350  * coordinate of the rectangle representing the view. The latter returns the
351  * top, or Y, coordinate of the rectangle representing the view. These methods
352  * both return the location of the view relative to its parent. For instance,
353  * when getLeft() returns 20, that means the view is located 20 pixels to the
354  * right of the left edge of its direct parent.
355  * </p>
356  *
357  * <p>
358  * In addition, several convenience methods are offered to avoid unnecessary
359  * computations, namely {@link #getRight()} and {@link #getBottom()}.
360  * These methods return the coordinates of the right and bottom edges of the
361  * rectangle representing the view. For instance, calling {@link #getRight()}
362  * is similar to the following computation: <code>getLeft() + getWidth()</code>
363  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
364  * </p>
365  *
366  * <a name="SizePaddingMargins"></a>
367  * <h3>Size, padding and margins</h3>
368  * <p>
369  * The size of a view is expressed with a width and a height. A view actually
370  * possess two pairs of width and height values.
371  * </p>
372  *
373  * <p>
374  * The first pair is known as <em>measured width</em> and
375  * <em>measured height</em>. These dimensions define how big a view wants to be
376  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
377  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
378  * and {@link #getMeasuredHeight()}.
379  * </p>
380  *
381  * <p>
382  * The second pair is simply known as <em>width</em> and <em>height</em>, or
383  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
384  * dimensions define the actual size of the view on screen, at drawing time and
385  * after layout. These values may, but do not have to, be different from the
386  * measured width and height. The width and height can be obtained by calling
387  * {@link #getWidth()} and {@link #getHeight()}.
388  * </p>
389  *
390  * <p>
391  * To measure its dimensions, a view takes into account its padding. The padding
392  * is expressed in pixels for the left, top, right and bottom parts of the view.
393  * Padding can be used to offset the content of the view by a specific amount of
394  * pixels. For instance, a left padding of 2 will push the view's content by
395  * 2 pixels to the right of the left edge. Padding can be set using the
396  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
397  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
398  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
399  * {@link #getPaddingEnd()}.
400  * </p>
401  *
402  * <p>
403  * Even though a view can define a padding, it does not provide any support for
404  * margins. However, view groups provide such a support. Refer to
405  * {@link android.view.ViewGroup} and
406  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
407  * </p>
408  *
409  * <a name="Layout"></a>
410  * <h3>Layout</h3>
411  * <p>
412  * Layout is a two pass process: a measure pass and a layout pass. The measuring
413  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
414  * of the view tree. Each view pushes dimension specifications down the tree
415  * during the recursion. At the end of the measure pass, every view has stored
416  * its measurements. The second pass happens in
417  * {@link #layout(int,int,int,int)} and is also top-down. During
418  * this pass each parent is responsible for positioning all of its children
419  * using the sizes computed in the measure pass.
420  * </p>
421  *
422  * <p>
423  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
424  * {@link #getMeasuredHeight()} values must be set, along with those for all of
425  * that view's descendants. A view's measured width and measured height values
426  * must respect the constraints imposed by the view's parents. This guarantees
427  * that at the end of the measure pass, all parents accept all of their
428  * children's measurements. A parent view may call measure() more than once on
429  * its children. For example, the parent may measure each child once with
430  * unspecified dimensions to find out how big they want to be, then call
431  * measure() on them again with actual numbers if the sum of all the children's
432  * unconstrained sizes is too big or too small.
433  * </p>
434  *
435  * <p>
436  * The measure pass uses two classes to communicate dimensions. The
437  * {@link MeasureSpec} class is used by views to tell their parents how they
438  * want to be measured and positioned. The base LayoutParams class just
439  * describes how big the view wants to be for both width and height. For each
440  * dimension, it can specify one of:
441  * <ul>
442  * <li> an exact number
443  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
444  * (minus padding)
445  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
446  * enclose its content (plus padding).
447  * </ul>
448  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
449  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
450  * an X and Y value.
451  * </p>
452  *
453  * <p>
454  * MeasureSpecs are used to push requirements down the tree from parent to
455  * child. A MeasureSpec can be in one of three modes:
456  * <ul>
457  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
458  * of a child view. For example, a LinearLayout may call measure() on its child
459  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
460  * tall the child view wants to be given a width of 240 pixels.
461  * <li>EXACTLY: This is used by the parent to impose an exact size on the
462  * child. The child must use this size, and guarantee that all of its
463  * descendants will fit within this size.
464  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
465  * child. The child must guarantee that it and all of its descendants will fit
466  * within this size.
467  * </ul>
468  * </p>
469  *
470  * <p>
471  * To initiate a layout, call {@link #requestLayout}. This method is typically
472  * called by a view on itself when it believes that is can no longer fit within
473  * its current bounds.
474  * </p>
475  *
476  * <a name="Drawing"></a>
477  * <h3>Drawing</h3>
478  * <p>
479  * Drawing is handled by walking the tree and recording the drawing commands of
480  * any View that needs to update. After this, the drawing commands of the
481  * entire tree are issued to screen, clipped to the newly damaged area.
482  * </p>
483  *
484  * <p>
485  * The tree is largely recorded and drawn in order, with parents drawn before
486  * (i.e., behind) their children, with siblings drawn in the order they appear
487  * in the tree. If you set a background drawable for a View, then the View will
488  * draw it before calling back to its <code>onDraw()</code> method. The child
489  * drawing order can be overridden with
490  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
491  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
492  * </p>
493  *
494  * <p>
495  * To force a view to draw, call {@link #invalidate()}.
496  * </p>
497  *
498  * <a name="EventHandlingThreading"></a>
499  * <h3>Event Handling and Threading</h3>
500  * <p>
501  * The basic cycle of a view is as follows:
502  * <ol>
503  * <li>An event comes in and is dispatched to the appropriate view. The view
504  * handles the event and notifies any listeners.</li>
505  * <li>If in the course of processing the event, the view's bounds may need
506  * to be changed, the view will call {@link #requestLayout()}.</li>
507  * <li>Similarly, if in the course of processing the event the view's appearance
508  * may need to be changed, the view will call {@link #invalidate()}.</li>
509  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
510  * the framework will take care of measuring, laying out, and drawing the tree
511  * as appropriate.</li>
512  * </ol>
513  * </p>
514  *
515  * <p><em>Note: The entire view tree is single threaded. You must always be on
516  * the UI thread when calling any method on any view.</em>
517  * If you are doing work on other threads and want to update the state of a view
518  * from that thread, you should use a {@link Handler}.
519  * </p>
520  *
521  * <a name="FocusHandling"></a>
522  * <h3>Focus Handling</h3>
523  * <p>
524  * The framework will handle routine focus movement in response to user input.
525  * This includes changing the focus as views are removed or hidden, or as new
526  * views become available. Views indicate their willingness to take focus
527  * through the {@link #isFocusable} method. To change whether a view can take
528  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
529  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
530  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
531  * </p>
532  * <p>
533  * Focus movement is based on an algorithm which finds the nearest neighbor in a
534  * given direction. In rare cases, the default algorithm may not match the
535  * intended behavior of the developer. In these situations, you can provide
536  * explicit overrides by using these XML attributes in the layout file:
537  * <pre>
538  * nextFocusDown
539  * nextFocusLeft
540  * nextFocusRight
541  * nextFocusUp
542  * </pre>
543  * </p>
544  *
545  *
546  * <p>
547  * To get a particular view to take focus, call {@link #requestFocus()}.
548  * </p>
549  *
550  * <a name="TouchMode"></a>
551  * <h3>Touch Mode</h3>
552  * <p>
553  * When a user is navigating a user interface via directional keys such as a D-pad, it is
554  * necessary to give focus to actionable items such as buttons so the user can see
555  * what will take input.  If the device has touch capabilities, however, and the user
556  * begins interacting with the interface by touching it, it is no longer necessary to
557  * always highlight, or give focus to, a particular view.  This motivates a mode
558  * for interaction named 'touch mode'.
559  * </p>
560  * <p>
561  * For a touch capable device, once the user touches the screen, the device
562  * will enter touch mode.  From this point onward, only views for which
563  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
564  * Other views that are touchable, like buttons, will not take focus when touched; they will
565  * only fire the on click listeners.
566  * </p>
567  * <p>
568  * Any time a user hits a directional key, such as a D-pad direction, the view device will
569  * exit touch mode, and find a view to take focus, so that the user may resume interacting
570  * with the user interface without touching the screen again.
571  * </p>
572  * <p>
573  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
574  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
575  * </p>
576  *
577  * <a name="Scrolling"></a>
578  * <h3>Scrolling</h3>
579  * <p>
580  * The framework provides basic support for views that wish to internally
581  * scroll their content. This includes keeping track of the X and Y scroll
582  * offset as well as mechanisms for drawing scrollbars. See
583  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
584  * {@link #awakenScrollBars()} for more details.
585  * </p>
586  *
587  * <a name="Tags"></a>
588  * <h3>Tags</h3>
589  * <p>
590  * Unlike IDs, tags are not used to identify views. Tags are essentially an
591  * extra piece of information that can be associated with a view. They are most
592  * often used as a convenience to store data related to views in the views
593  * themselves rather than by putting them in a separate structure.
594  * </p>
595  * <p>
596  * Tags may be specified with character sequence values in layout XML as either
597  * a single tag using the {@link android.R.styleable#View_tag android:tag}
598  * attribute or multiple tags using the {@code <tag>} child element:
599  * <pre>
600  *     &lt;View ...
601  *           android:tag="@string/mytag_value" /&gt;
602  *     &lt;View ...&gt;
603  *         &lt;tag android:id="@+id/mytag"
604  *              android:value="@string/mytag_value" /&gt;
605  *     &lt;/View>
606  * </pre>
607  * </p>
608  * <p>
609  * Tags may also be specified with arbitrary objects from code using
610  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
611  * </p>
612  *
613  * <a name="Themes"></a>
614  * <h3>Themes</h3>
615  * <p>
616  * By default, Views are created using the theme of the Context object supplied
617  * to their constructor; however, a different theme may be specified by using
618  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
619  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
620  * code.
621  * </p>
622  * <p>
623  * When the {@link android.R.styleable#View_theme android:theme} attribute is
624  * used in XML, the specified theme is applied on top of the inflation
625  * context's theme (see {@link LayoutInflater}) and used for the view itself as
626  * well as any child elements.
627  * </p>
628  * <p>
629  * In the following example, both views will be created using the Material dark
630  * color scheme; however, because an overlay theme is used which only defines a
631  * subset of attributes, the value of
632  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
633  * the inflation context's theme (e.g. the Activity theme) will be preserved.
634  * <pre>
635  *     &lt;LinearLayout
636  *             ...
637  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
638  *         &lt;View ...&gt;
639  *     &lt;/LinearLayout&gt;
640  * </pre>
641  * </p>
642  *
643  * <a name="Properties"></a>
644  * <h3>Properties</h3>
645  * <p>
646  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
647  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
648  * available both in the {@link Property} form as well as in similarly-named setter/getter
649  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
650  * be used to set persistent state associated with these rendering-related properties on the view.
651  * The properties and methods can also be used in conjunction with
652  * {@link android.animation.Animator Animator}-based animations, described more in the
653  * <a href="#Animation">Animation</a> section.
654  * </p>
655  *
656  * <a name="Animation"></a>
657  * <h3>Animation</h3>
658  * <p>
659  * Starting with Android 3.0, the preferred way of animating views is to use the
660  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
661  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
662  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
663  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
664  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
665  * makes animating these View properties particularly easy and efficient.
666  * </p>
667  * <p>
668  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
669  * You can attach an {@link Animation} object to a view using
670  * {@link #setAnimation(Animation)} or
671  * {@link #startAnimation(Animation)}. The animation can alter the scale,
672  * rotation, translation and alpha of a view over time. If the animation is
673  * attached to a view that has children, the animation will affect the entire
674  * subtree rooted by that node. When an animation is started, the framework will
675  * take care of redrawing the appropriate views until the animation completes.
676  * </p>
677  *
678  * <a name="Security"></a>
679  * <h3>Security</h3>
680  * <p>
681  * Sometimes it is essential that an application be able to verify that an action
682  * is being performed with the full knowledge and consent of the user, such as
683  * granting a permission request, making a purchase or clicking on an advertisement.
684  * Unfortunately, a malicious application could try to spoof the user into
685  * performing these actions, unaware, by concealing the intended purpose of the view.
686  * As a remedy, the framework offers a touch filtering mechanism that can be used to
687  * improve the security of views that provide access to sensitive functionality.
688  * </p><p>
689  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
690  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
691  * will discard touches that are received whenever the view's window is obscured by
692  * another visible window.  As a result, the view will not receive touches whenever a
693  * toast, dialog or other window appears above the view's window.
694  * </p><p>
695  * For more fine-grained control over security, consider overriding the
696  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
697  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
698  * </p>
699  *
700  * @attr ref android.R.styleable#View_accessibilityHeading
701  * @attr ref android.R.styleable#View_alpha
702  * @attr ref android.R.styleable#View_background
703  * @attr ref android.R.styleable#View_clickable
704  * @attr ref android.R.styleable#View_contentDescription
705  * @attr ref android.R.styleable#View_drawingCacheQuality
706  * @attr ref android.R.styleable#View_duplicateParentState
707  * @attr ref android.R.styleable#View_id
708  * @attr ref android.R.styleable#View_requiresFadingEdge
709  * @attr ref android.R.styleable#View_fadeScrollbars
710  * @attr ref android.R.styleable#View_fadingEdgeLength
711  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
712  * @attr ref android.R.styleable#View_fitsSystemWindows
713  * @attr ref android.R.styleable#View_isScrollContainer
714  * @attr ref android.R.styleable#View_focusable
715  * @attr ref android.R.styleable#View_focusableInTouchMode
716  * @attr ref android.R.styleable#View_focusedByDefault
717  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
718  * @attr ref android.R.styleable#View_keepScreenOn
719  * @attr ref android.R.styleable#View_keyboardNavigationCluster
720  * @attr ref android.R.styleable#View_layerType
721  * @attr ref android.R.styleable#View_layoutDirection
722  * @attr ref android.R.styleable#View_longClickable
723  * @attr ref android.R.styleable#View_minHeight
724  * @attr ref android.R.styleable#View_minWidth
725  * @attr ref android.R.styleable#View_nextClusterForward
726  * @attr ref android.R.styleable#View_nextFocusDown
727  * @attr ref android.R.styleable#View_nextFocusLeft
728  * @attr ref android.R.styleable#View_nextFocusRight
729  * @attr ref android.R.styleable#View_nextFocusUp
730  * @attr ref android.R.styleable#View_onClick
731  * @attr ref android.R.styleable#View_outlineSpotShadowColor
732  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
733  * @attr ref android.R.styleable#View_padding
734  * @attr ref android.R.styleable#View_paddingHorizontal
735  * @attr ref android.R.styleable#View_paddingVertical
736  * @attr ref android.R.styleable#View_paddingBottom
737  * @attr ref android.R.styleable#View_paddingLeft
738  * @attr ref android.R.styleable#View_paddingRight
739  * @attr ref android.R.styleable#View_paddingTop
740  * @attr ref android.R.styleable#View_paddingStart
741  * @attr ref android.R.styleable#View_paddingEnd
742  * @attr ref android.R.styleable#View_saveEnabled
743  * @attr ref android.R.styleable#View_rotation
744  * @attr ref android.R.styleable#View_rotationX
745  * @attr ref android.R.styleable#View_rotationY
746  * @attr ref android.R.styleable#View_scaleX
747  * @attr ref android.R.styleable#View_scaleY
748  * @attr ref android.R.styleable#View_scrollX
749  * @attr ref android.R.styleable#View_scrollY
750  * @attr ref android.R.styleable#View_scrollbarSize
751  * @attr ref android.R.styleable#View_scrollbarStyle
752  * @attr ref android.R.styleable#View_scrollbars
753  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
754  * @attr ref android.R.styleable#View_scrollbarFadeDuration
755  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
756  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
757  * @attr ref android.R.styleable#View_scrollbarThumbVertical
758  * @attr ref android.R.styleable#View_scrollbarTrackVertical
759  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
760  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
761  * @attr ref android.R.styleable#View_stateListAnimator
762  * @attr ref android.R.styleable#View_transitionName
763  * @attr ref android.R.styleable#View_soundEffectsEnabled
764  * @attr ref android.R.styleable#View_tag
765  * @attr ref android.R.styleable#View_textAlignment
766  * @attr ref android.R.styleable#View_textDirection
767  * @attr ref android.R.styleable#View_transformPivotX
768  * @attr ref android.R.styleable#View_transformPivotY
769  * @attr ref android.R.styleable#View_translationX
770  * @attr ref android.R.styleable#View_translationY
771  * @attr ref android.R.styleable#View_translationZ
772  * @attr ref android.R.styleable#View_visibility
773  * @attr ref android.R.styleable#View_theme
774  *
775  * @see android.view.ViewGroup
776  */
777 @UiThread
778 public class View implements Drawable.Callback, KeyEvent.Callback,
779         AccessibilityEventSource {
780     private static final boolean DBG = false;
781 
782     /** @hide */
783     public static boolean DEBUG_DRAW = false;
784 
785     /**
786      * The logging tag used by this class with android.util.Log.
787      */
788     protected static final String VIEW_LOG_TAG = "View";
789 
790     /**
791      * When set to true, apps will draw debugging information about their layouts.
792      *
793      * @hide
794      */
795     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
796 
797     /**
798      * When set to true, this view will save its attribute data.
799      *
800      * @hide
801      */
802     public static boolean mDebugViewAttributes = false;
803 
804     /**
805      * Used to mark a View that has no ID.
806      */
807     public static final int NO_ID = -1;
808 
809     /**
810      * Last ID that is given to Views that are no part of activities.
811      *
812      * {@hide}
813      */
814     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
815 
816     /**
817      * Attribute to find the autofilled highlight
818      *
819      * @see #getAutofilledDrawable()
820      */
821     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
822             new int[]{android.R.attr.autofilledHighlight};
823 
824     /**
825      * Signals that compatibility booleans have been initialized according to
826      * target SDK versions.
827      */
828     private static boolean sCompatibilityDone = false;
829 
830     /**
831      * Use the old (broken) way of building MeasureSpecs.
832      */
833     private static boolean sUseBrokenMakeMeasureSpec = false;
834 
835     /**
836      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
837      */
838     static boolean sUseZeroUnspecifiedMeasureSpec = false;
839 
840     /**
841      * Ignore any optimizations using the measure cache.
842      */
843     private static boolean sIgnoreMeasureCache = false;
844 
845     /**
846      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
847      */
848     private static boolean sAlwaysRemeasureExactly = false;
849 
850     /**
851      * Relax constraints around whether setLayoutParams() must be called after
852      * modifying the layout params.
853      */
854     private static boolean sLayoutParamsAlwaysChanged = false;
855 
856     /**
857      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
858      * without throwing
859      */
860     static boolean sTextureViewIgnoresDrawableSetters = false;
861 
862     /**
863      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
864      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
865      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
866      * check is implemented for backwards compatibility.
867      *
868      * {@hide}
869      */
870     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
871 
872     /**
873      * Prior to N, when drag enters into child of a view that has already received an
874      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
875      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
876      * false from its event handler for these events.
877      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
878      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
879      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
880      */
881     static boolean sCascadedDragDrop;
882 
883     /**
884      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
885      * to determine things like whether or not to permit item click events. We can't break
886      * apps that do this just because more things (clickable things) are now auto-focusable
887      * and they would get different results, so give old behavior to old apps.
888      */
889     static boolean sHasFocusableExcludeAutoFocusable;
890 
891     /**
892      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
893      * made focusable by default. As a result, apps could (incorrectly) change the clickable
894      * setting of views off the UI thread. Now that clickable can effect the focusable state,
895      * changing the clickable attribute off the UI thread will cause an exception (since changing
896      * the focusable state checks). In order to prevent apps from crashing, we will handle this
897      * specific case and just not notify parents on new focusables resulting from marking views
898      * clickable from outside the UI thread.
899      */
900     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
901 
902     /**
903      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
904      * Float.NaN. If the app is targetting P or later then passing these values will result in an
905      * exception being thrown. If the app is targetting an earlier SDK version, then we will
906      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
907      * these bogus values.
908      */
909     private static boolean sThrowOnInvalidFloatProperties;
910 
911     /**
912      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
913      * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface
914      * instead.
915      */
916     private static boolean sAcceptZeroSizeDragShadow;
917 
918     /** @hide */
919     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
920     @Retention(RetentionPolicy.SOURCE)
921     public @interface Focusable {}
922 
923     /**
924      * This view does not want keystrokes.
925      * <p>
926      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
927      * android:focusable}.
928      */
929     public static final int NOT_FOCUSABLE = 0x00000000;
930 
931     /**
932      * This view wants keystrokes.
933      * <p>
934      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
935      * android:focusable}.
936      */
937     public static final int FOCUSABLE = 0x00000001;
938 
939     /**
940      * This view determines focusability automatically. This is the default.
941      * <p>
942      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
943      * android:focusable}.
944      */
945     public static final int FOCUSABLE_AUTO = 0x00000010;
946 
947     /**
948      * Mask for use with setFlags indicating bits used for focus.
949      */
950     private static final int FOCUSABLE_MASK = 0x00000011;
951 
952     /**
953      * This view will adjust its padding to fit sytem windows (e.g. status bar)
954      */
955     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
956 
957     /** @hide */
958     @IntDef({VISIBLE, INVISIBLE, GONE})
959     @Retention(RetentionPolicy.SOURCE)
960     public @interface Visibility {}
961 
962     /**
963      * This view is visible.
964      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
965      * android:visibility}.
966      */
967     public static final int VISIBLE = 0x00000000;
968 
969     /**
970      * This view is invisible, but it still takes up space for layout purposes.
971      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
972      * android:visibility}.
973      */
974     public static final int INVISIBLE = 0x00000004;
975 
976     /**
977      * This view is invisible, and it doesn't take any space for layout
978      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
979      * android:visibility}.
980      */
981     public static final int GONE = 0x00000008;
982 
983     /**
984      * Mask for use with setFlags indicating bits used for visibility.
985      * {@hide}
986      */
987     static final int VISIBILITY_MASK = 0x0000000C;
988 
989     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
990 
991     /**
992      * Hint indicating that this view can be autofilled with an email address.
993      *
994      * <p>Can be used with either {@link #setAutofillHints(String[])} or
995      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
996      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
997      *
998      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
999      */
1000     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1001 
1002     /**
1003      * Hint indicating that this view can be autofilled with a user's real name.
1004      *
1005      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1006      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1007      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1008      *
1009      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1010      */
1011     public static final String AUTOFILL_HINT_NAME = "name";
1012 
1013     /**
1014      * Hint indicating that this view can be autofilled with a username.
1015      *
1016      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1017      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1018      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1019      *
1020      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1021      */
1022     public static final String AUTOFILL_HINT_USERNAME = "username";
1023 
1024     /**
1025      * Hint indicating that this view can be autofilled with a password.
1026      *
1027      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1028      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1029      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1030      *
1031      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1032      */
1033     public static final String AUTOFILL_HINT_PASSWORD = "password";
1034 
1035     /**
1036      * Hint indicating that this view can be autofilled with a phone number.
1037      *
1038      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1039      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1040      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1041      *
1042      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1043      */
1044     public static final String AUTOFILL_HINT_PHONE = "phone";
1045 
1046     /**
1047      * Hint indicating that this view can be autofilled with a postal address.
1048      *
1049      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1050      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1051      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1052      *
1053      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1054      */
1055     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1056 
1057     /**
1058      * Hint indicating that this view can be autofilled with a postal code.
1059      *
1060      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1061      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1062      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1063      *
1064      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1065      */
1066     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1067 
1068     /**
1069      * Hint indicating that this view can be autofilled with a credit card number.
1070      *
1071      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1072      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1073      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1074      *
1075      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1076      */
1077     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1078 
1079     /**
1080      * Hint indicating that this view can be autofilled with a credit card security code.
1081      *
1082      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1083      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1084      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1085      *
1086      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1087      */
1088     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1089 
1090     /**
1091      * Hint indicating that this view can be autofilled with a credit card expiration date.
1092      *
1093      * <p>It should be used when the credit card expiration date is represented by just one view;
1094      * if it is represented by more than one (for example, one view for the month and another view
1095      * for the year), then each of these views should use the hint specific for the unit
1096      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1097      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1098      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1099      *
1100      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1101      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1102      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1103      *
1104      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1105      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1106      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1107      * the following options:
1108      *
1109      * <ul>
1110      *   <li>{@code "04/2020"}
1111      *   <li>{@code "4/2020"}
1112      *   <li>{@code "2020/04"}
1113      *   <li>{@code "2020/4"}
1114      *   <li>{@code "April/2020"}
1115      *   <li>{@code "Apr/2020"}
1116      * </ul>
1117      *
1118      * <p>You define a date autofill value for the view by overriding the following methods:
1119      *
1120      * <ol>
1121      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1122      *   <li>{@link #getAutofillValue()} to return a
1123      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1124      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1125      * </ol>
1126      *
1127      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1128      */
1129     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1130             "creditCardExpirationDate";
1131 
1132     /**
1133      * Hint indicating that this view can be autofilled with a credit card expiration month.
1134      *
1135      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1136      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1137      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1138      *
1139      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1140      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1141      * ambiguity when the autofill service provides a value for it. To understand why a
1142      * value can be ambiguous, consider "January", which could be represented as either of
1143      *
1144      * <ul>
1145      *   <li>{@code "1"}: recommended way.
1146      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1147      *   <li>{@code "January"}: full name, in English.
1148      *   <li>{@code "jan"}: abbreviated name, in English.
1149      *   <li>{@code "Janeiro"}: full name, in another language.
1150      * </ul>
1151      *
1152      * <p>Another recommended approach is to use a date autofill value - see
1153      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1154      *
1155      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1156      */
1157     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1158             "creditCardExpirationMonth";
1159 
1160     /**
1161      * Hint indicating that this view can be autofilled with a credit card expiration year.
1162      *
1163      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1164      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1165      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1166      *
1167      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1168      */
1169     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1170             "creditCardExpirationYear";
1171 
1172     /**
1173      * Hint indicating that this view can be autofilled with a credit card expiration day.
1174      *
1175      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1176      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1177      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1178      *
1179      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1180      */
1181     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1182 
1183     /**
1184      * Hints for the autofill services that describes the content of the view.
1185      */
1186     private @Nullable String[] mAutofillHints;
1187 
1188     /**
1189      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1190      */
1191     private AutofillId mAutofillId;
1192 
1193     /** @hide */
1194     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1195             AUTOFILL_TYPE_NONE,
1196             AUTOFILL_TYPE_TEXT,
1197             AUTOFILL_TYPE_TOGGLE,
1198             AUTOFILL_TYPE_LIST,
1199             AUTOFILL_TYPE_DATE
1200     })
1201     @Retention(RetentionPolicy.SOURCE)
1202     public @interface AutofillType {}
1203 
1204     /**
1205      * Autofill type for views that cannot be autofilled.
1206      *
1207      * <p>Typically used when the view is read-only; for example, a text label.
1208      *
1209      * @see #getAutofillType()
1210      */
1211     public static final int AUTOFILL_TYPE_NONE = 0;
1212 
1213     /**
1214      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1215      *
1216      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1217      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1218      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1219      *
1220      * @see #getAutofillType()
1221      */
1222     public static final int AUTOFILL_TYPE_TEXT = 1;
1223 
1224     /**
1225      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1226      *
1227      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1228      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1229      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1230      *
1231      * @see #getAutofillType()
1232      */
1233     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1234 
1235     /**
1236      * Autofill type for a selection list field, which is filled by an {@code int}
1237      * representing the element index inside the list (starting at {@code 0}).
1238      *
1239      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1240      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1241      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1242      *
1243      * <p>The available options in the selection list are typically provided by
1244      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1245      *
1246      * @see #getAutofillType()
1247      */
1248     public static final int AUTOFILL_TYPE_LIST = 3;
1249 
1250 
1251     /**
1252      * Autofill type for a field that contains a date, which is represented by a long representing
1253      * the number of milliseconds since the standard base time known as "the epoch", namely
1254      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1255      *
1256      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1257      * {@link AutofillValue#forDate(long)}, and the values passed to
1258      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1259      *
1260      * @see #getAutofillType()
1261      */
1262     public static final int AUTOFILL_TYPE_DATE = 4;
1263 
1264     /** @hide */
1265     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1266             IMPORTANT_FOR_AUTOFILL_AUTO,
1267             IMPORTANT_FOR_AUTOFILL_YES,
1268             IMPORTANT_FOR_AUTOFILL_NO,
1269             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1270             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1271     })
1272     @Retention(RetentionPolicy.SOURCE)
1273     public @interface AutofillImportance {}
1274 
1275     /**
1276      * Automatically determine whether a view is important for autofill.
1277      *
1278      * @see #isImportantForAutofill()
1279      * @see #setImportantForAutofill(int)
1280      */
1281     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1282 
1283     /**
1284      * The view is important for autofill, and its children (if any) will be traversed.
1285      *
1286      * @see #isImportantForAutofill()
1287      * @see #setImportantForAutofill(int)
1288      */
1289     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1290 
1291     /**
1292      * The view is not important for autofill, but its children (if any) will be traversed.
1293      *
1294      * @see #isImportantForAutofill()
1295      * @see #setImportantForAutofill(int)
1296      */
1297     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1298 
1299     /**
1300      * The view is important for autofill, but its children (if any) will not be traversed.
1301      *
1302      * @see #isImportantForAutofill()
1303      * @see #setImportantForAutofill(int)
1304      */
1305     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1306 
1307     /**
1308      * The view is not important for autofill, and its children (if any) will not be traversed.
1309      *
1310      * @see #isImportantForAutofill()
1311      * @see #setImportantForAutofill(int)
1312      */
1313     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1314 
1315     /** @hide */
1316     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1317             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1318     })
1319     @Retention(RetentionPolicy.SOURCE)
1320     public @interface AutofillFlags {}
1321 
1322     /**
1323      * Flag requesting you to add views that are marked as not important for autofill
1324      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1325      */
1326     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1327 
1328     /**
1329      * This view is enabled. Interpretation varies by subclass.
1330      * Use with ENABLED_MASK when calling setFlags.
1331      * {@hide}
1332      */
1333     static final int ENABLED = 0x00000000;
1334 
1335     /**
1336      * This view is disabled. Interpretation varies by subclass.
1337      * Use with ENABLED_MASK when calling setFlags.
1338      * {@hide}
1339      */
1340     static final int DISABLED = 0x00000020;
1341 
1342    /**
1343     * Mask for use with setFlags indicating bits used for indicating whether
1344     * this view is enabled
1345     * {@hide}
1346     */
1347     static final int ENABLED_MASK = 0x00000020;
1348 
1349     /**
1350      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1351      * called and further optimizations will be performed. It is okay to have
1352      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1353      * {@hide}
1354      */
1355     static final int WILL_NOT_DRAW = 0x00000080;
1356 
1357     /**
1358      * Mask for use with setFlags indicating bits used for indicating whether
1359      * this view is will draw
1360      * {@hide}
1361      */
1362     static final int DRAW_MASK = 0x00000080;
1363 
1364     /**
1365      * <p>This view doesn't show scrollbars.</p>
1366      * {@hide}
1367      */
1368     static final int SCROLLBARS_NONE = 0x00000000;
1369 
1370     /**
1371      * <p>This view shows horizontal scrollbars.</p>
1372      * {@hide}
1373      */
1374     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1375 
1376     /**
1377      * <p>This view shows vertical scrollbars.</p>
1378      * {@hide}
1379      */
1380     static final int SCROLLBARS_VERTICAL = 0x00000200;
1381 
1382     /**
1383      * <p>Mask for use with setFlags indicating bits used for indicating which
1384      * scrollbars are enabled.</p>
1385      * {@hide}
1386      */
1387     static final int SCROLLBARS_MASK = 0x00000300;
1388 
1389     /**
1390      * Indicates that the view should filter touches when its window is obscured.
1391      * Refer to the class comments for more information about this security feature.
1392      * {@hide}
1393      */
1394     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1395 
1396     /**
1397      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1398      * that they are optional and should be skipped if the window has
1399      * requested system UI flags that ignore those insets for layout.
1400      */
1401     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1402 
1403     /**
1404      * <p>This view doesn't show fading edges.</p>
1405      * {@hide}
1406      */
1407     static final int FADING_EDGE_NONE = 0x00000000;
1408 
1409     /**
1410      * <p>This view shows horizontal fading edges.</p>
1411      * {@hide}
1412      */
1413     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1414 
1415     /**
1416      * <p>This view shows vertical fading edges.</p>
1417      * {@hide}
1418      */
1419     static final int FADING_EDGE_VERTICAL = 0x00002000;
1420 
1421     /**
1422      * <p>Mask for use with setFlags indicating bits used for indicating which
1423      * fading edges are enabled.</p>
1424      * {@hide}
1425      */
1426     static final int FADING_EDGE_MASK = 0x00003000;
1427 
1428     /**
1429      * <p>Indicates this view can be clicked. When clickable, a View reacts
1430      * to clicks by notifying the OnClickListener.<p>
1431      * {@hide}
1432      */
1433     static final int CLICKABLE = 0x00004000;
1434 
1435     /**
1436      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1437      * {@hide}
1438      */
1439     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1440 
1441     /**
1442      * <p>Indicates that no icicle should be saved for this view.<p>
1443      * {@hide}
1444      */
1445     static final int SAVE_DISABLED = 0x000010000;
1446 
1447     /**
1448      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1449      * property.</p>
1450      * {@hide}
1451      */
1452     static final int SAVE_DISABLED_MASK = 0x000010000;
1453 
1454     /**
1455      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1456      * {@hide}
1457      */
1458     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1459 
1460     /**
1461      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1462      * {@hide}
1463      */
1464     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1465 
1466     /** @hide */
1467     @Retention(RetentionPolicy.SOURCE)
1468     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1469             DRAWING_CACHE_QUALITY_LOW,
1470             DRAWING_CACHE_QUALITY_HIGH,
1471             DRAWING_CACHE_QUALITY_AUTO
1472     })
1473     public @interface DrawingCacheQuality {}
1474 
1475     /**
1476      * <p>Enables low quality mode for the drawing cache.</p>
1477      *
1478      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1479      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1480      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1481      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1482      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1483      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1484      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1485      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1486      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1487      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1488      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1489      * reports or unit testing the {@link PixelCopy} API is recommended.
1490      */
1491     @Deprecated
1492     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1493 
1494     /**
1495      * <p>Enables high quality mode for the drawing cache.</p>
1496      *
1497      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1498      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1499      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1500      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1501      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1502      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1503      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1504      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1505      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1506      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1507      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1508      * reports or unit testing the {@link PixelCopy} API is recommended.
1509      */
1510     @Deprecated
1511     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1512 
1513     /**
1514      * <p>Enables automatic quality mode for the drawing cache.</p>
1515      *
1516      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1517      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1518      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1519      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1520      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1521      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1522      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1523      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1524      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1525      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1526      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1527      * reports or unit testing the {@link PixelCopy} API is recommended.
1528      */
1529     @Deprecated
1530     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1531 
1532     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1533             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1534     };
1535 
1536     /**
1537      * <p>Mask for use with setFlags indicating bits used for the cache
1538      * quality property.</p>
1539      * {@hide}
1540      */
1541     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1542 
1543     /**
1544      * <p>
1545      * Indicates this view can be long clicked. When long clickable, a View
1546      * reacts to long clicks by notifying the OnLongClickListener or showing a
1547      * context menu.
1548      * </p>
1549      * {@hide}
1550      */
1551     static final int LONG_CLICKABLE = 0x00200000;
1552 
1553     /**
1554      * <p>Indicates that this view gets its drawable states from its direct parent
1555      * and ignores its original internal states.</p>
1556      *
1557      * @hide
1558      */
1559     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1560 
1561     /**
1562      * <p>
1563      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1564      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1565      * OnContextClickListener.
1566      * </p>
1567      * {@hide}
1568      */
1569     static final int CONTEXT_CLICKABLE = 0x00800000;
1570 
1571     /** @hide */
1572     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1573             SCROLLBARS_INSIDE_OVERLAY,
1574             SCROLLBARS_INSIDE_INSET,
1575             SCROLLBARS_OUTSIDE_OVERLAY,
1576             SCROLLBARS_OUTSIDE_INSET
1577     })
1578     @Retention(RetentionPolicy.SOURCE)
1579     public @interface ScrollBarStyle {}
1580 
1581     /**
1582      * The scrollbar style to display the scrollbars inside the content area,
1583      * without increasing the padding. The scrollbars will be overlaid with
1584      * translucency on the view's content.
1585      */
1586     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1587 
1588     /**
1589      * The scrollbar style to display the scrollbars inside the padded area,
1590      * increasing the padding of the view. The scrollbars will not overlap the
1591      * content area of the view.
1592      */
1593     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1594 
1595     /**
1596      * The scrollbar style to display the scrollbars at the edge of the view,
1597      * without increasing the padding. The scrollbars will be overlaid with
1598      * translucency.
1599      */
1600     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1601 
1602     /**
1603      * The scrollbar style to display the scrollbars at the edge of the view,
1604      * increasing the padding of the view. The scrollbars will only overlap the
1605      * background, if any.
1606      */
1607     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1608 
1609     /**
1610      * Mask to check if the scrollbar style is overlay or inset.
1611      * {@hide}
1612      */
1613     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1614 
1615     /**
1616      * Mask to check if the scrollbar style is inside or outside.
1617      * {@hide}
1618      */
1619     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1620 
1621     /**
1622      * Mask for scrollbar style.
1623      * {@hide}
1624      */
1625     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1626 
1627     /**
1628      * View flag indicating that the screen should remain on while the
1629      * window containing this view is visible to the user.  This effectively
1630      * takes care of automatically setting the WindowManager's
1631      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1632      */
1633     public static final int KEEP_SCREEN_ON = 0x04000000;
1634 
1635     /**
1636      * View flag indicating whether this view should have sound effects enabled
1637      * for events such as clicking and touching.
1638      */
1639     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1640 
1641     /**
1642      * View flag indicating whether this view should have haptic feedback
1643      * enabled for events such as long presses.
1644      */
1645     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1646 
1647     /**
1648      * <p>Indicates that the view hierarchy should stop saving state when
1649      * it reaches this view.  If state saving is initiated immediately at
1650      * the view, it will be allowed.
1651      * {@hide}
1652      */
1653     static final int PARENT_SAVE_DISABLED = 0x20000000;
1654 
1655     /**
1656      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1657      * {@hide}
1658      */
1659     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1660 
1661     private static Paint sDebugPaint;
1662 
1663     /**
1664      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1665      * {@hide}
1666      */
1667     static final int TOOLTIP = 0x40000000;
1668 
1669     /** @hide */
1670     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
1671             FOCUSABLES_ALL,
1672             FOCUSABLES_TOUCH_MODE
1673     })
1674     @Retention(RetentionPolicy.SOURCE)
1675     public @interface FocusableMode {}
1676 
1677     /**
1678      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1679      * should add all focusable Views regardless if they are focusable in touch mode.
1680      */
1681     public static final int FOCUSABLES_ALL = 0x00000000;
1682 
1683     /**
1684      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1685      * should add only Views focusable in touch mode.
1686      */
1687     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1688 
1689     /** @hide */
1690     @IntDef(prefix = { "FOCUS_" }, value = {
1691             FOCUS_BACKWARD,
1692             FOCUS_FORWARD,
1693             FOCUS_LEFT,
1694             FOCUS_UP,
1695             FOCUS_RIGHT,
1696             FOCUS_DOWN
1697     })
1698     @Retention(RetentionPolicy.SOURCE)
1699     public @interface FocusDirection {}
1700 
1701     /** @hide */
1702     @IntDef(prefix = { "FOCUS_" }, value = {
1703             FOCUS_LEFT,
1704             FOCUS_UP,
1705             FOCUS_RIGHT,
1706             FOCUS_DOWN
1707     })
1708     @Retention(RetentionPolicy.SOURCE)
1709     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1710 
1711     /**
1712      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1713      * item.
1714      */
1715     public static final int FOCUS_BACKWARD = 0x00000001;
1716 
1717     /**
1718      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1719      * item.
1720      */
1721     public static final int FOCUS_FORWARD = 0x00000002;
1722 
1723     /**
1724      * Use with {@link #focusSearch(int)}. Move focus to the left.
1725      */
1726     public static final int FOCUS_LEFT = 0x00000011;
1727 
1728     /**
1729      * Use with {@link #focusSearch(int)}. Move focus up.
1730      */
1731     public static final int FOCUS_UP = 0x00000021;
1732 
1733     /**
1734      * Use with {@link #focusSearch(int)}. Move focus to the right.
1735      */
1736     public static final int FOCUS_RIGHT = 0x00000042;
1737 
1738     /**
1739      * Use with {@link #focusSearch(int)}. Move focus down.
1740      */
1741     public static final int FOCUS_DOWN = 0x00000082;
1742 
1743     /**
1744      * Bits of {@link #getMeasuredWidthAndState()} and
1745      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1746      */
1747     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1748 
1749     /**
1750      * Bits of {@link #getMeasuredWidthAndState()} and
1751      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1752      */
1753     public static final int MEASURED_STATE_MASK = 0xff000000;
1754 
1755     /**
1756      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1757      * for functions that combine both width and height into a single int,
1758      * such as {@link #getMeasuredState()} and the childState argument of
1759      * {@link #resolveSizeAndState(int, int, int)}.
1760      */
1761     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1762 
1763     /**
1764      * Bit of {@link #getMeasuredWidthAndState()} and
1765      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1766      * is smaller that the space the view would like to have.
1767      */
1768     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1769 
1770     /**
1771      * Base View state sets
1772      */
1773     // Singles
1774     /**
1775      * Indicates the view has no states set. States are used with
1776      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1777      * view depending on its state.
1778      *
1779      * @see android.graphics.drawable.Drawable
1780      * @see #getDrawableState()
1781      */
1782     protected static final int[] EMPTY_STATE_SET;
1783     /**
1784      * Indicates the view is enabled. States are used with
1785      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1786      * view depending on its state.
1787      *
1788      * @see android.graphics.drawable.Drawable
1789      * @see #getDrawableState()
1790      */
1791     protected static final int[] ENABLED_STATE_SET;
1792     /**
1793      * Indicates the view is focused. States are used with
1794      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1795      * view depending on its state.
1796      *
1797      * @see android.graphics.drawable.Drawable
1798      * @see #getDrawableState()
1799      */
1800     protected static final int[] FOCUSED_STATE_SET;
1801     /**
1802      * Indicates the view is selected. States are used with
1803      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1804      * view depending on its state.
1805      *
1806      * @see android.graphics.drawable.Drawable
1807      * @see #getDrawableState()
1808      */
1809     protected static final int[] SELECTED_STATE_SET;
1810     /**
1811      * Indicates the view is pressed. States are used with
1812      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1813      * view depending on its state.
1814      *
1815      * @see android.graphics.drawable.Drawable
1816      * @see #getDrawableState()
1817      */
1818     protected static final int[] PRESSED_STATE_SET;
1819     /**
1820      * Indicates the view's window has focus. States are used with
1821      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1822      * view depending on its state.
1823      *
1824      * @see android.graphics.drawable.Drawable
1825      * @see #getDrawableState()
1826      */
1827     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1828     // Doubles
1829     /**
1830      * Indicates the view is enabled and has the focus.
1831      *
1832      * @see #ENABLED_STATE_SET
1833      * @see #FOCUSED_STATE_SET
1834      */
1835     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1836     /**
1837      * Indicates the view is enabled and selected.
1838      *
1839      * @see #ENABLED_STATE_SET
1840      * @see #SELECTED_STATE_SET
1841      */
1842     protected static final int[] ENABLED_SELECTED_STATE_SET;
1843     /**
1844      * Indicates the view is enabled and that its window has focus.
1845      *
1846      * @see #ENABLED_STATE_SET
1847      * @see #WINDOW_FOCUSED_STATE_SET
1848      */
1849     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1850     /**
1851      * Indicates the view is focused and selected.
1852      *
1853      * @see #FOCUSED_STATE_SET
1854      * @see #SELECTED_STATE_SET
1855      */
1856     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1857     /**
1858      * Indicates the view has the focus and that its window has the focus.
1859      *
1860      * @see #FOCUSED_STATE_SET
1861      * @see #WINDOW_FOCUSED_STATE_SET
1862      */
1863     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1864     /**
1865      * Indicates the view is selected and that its window has the focus.
1866      *
1867      * @see #SELECTED_STATE_SET
1868      * @see #WINDOW_FOCUSED_STATE_SET
1869      */
1870     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1871     // Triples
1872     /**
1873      * Indicates the view is enabled, focused and selected.
1874      *
1875      * @see #ENABLED_STATE_SET
1876      * @see #FOCUSED_STATE_SET
1877      * @see #SELECTED_STATE_SET
1878      */
1879     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1880     /**
1881      * Indicates the view is enabled, focused and its window has the focus.
1882      *
1883      * @see #ENABLED_STATE_SET
1884      * @see #FOCUSED_STATE_SET
1885      * @see #WINDOW_FOCUSED_STATE_SET
1886      */
1887     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1888     /**
1889      * Indicates the view is enabled, selected and its window has the focus.
1890      *
1891      * @see #ENABLED_STATE_SET
1892      * @see #SELECTED_STATE_SET
1893      * @see #WINDOW_FOCUSED_STATE_SET
1894      */
1895     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1896     /**
1897      * Indicates the view is focused, selected and its window has the focus.
1898      *
1899      * @see #FOCUSED_STATE_SET
1900      * @see #SELECTED_STATE_SET
1901      * @see #WINDOW_FOCUSED_STATE_SET
1902      */
1903     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1904     /**
1905      * Indicates the view is enabled, focused, selected and its window
1906      * has the focus.
1907      *
1908      * @see #ENABLED_STATE_SET
1909      * @see #FOCUSED_STATE_SET
1910      * @see #SELECTED_STATE_SET
1911      * @see #WINDOW_FOCUSED_STATE_SET
1912      */
1913     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1914     /**
1915      * Indicates the view is pressed and its window has the focus.
1916      *
1917      * @see #PRESSED_STATE_SET
1918      * @see #WINDOW_FOCUSED_STATE_SET
1919      */
1920     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1921     /**
1922      * Indicates the view is pressed and selected.
1923      *
1924      * @see #PRESSED_STATE_SET
1925      * @see #SELECTED_STATE_SET
1926      */
1927     protected static final int[] PRESSED_SELECTED_STATE_SET;
1928     /**
1929      * Indicates the view is pressed, selected and its window has the focus.
1930      *
1931      * @see #PRESSED_STATE_SET
1932      * @see #SELECTED_STATE_SET
1933      * @see #WINDOW_FOCUSED_STATE_SET
1934      */
1935     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1936     /**
1937      * Indicates the view is pressed and focused.
1938      *
1939      * @see #PRESSED_STATE_SET
1940      * @see #FOCUSED_STATE_SET
1941      */
1942     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1943     /**
1944      * Indicates the view is pressed, focused and its window has the focus.
1945      *
1946      * @see #PRESSED_STATE_SET
1947      * @see #FOCUSED_STATE_SET
1948      * @see #WINDOW_FOCUSED_STATE_SET
1949      */
1950     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1951     /**
1952      * Indicates the view is pressed, focused and selected.
1953      *
1954      * @see #PRESSED_STATE_SET
1955      * @see #SELECTED_STATE_SET
1956      * @see #FOCUSED_STATE_SET
1957      */
1958     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1959     /**
1960      * Indicates the view is pressed, focused, selected and its window has the focus.
1961      *
1962      * @see #PRESSED_STATE_SET
1963      * @see #FOCUSED_STATE_SET
1964      * @see #SELECTED_STATE_SET
1965      * @see #WINDOW_FOCUSED_STATE_SET
1966      */
1967     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1968     /**
1969      * Indicates the view is pressed and enabled.
1970      *
1971      * @see #PRESSED_STATE_SET
1972      * @see #ENABLED_STATE_SET
1973      */
1974     protected static final int[] PRESSED_ENABLED_STATE_SET;
1975     /**
1976      * Indicates the view is pressed, enabled and its window has the focus.
1977      *
1978      * @see #PRESSED_STATE_SET
1979      * @see #ENABLED_STATE_SET
1980      * @see #WINDOW_FOCUSED_STATE_SET
1981      */
1982     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1983     /**
1984      * Indicates the view is pressed, enabled and selected.
1985      *
1986      * @see #PRESSED_STATE_SET
1987      * @see #ENABLED_STATE_SET
1988      * @see #SELECTED_STATE_SET
1989      */
1990     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1991     /**
1992      * Indicates the view is pressed, enabled, selected and its window has the
1993      * focus.
1994      *
1995      * @see #PRESSED_STATE_SET
1996      * @see #ENABLED_STATE_SET
1997      * @see #SELECTED_STATE_SET
1998      * @see #WINDOW_FOCUSED_STATE_SET
1999      */
2000     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2001     /**
2002      * Indicates the view is pressed, enabled and focused.
2003      *
2004      * @see #PRESSED_STATE_SET
2005      * @see #ENABLED_STATE_SET
2006      * @see #FOCUSED_STATE_SET
2007      */
2008     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2009     /**
2010      * Indicates the view is pressed, enabled, focused and its window has the
2011      * focus.
2012      *
2013      * @see #PRESSED_STATE_SET
2014      * @see #ENABLED_STATE_SET
2015      * @see #FOCUSED_STATE_SET
2016      * @see #WINDOW_FOCUSED_STATE_SET
2017      */
2018     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2019     /**
2020      * Indicates the view is pressed, enabled, focused and selected.
2021      *
2022      * @see #PRESSED_STATE_SET
2023      * @see #ENABLED_STATE_SET
2024      * @see #SELECTED_STATE_SET
2025      * @see #FOCUSED_STATE_SET
2026      */
2027     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2028     /**
2029      * Indicates the view is pressed, enabled, focused, selected and its window
2030      * has the focus.
2031      *
2032      * @see #PRESSED_STATE_SET
2033      * @see #ENABLED_STATE_SET
2034      * @see #SELECTED_STATE_SET
2035      * @see #FOCUSED_STATE_SET
2036      * @see #WINDOW_FOCUSED_STATE_SET
2037      */
2038     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2039 
2040     static {
2041         EMPTY_STATE_SET = StateSet.get(0);
2042 
2043         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2044 
2045         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2046         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2047                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2048 
2049         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2050         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2051                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2052         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2053                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2054         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2055                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2056                         | StateSet.VIEW_STATE_FOCUSED);
2057 
2058         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2059         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2060                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2061         ENABLED_SELECTED_STATE_SET = StateSet.get(
2062                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2063         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2064                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2065                         | StateSet.VIEW_STATE_ENABLED);
2066         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2067                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2068         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2069                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2070                         | StateSet.VIEW_STATE_ENABLED);
2071         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2072                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2073                         | StateSet.VIEW_STATE_ENABLED);
2074         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2075                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2076                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2077 
2078         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2079         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2080                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2081         PRESSED_SELECTED_STATE_SET = StateSet.get(
2082                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2083         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2084                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2085                         | StateSet.VIEW_STATE_PRESSED);
2086         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2087                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2088         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2089                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2090                         | StateSet.VIEW_STATE_PRESSED);
2091         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2092                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2093                         | StateSet.VIEW_STATE_PRESSED);
2094         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2095                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2096                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2097         PRESSED_ENABLED_STATE_SET = StateSet.get(
2098                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2099         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2100                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2101                         | StateSet.VIEW_STATE_PRESSED);
2102         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2103                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2104                         | StateSet.VIEW_STATE_PRESSED);
2105         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2106                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2107                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2108         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2109                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2110                         | StateSet.VIEW_STATE_PRESSED);
2111         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2112                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2113                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2114         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2115                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2116                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2117         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2118                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2119                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2120                         | StateSet.VIEW_STATE_PRESSED);
2121     }
2122 
2123     /**
2124      * Accessibility event types that are dispatched for text population.
2125      */
2126     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2127             AccessibilityEvent.TYPE_VIEW_CLICKED
2128             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2129             | AccessibilityEvent.TYPE_VIEW_SELECTED
2130             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2131             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2132             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2133             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2134             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2135             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2136             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2137             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2138 
2139     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2140 
2141     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2142 
2143     /**
2144      * Temporary Rect currently for use in setBackground().  This will probably
2145      * be extended in the future to hold our own class with more than just
2146      * a Rect. :)
2147      */
2148     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2149 
2150     /**
2151      * Map used to store views' tags.
2152      */
2153     private SparseArray<Object> mKeyedTags;
2154 
2155     /**
2156      * The next available accessibility id.
2157      */
2158     private static int sNextAccessibilityViewId;
2159 
2160     /**
2161      * The animation currently associated with this view.
2162      * @hide
2163      */
2164     protected Animation mCurrentAnimation = null;
2165 
2166     /**
2167      * Width as measured during measure pass.
2168      * {@hide}
2169      */
2170     @ViewDebug.ExportedProperty(category = "measurement")
2171     int mMeasuredWidth;
2172 
2173     /**
2174      * Height as measured during measure pass.
2175      * {@hide}
2176      */
2177     @ViewDebug.ExportedProperty(category = "measurement")
2178     int mMeasuredHeight;
2179 
2180     /**
2181      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2182      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2183      * its display list. This flag, used only when hw accelerated, allows us to clear the
2184      * flag while retaining this information until it's needed (at getDisplayList() time and
2185      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2186      *
2187      * {@hide}
2188      */
2189     boolean mRecreateDisplayList = false;
2190 
2191     /**
2192      * The view's identifier.
2193      * {@hide}
2194      *
2195      * @see #setId(int)
2196      * @see #getId()
2197      */
2198     @IdRes
2199     @ViewDebug.ExportedProperty(resolveId = true)
2200     int mID = NO_ID;
2201 
2202     /** The ID of this view for autofill purposes.
2203      * <ul>
2204      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2205      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2206      *                                                  unique in the process. This might change
2207      *                                                  over activity lifecycle events.
2208      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2209      *                                                  unique in the activity. This stays the same
2210      *                                                  over activity lifecycle events.
2211      */
2212     private int mAutofillViewId = NO_ID;
2213 
2214     // ID for accessibility purposes. This ID must be unique for every window
2215     private int mAccessibilityViewId = NO_ID;
2216 
2217     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2218 
2219     /**
2220      * The view's tag.
2221      * {@hide}
2222      *
2223      * @see #setTag(Object)
2224      * @see #getTag()
2225      */
2226     protected Object mTag = null;
2227 
2228     // for mPrivateFlags:
2229     /** {@hide} */
2230     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2231     /** {@hide} */
2232     static final int PFLAG_FOCUSED                     = 0x00000002;
2233     /** {@hide} */
2234     static final int PFLAG_SELECTED                    = 0x00000004;
2235     /** {@hide} */
2236     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2237     /** {@hide} */
2238     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2239     /** {@hide} */
2240     static final int PFLAG_DRAWN                       = 0x00000020;
2241     /**
2242      * When this flag is set, this view is running an animation on behalf of its
2243      * children and should therefore not cancel invalidate requests, even if they
2244      * lie outside of this view's bounds.
2245      *
2246      * {@hide}
2247      */
2248     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2249     /** {@hide} */
2250     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2251     /** {@hide} */
2252     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2253     /** {@hide} */
2254     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2255     /** {@hide} */
2256     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2257     /** {@hide} */
2258     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2259     /** {@hide} */
2260     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2261 
2262     private static final int PFLAG_PRESSED             = 0x00004000;
2263 
2264     /** {@hide} */
2265     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2266     /**
2267      * Flag used to indicate that this view should be drawn once more (and only once
2268      * more) after its animation has completed.
2269      * {@hide}
2270      */
2271     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2272 
2273     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2274 
2275     /**
2276      * Indicates that the View returned true when onSetAlpha() was called and that
2277      * the alpha must be restored.
2278      * {@hide}
2279      */
2280     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2281 
2282     /**
2283      * Set by {@link #setScrollContainer(boolean)}.
2284      */
2285     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2286 
2287     /**
2288      * Set by {@link #setScrollContainer(boolean)}.
2289      */
2290     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2291 
2292     /**
2293      * View flag indicating whether this view was invalidated (fully or partially.)
2294      *
2295      * @hide
2296      */
2297     static final int PFLAG_DIRTY                       = 0x00200000;
2298 
2299     /**
2300      * View flag indicating whether this view was invalidated by an opaque
2301      * invalidate request.
2302      *
2303      * @hide
2304      */
2305     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2306 
2307     /**
2308      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2309      *
2310      * @hide
2311      */
2312     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2313 
2314     /**
2315      * Indicates whether the background is opaque.
2316      *
2317      * @hide
2318      */
2319     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2320 
2321     /**
2322      * Indicates whether the scrollbars are opaque.
2323      *
2324      * @hide
2325      */
2326     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2327 
2328     /**
2329      * Indicates whether the view is opaque.
2330      *
2331      * @hide
2332      */
2333     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2334 
2335     /**
2336      * Indicates a prepressed state;
2337      * the short time between ACTION_DOWN and recognizing
2338      * a 'real' press. Prepressed is used to recognize quick taps
2339      * even when they are shorter than ViewConfiguration.getTapTimeout().
2340      *
2341      * @hide
2342      */
2343     private static final int PFLAG_PREPRESSED          = 0x02000000;
2344 
2345     /**
2346      * Indicates whether the view is temporarily detached.
2347      *
2348      * @hide
2349      */
2350     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2351 
2352     /**
2353      * Indicates that we should awaken scroll bars once attached
2354      *
2355      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2356      * during window attachment and it is no longer needed. Feel free to repurpose it.
2357      *
2358      * @hide
2359      */
2360     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2361 
2362     /**
2363      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2364      * @hide
2365      */
2366     private static final int PFLAG_HOVERED             = 0x10000000;
2367 
2368     /**
2369      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2370      */
2371     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2372 
2373     /** {@hide} */
2374     static final int PFLAG_ACTIVATED                   = 0x40000000;
2375 
2376     /**
2377      * Indicates that this view was specifically invalidated, not just dirtied because some
2378      * child view was invalidated. The flag is used to determine when we need to recreate
2379      * a view's display list (as opposed to just returning a reference to its existing
2380      * display list).
2381      *
2382      * @hide
2383      */
2384     static final int PFLAG_INVALIDATED                 = 0x80000000;
2385 
2386     /**
2387      * Masks for mPrivateFlags2, as generated by dumpFlags():
2388      *
2389      * |-------|-------|-------|-------|
2390      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2391      *                                1  PFLAG2_DRAG_HOVERED
2392      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2393      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2394      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2395      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2396      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2397      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2398      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2399      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2400      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2401      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2402      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2403      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2404      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2405      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2406      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2407      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2408      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2409      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2410      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2411      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2412      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2413      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2414      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2415      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2416      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2417      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2418      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2419      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2420      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2421      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2422      *    1                              PFLAG2_PADDING_RESOLVED
2423      *   1                               PFLAG2_DRAWABLE_RESOLVED
2424      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2425      * |-------|-------|-------|-------|
2426      */
2427 
2428     /**
2429      * Indicates that this view has reported that it can accept the current drag's content.
2430      * Cleared when the drag operation concludes.
2431      * @hide
2432      */
2433     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2434 
2435     /**
2436      * Indicates that this view is currently directly under the drag location in a
2437      * drag-and-drop operation involving content that it can accept.  Cleared when
2438      * the drag exits the view, or when the drag operation concludes.
2439      * @hide
2440      */
2441     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2442 
2443     /** @hide */
2444     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2445             LAYOUT_DIRECTION_LTR,
2446             LAYOUT_DIRECTION_RTL,
2447             LAYOUT_DIRECTION_INHERIT,
2448             LAYOUT_DIRECTION_LOCALE
2449     })
2450     @Retention(RetentionPolicy.SOURCE)
2451     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2452     public @interface LayoutDir {}
2453 
2454     /** @hide */
2455     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2456             LAYOUT_DIRECTION_LTR,
2457             LAYOUT_DIRECTION_RTL
2458     })
2459     @Retention(RetentionPolicy.SOURCE)
2460     public @interface ResolvedLayoutDir {}
2461 
2462     /**
2463      * A flag to indicate that the layout direction of this view has not been defined yet.
2464      * @hide
2465      */
2466     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2467 
2468     /**
2469      * Horizontal layout direction of this view is from Left to Right.
2470      * Use with {@link #setLayoutDirection}.
2471      */
2472     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2473 
2474     /**
2475      * Horizontal layout direction of this view is from Right to Left.
2476      * Use with {@link #setLayoutDirection}.
2477      */
2478     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2479 
2480     /**
2481      * Horizontal layout direction of this view is inherited from its parent.
2482      * Use with {@link #setLayoutDirection}.
2483      */
2484     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2485 
2486     /**
2487      * Horizontal layout direction of this view is from deduced from the default language
2488      * script for the locale. Use with {@link #setLayoutDirection}.
2489      */
2490     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2491 
2492     /**
2493      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2494      * @hide
2495      */
2496     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2497 
2498     /**
2499      * Mask for use with private flags indicating bits used for horizontal layout direction.
2500      * @hide
2501      */
2502     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2503 
2504     /**
2505      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2506      * right-to-left direction.
2507      * @hide
2508      */
2509     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2510 
2511     /**
2512      * Indicates whether the view horizontal layout direction has been resolved.
2513      * @hide
2514      */
2515     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2516 
2517     /**
2518      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2519      * @hide
2520      */
2521     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2522             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2523 
2524     /*
2525      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2526      * flag value.
2527      * @hide
2528      */
2529     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2530             LAYOUT_DIRECTION_LTR,
2531             LAYOUT_DIRECTION_RTL,
2532             LAYOUT_DIRECTION_INHERIT,
2533             LAYOUT_DIRECTION_LOCALE
2534     };
2535 
2536     /**
2537      * Default horizontal layout direction.
2538      */
2539     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2540 
2541     /**
2542      * Default horizontal layout direction.
2543      * @hide
2544      */
2545     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2546 
2547     /**
2548      * Text direction is inherited through {@link ViewGroup}
2549      */
2550     public static final int TEXT_DIRECTION_INHERIT = 0;
2551 
2552     /**
2553      * Text direction is using "first strong algorithm". The first strong directional character
2554      * determines the paragraph direction. If there is no strong directional character, the
2555      * paragraph direction is the view's resolved layout direction.
2556      */
2557     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2558 
2559     /**
2560      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2561      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2562      * If there are neither, the paragraph direction is the view's resolved layout direction.
2563      */
2564     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2565 
2566     /**
2567      * Text direction is forced to LTR.
2568      */
2569     public static final int TEXT_DIRECTION_LTR = 3;
2570 
2571     /**
2572      * Text direction is forced to RTL.
2573      */
2574     public static final int TEXT_DIRECTION_RTL = 4;
2575 
2576     /**
2577      * Text direction is coming from the system Locale.
2578      */
2579     public static final int TEXT_DIRECTION_LOCALE = 5;
2580 
2581     /**
2582      * Text direction is using "first strong algorithm". The first strong directional character
2583      * determines the paragraph direction. If there is no strong directional character, the
2584      * paragraph direction is LTR.
2585      */
2586     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2587 
2588     /**
2589      * Text direction is using "first strong algorithm". The first strong directional character
2590      * determines the paragraph direction. If there is no strong directional character, the
2591      * paragraph direction is RTL.
2592      */
2593     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2594 
2595     /**
2596      * Default text direction is inherited
2597      */
2598     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2599 
2600     /**
2601      * Default resolved text direction
2602      * @hide
2603      */
2604     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2605 
2606     /**
2607      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2608      * @hide
2609      */
2610     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2611 
2612     /**
2613      * Mask for use with private flags indicating bits used for text direction.
2614      * @hide
2615      */
2616     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2617             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2618 
2619     /**
2620      * Array of text direction flags for mapping attribute "textDirection" to correct
2621      * flag value.
2622      * @hide
2623      */
2624     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2625             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2626             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2627             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2628             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2629             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2630             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2631             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2632             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2633     };
2634 
2635     /**
2636      * Indicates whether the view text direction has been resolved.
2637      * @hide
2638      */
2639     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2640             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2641 
2642     /**
2643      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2644      * @hide
2645      */
2646     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2647 
2648     /**
2649      * Mask for use with private flags indicating bits used for resolved text direction.
2650      * @hide
2651      */
2652     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2653             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2654 
2655     /**
2656      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2657      * @hide
2658      */
2659     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2660             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2661 
2662     /** @hide */
2663     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
2664             TEXT_ALIGNMENT_INHERIT,
2665             TEXT_ALIGNMENT_GRAVITY,
2666             TEXT_ALIGNMENT_CENTER,
2667             TEXT_ALIGNMENT_TEXT_START,
2668             TEXT_ALIGNMENT_TEXT_END,
2669             TEXT_ALIGNMENT_VIEW_START,
2670             TEXT_ALIGNMENT_VIEW_END
2671     })
2672     @Retention(RetentionPolicy.SOURCE)
2673     public @interface TextAlignment {}
2674 
2675     /**
2676      * Default text alignment. The text alignment of this View is inherited from its parent.
2677      * Use with {@link #setTextAlignment(int)}
2678      */
2679     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2680 
2681     /**
2682      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2683      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2684      *
2685      * Use with {@link #setTextAlignment(int)}
2686      */
2687     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2688 
2689     /**
2690      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2691      *
2692      * Use with {@link #setTextAlignment(int)}
2693      */
2694     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2695 
2696     /**
2697      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2698      *
2699      * Use with {@link #setTextAlignment(int)}
2700      */
2701     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2702 
2703     /**
2704      * Center the paragraph, e.g. ALIGN_CENTER.
2705      *
2706      * Use with {@link #setTextAlignment(int)}
2707      */
2708     public static final int TEXT_ALIGNMENT_CENTER = 4;
2709 
2710     /**
2711      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2712      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2713      *
2714      * Use with {@link #setTextAlignment(int)}
2715      */
2716     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2717 
2718     /**
2719      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2720      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2721      *
2722      * Use with {@link #setTextAlignment(int)}
2723      */
2724     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2725 
2726     /**
2727      * Default text alignment is inherited
2728      */
2729     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2730 
2731     /**
2732      * Default resolved text alignment
2733      * @hide
2734      */
2735     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2736 
2737     /**
2738       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2739       * @hide
2740       */
2741     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2742 
2743     /**
2744       * Mask for use with private flags indicating bits used for text alignment.
2745       * @hide
2746       */
2747     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2748 
2749     /**
2750      * Array of text direction flags for mapping attribute "textAlignment" to correct
2751      * flag value.
2752      * @hide
2753      */
2754     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2755             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2756             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2757             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2758             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2759             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2760             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2761             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2762     };
2763 
2764     /**
2765      * Indicates whether the view text alignment has been resolved.
2766      * @hide
2767      */
2768     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2769 
2770     /**
2771      * Bit shift to get the resolved text alignment.
2772      * @hide
2773      */
2774     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2775 
2776     /**
2777      * Mask for use with private flags indicating bits used for text alignment.
2778      * @hide
2779      */
2780     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2781             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2782 
2783     /**
2784      * Indicates whether if the view text alignment has been resolved to gravity
2785      */
2786     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2787             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2788 
2789     // Accessiblity constants for mPrivateFlags2
2790 
2791     /**
2792      * Shift for the bits in {@link #mPrivateFlags2} related to the
2793      * "importantForAccessibility" attribute.
2794      */
2795     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2796 
2797     /**
2798      * Automatically determine whether a view is important for accessibility.
2799      */
2800     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2801 
2802     /**
2803      * The view is important for accessibility.
2804      */
2805     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2806 
2807     /**
2808      * The view is not important for accessibility.
2809      */
2810     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2811 
2812     /**
2813      * The view is not important for accessibility, nor are any of its
2814      * descendant views.
2815      */
2816     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2817 
2818     /**
2819      * The default whether the view is important for accessibility.
2820      */
2821     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2822 
2823     /**
2824      * Mask for obtaining the bits which specify how to determine
2825      * whether a view is important for accessibility.
2826      */
2827     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2828         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2829         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2830         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2831 
2832     /**
2833      * Shift for the bits in {@link #mPrivateFlags2} related to the
2834      * "accessibilityLiveRegion" attribute.
2835      */
2836     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2837 
2838     /**
2839      * Live region mode specifying that accessibility services should not
2840      * automatically announce changes to this view. This is the default live
2841      * region mode for most views.
2842      * <p>
2843      * Use with {@link #setAccessibilityLiveRegion(int)}.
2844      */
2845     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2846 
2847     /**
2848      * Live region mode specifying that accessibility services should announce
2849      * changes to this view.
2850      * <p>
2851      * Use with {@link #setAccessibilityLiveRegion(int)}.
2852      */
2853     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2854 
2855     /**
2856      * Live region mode specifying that accessibility services should interrupt
2857      * ongoing speech to immediately announce changes to this view.
2858      * <p>
2859      * Use with {@link #setAccessibilityLiveRegion(int)}.
2860      */
2861     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2862 
2863     /**
2864      * The default whether the view is important for accessibility.
2865      */
2866     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2867 
2868     /**
2869      * Mask for obtaining the bits which specify a view's accessibility live
2870      * region mode.
2871      */
2872     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2873             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2874             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2875 
2876     /**
2877      * Flag indicating whether a view has accessibility focus.
2878      */
2879     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2880 
2881     /**
2882      * Flag whether the accessibility state of the subtree rooted at this view changed.
2883      */
2884     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2885 
2886     /**
2887      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2888      * is used to check whether later changes to the view's transform should invalidate the
2889      * view to force the quickReject test to run again.
2890      */
2891     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2892 
2893     /**
2894      * Flag indicating that start/end padding has been resolved into left/right padding
2895      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2896      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2897      * during measurement. In some special cases this is required such as when an adapter-based
2898      * view measures prospective children without attaching them to a window.
2899      */
2900     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2901 
2902     /**
2903      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2904      */
2905     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2906 
2907     /**
2908      * Indicates that the view is tracking some sort of transient state
2909      * that the app should not need to be aware of, but that the framework
2910      * should take special care to preserve.
2911      */
2912     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2913 
2914     /**
2915      * Group of bits indicating that RTL properties resolution is done.
2916      */
2917     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2918             PFLAG2_TEXT_DIRECTION_RESOLVED |
2919             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2920             PFLAG2_PADDING_RESOLVED |
2921             PFLAG2_DRAWABLE_RESOLVED;
2922 
2923     // There are a couple of flags left in mPrivateFlags2
2924 
2925     /* End of masks for mPrivateFlags2 */
2926 
2927     /**
2928      * Masks for mPrivateFlags3, as generated by dumpFlags():
2929      *
2930      * |-------|-------|-------|-------|
2931      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2932      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2933      *                               1   PFLAG3_IS_LAID_OUT
2934      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2935      *                             1     PFLAG3_CALLED_SUPER
2936      *                            1      PFLAG3_APPLYING_INSETS
2937      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2938      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2939      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2940      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2941      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2942      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2943      *                     1             PFLAG3_SCROLL_INDICATOR_START
2944      *                    1              PFLAG3_SCROLL_INDICATOR_END
2945      *                   1               PFLAG3_ASSIST_BLOCKED
2946      *                  1                PFLAG3_CLUSTER
2947      *                 1                 PFLAG3_IS_AUTOFILLED
2948      *                1                  PFLAG3_FINGER_DOWN
2949      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2950      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2951      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2952      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2953      *        1                          PFLAG3_TEMPORARY_DETACH
2954      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2955      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
2956      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
2957      *    1                              PFLAG3_AGGREGATED_VISIBLE
2958      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
2959      *  1                                PFLAG3_ACCESSIBILITY_HEADING
2960      * |-------|-------|-------|-------|
2961      */
2962 
2963     /**
2964      * Flag indicating that view has a transform animation set on it. This is used to track whether
2965      * an animation is cleared between successive frames, in order to tell the associated
2966      * DisplayList to clear its animation matrix.
2967      */
2968     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2969 
2970     /**
2971      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2972      * animation is cleared between successive frames, in order to tell the associated
2973      * DisplayList to restore its alpha value.
2974      */
2975     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2976 
2977     /**
2978      * Flag indicating that the view has been through at least one layout since it
2979      * was last attached to a window.
2980      */
2981     static final int PFLAG3_IS_LAID_OUT = 0x4;
2982 
2983     /**
2984      * Flag indicating that a call to measure() was skipped and should be done
2985      * instead when layout() is invoked.
2986      */
2987     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2988 
2989     /**
2990      * Flag indicating that an overridden method correctly called down to
2991      * the superclass implementation as required by the API spec.
2992      */
2993     static final int PFLAG3_CALLED_SUPER = 0x10;
2994 
2995     /**
2996      * Flag indicating that we're in the process of applying window insets.
2997      */
2998     static final int PFLAG3_APPLYING_INSETS = 0x20;
2999 
3000     /**
3001      * Flag indicating that we're in the process of fitting system windows using the old method.
3002      */
3003     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3004 
3005     /**
3006      * Flag indicating that nested scrolling is enabled for this view.
3007      * The view will optionally cooperate with views up its parent chain to allow for
3008      * integrated nested scrolling along the same axis.
3009      */
3010     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3011 
3012     /**
3013      * Flag indicating that the bottom scroll indicator should be displayed
3014      * when this view can scroll up.
3015      */
3016     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3017 
3018     /**
3019      * Flag indicating that the bottom scroll indicator should be displayed
3020      * when this view can scroll down.
3021      */
3022     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3023 
3024     /**
3025      * Flag indicating that the left scroll indicator should be displayed
3026      * when this view can scroll left.
3027      */
3028     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3029 
3030     /**
3031      * Flag indicating that the right scroll indicator should be displayed
3032      * when this view can scroll right.
3033      */
3034     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3035 
3036     /**
3037      * Flag indicating that the start scroll indicator should be displayed
3038      * when this view can scroll in the start direction.
3039      */
3040     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3041 
3042     /**
3043      * Flag indicating that the end scroll indicator should be displayed
3044      * when this view can scroll in the end direction.
3045      */
3046     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3047 
3048     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3049 
3050     static final int SCROLL_INDICATORS_NONE = 0x0000;
3051 
3052     /**
3053      * Mask for use with setFlags indicating bits used for indicating which
3054      * scroll indicators are enabled.
3055      */
3056     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3057             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3058             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3059             | PFLAG3_SCROLL_INDICATOR_END;
3060 
3061     /**
3062      * Left-shift required to translate between public scroll indicator flags
3063      * and internal PFLAGS3 flags. When used as a right-shift, translates
3064      * PFLAGS3 flags to public flags.
3065      */
3066     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3067 
3068     /** @hide */
3069     @Retention(RetentionPolicy.SOURCE)
3070     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3071             SCROLL_INDICATOR_TOP,
3072             SCROLL_INDICATOR_BOTTOM,
3073             SCROLL_INDICATOR_LEFT,
3074             SCROLL_INDICATOR_RIGHT,
3075             SCROLL_INDICATOR_START,
3076             SCROLL_INDICATOR_END,
3077     })
3078     public @interface ScrollIndicators {}
3079 
3080     /**
3081      * Scroll indicator direction for the top edge of the view.
3082      *
3083      * @see #setScrollIndicators(int)
3084      * @see #setScrollIndicators(int, int)
3085      * @see #getScrollIndicators()
3086      */
3087     public static final int SCROLL_INDICATOR_TOP =
3088             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3089 
3090     /**
3091      * Scroll indicator direction for the bottom edge of the view.
3092      *
3093      * @see #setScrollIndicators(int)
3094      * @see #setScrollIndicators(int, int)
3095      * @see #getScrollIndicators()
3096      */
3097     public static final int SCROLL_INDICATOR_BOTTOM =
3098             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3099 
3100     /**
3101      * Scroll indicator direction for the left edge of the view.
3102      *
3103      * @see #setScrollIndicators(int)
3104      * @see #setScrollIndicators(int, int)
3105      * @see #getScrollIndicators()
3106      */
3107     public static final int SCROLL_INDICATOR_LEFT =
3108             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3109 
3110     /**
3111      * Scroll indicator direction for the right edge of the view.
3112      *
3113      * @see #setScrollIndicators(int)
3114      * @see #setScrollIndicators(int, int)
3115      * @see #getScrollIndicators()
3116      */
3117     public static final int SCROLL_INDICATOR_RIGHT =
3118             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3119 
3120     /**
3121      * Scroll indicator direction for the starting edge of the view.
3122      * <p>
3123      * Resolved according to the view's layout direction, see
3124      * {@link #getLayoutDirection()} for more information.
3125      *
3126      * @see #setScrollIndicators(int)
3127      * @see #setScrollIndicators(int, int)
3128      * @see #getScrollIndicators()
3129      */
3130     public static final int SCROLL_INDICATOR_START =
3131             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3132 
3133     /**
3134      * Scroll indicator direction for the ending edge of the view.
3135      * <p>
3136      * Resolved according to the view's layout direction, see
3137      * {@link #getLayoutDirection()} for more information.
3138      *
3139      * @see #setScrollIndicators(int)
3140      * @see #setScrollIndicators(int, int)
3141      * @see #getScrollIndicators()
3142      */
3143     public static final int SCROLL_INDICATOR_END =
3144             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3145 
3146     /**
3147      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3148      * into this view.<p>
3149      */
3150     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3151 
3152     /**
3153      * Flag indicating that the view is a root of a keyboard navigation cluster.
3154      *
3155      * @see #isKeyboardNavigationCluster()
3156      * @see #setKeyboardNavigationCluster(boolean)
3157      */
3158     private static final int PFLAG3_CLUSTER = 0x8000;
3159 
3160     /**
3161      * Flag indicating that the view is autofilled
3162      *
3163      * @see #isAutofilled()
3164      * @see #setAutofilled(boolean)
3165      */
3166     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3167 
3168     /**
3169      * Indicates that the user is currently touching the screen.
3170      * Currently used for the tooltip positioning only.
3171      */
3172     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3173 
3174     /**
3175      * Flag indicating that this view is the default-focus view.
3176      *
3177      * @see #isFocusedByDefault()
3178      * @see #setFocusedByDefault(boolean)
3179      */
3180     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3181 
3182     /**
3183      * Shift for the bits in {@link #mPrivateFlags3} related to the
3184      * "importantForAutofill" attribute.
3185      */
3186     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3187 
3188     /**
3189      * Mask for obtaining the bits which specify how to determine
3190      * whether a view is important for autofill.
3191      */
3192     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3193             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3194             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3195             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3196             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3197 
3198     /**
3199      * Whether this view has rendered elements that overlap (see {@link
3200      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3201      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3202      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3203      * determined by whatever {@link #hasOverlappingRendering()} returns.
3204      */
3205     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3206 
3207     /**
3208      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3209      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3210      */
3211     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3212 
3213     /**
3214      * Flag indicating that the view is temporarily detached from the parent view.
3215      *
3216      * @see #onStartTemporaryDetach()
3217      * @see #onFinishTemporaryDetach()
3218      */
3219     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3220 
3221     /**
3222      * Flag indicating that the view does not wish to be revealed within its parent
3223      * hierarchy when it gains focus. Expressed in the negative since the historical
3224      * default behavior is to reveal on focus; this flag suppresses that behavior.
3225      *
3226      * @see #setRevealOnFocusHint(boolean)
3227      * @see #getRevealOnFocusHint()
3228      */
3229     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3230 
3231     /**
3232      * Flag indicating that when layout is completed we should notify
3233      * that the view was entered for autofill purposes. To minimize
3234      * showing autofill for views not visible to the user we evaluate
3235      * user visibility which cannot be done until the view is laid out.
3236      */
3237     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3238 
3239     /**
3240      * Works like focusable for screen readers, but without the side effects on input focus.
3241      * @see #setScreenReaderFocusable(boolean)
3242      */
3243     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3244 
3245     /**
3246      * The last aggregated visibility. Used to detect when it truly changes.
3247      */
3248     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3249 
3250     /**
3251      * Used to indicate that {@link #mAutofillId} was explicitly set through
3252      * {@link #setAutofillId(AutofillId)}.
3253      */
3254     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3255 
3256     /**
3257      * Indicates if the View is a heading for accessibility purposes
3258      */
3259     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3260 
3261     /* End of masks for mPrivateFlags3 */
3262 
3263     /**
3264      * Always allow a user to over-scroll this view, provided it is a
3265      * view that can scroll.
3266      *
3267      * @see #getOverScrollMode()
3268      * @see #setOverScrollMode(int)
3269      */
3270     public static final int OVER_SCROLL_ALWAYS = 0;
3271 
3272     /**
3273      * Allow a user to over-scroll this view only if the content is large
3274      * enough to meaningfully scroll, provided it is a view that can scroll.
3275      *
3276      * @see #getOverScrollMode()
3277      * @see #setOverScrollMode(int)
3278      */
3279     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3280 
3281     /**
3282      * Never allow a user to over-scroll this view.
3283      *
3284      * @see #getOverScrollMode()
3285      * @see #setOverScrollMode(int)
3286      */
3287     public static final int OVER_SCROLL_NEVER = 2;
3288 
3289     /**
3290      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3291      * requested the system UI (status bar) to be visible (the default).
3292      *
3293      * @see #setSystemUiVisibility(int)
3294      */
3295     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3296 
3297     /**
3298      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3299      * system UI to enter an unobtrusive "low profile" mode.
3300      *
3301      * <p>This is for use in games, book readers, video players, or any other
3302      * "immersive" application where the usual system chrome is deemed too distracting.
3303      *
3304      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3305      *
3306      * @see #setSystemUiVisibility(int)
3307      */
3308     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3309 
3310     /**
3311      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3312      * system navigation be temporarily hidden.
3313      *
3314      * <p>This is an even less obtrusive state than that called for by
3315      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3316      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3317      * those to disappear. This is useful (in conjunction with the
3318      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3319      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3320      * window flags) for displaying content using every last pixel on the display.
3321      *
3322      * <p>There is a limitation: because navigation controls are so important, the least user
3323      * interaction will cause them to reappear immediately.  When this happens, both
3324      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3325      * so that both elements reappear at the same time.
3326      *
3327      * @see #setSystemUiVisibility(int)
3328      */
3329     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3330 
3331     /**
3332      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3333      * into the normal fullscreen mode so that its content can take over the screen
3334      * while still allowing the user to interact with the application.
3335      *
3336      * <p>This has the same visual effect as
3337      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3338      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3339      * meaning that non-critical screen decorations (such as the status bar) will be
3340      * hidden while the user is in the View's window, focusing the experience on
3341      * that content.  Unlike the window flag, if you are using ActionBar in
3342      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3343      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3344      * hide the action bar.
3345      *
3346      * <p>This approach to going fullscreen is best used over the window flag when
3347      * it is a transient state -- that is, the application does this at certain
3348      * points in its user interaction where it wants to allow the user to focus
3349      * on content, but not as a continuous state.  For situations where the application
3350      * would like to simply stay full screen the entire time (such as a game that
3351      * wants to take over the screen), the
3352      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3353      * is usually a better approach.  The state set here will be removed by the system
3354      * in various situations (such as the user moving to another application) like
3355      * the other system UI states.
3356      *
3357      * <p>When using this flag, the application should provide some easy facility
3358      * for the user to go out of it.  A common example would be in an e-book
3359      * reader, where tapping on the screen brings back whatever screen and UI
3360      * decorations that had been hidden while the user was immersed in reading
3361      * the book.
3362      *
3363      * @see #setSystemUiVisibility(int)
3364      */
3365     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3366 
3367     /**
3368      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3369      * flags, we would like a stable view of the content insets given to
3370      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3371      * will always represent the worst case that the application can expect
3372      * as a continuous state.  In the stock Android UI this is the space for
3373      * the system bar, nav bar, and status bar, but not more transient elements
3374      * such as an input method.
3375      *
3376      * The stable layout your UI sees is based on the system UI modes you can
3377      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3378      * then you will get a stable layout for changes of the
3379      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3380      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3381      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3382      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3383      * with a stable layout.  (Note that you should avoid using
3384      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3385      *
3386      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3387      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3388      * then a hidden status bar will be considered a "stable" state for purposes
3389      * here.  This allows your UI to continually hide the status bar, while still
3390      * using the system UI flags to hide the action bar while still retaining
3391      * a stable layout.  Note that changing the window fullscreen flag will never
3392      * provide a stable layout for a clean transition.
3393      *
3394      * <p>If you are using ActionBar in
3395      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3396      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3397      * insets it adds to those given to the application.
3398      */
3399     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3400 
3401     /**
3402      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3403      * to be laid out as if it has requested
3404      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3405      * allows it to avoid artifacts when switching in and out of that mode, at
3406      * the expense that some of its user interface may be covered by screen
3407      * decorations when they are shown.  You can perform layout of your inner
3408      * UI elements to account for the navigation system UI through the
3409      * {@link #fitSystemWindows(Rect)} method.
3410      */
3411     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3412 
3413     /**
3414      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3415      * to be laid out as if it has requested
3416      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3417      * allows it to avoid artifacts when switching in and out of that mode, at
3418      * the expense that some of its user interface may be covered by screen
3419      * decorations when they are shown.  You can perform layout of your inner
3420      * UI elements to account for non-fullscreen system UI through the
3421      * {@link #fitSystemWindows(Rect)} method.
3422      *
3423      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3424      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3425      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3426      *  layoutInDisplayCutoutMode} is
3427      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3428      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3429      *
3430      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3431      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3432      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
3433      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3434      */
3435     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3436 
3437     /**
3438      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3439      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3440      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3441      * user interaction.
3442      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3443      * has an effect when used in combination with that flag.</p>
3444      */
3445     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3446 
3447     /**
3448      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3449      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3450      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3451      * experience while also hiding the system bars.  If this flag is not set,
3452      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3453      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3454      * if the user swipes from the top of the screen.
3455      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3456      * system gestures, such as swiping from the top of the screen.  These transient system bars
3457      * will overlay app’s content, may have some degree of transparency, and will automatically
3458      * hide after a short timeout.
3459      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3460      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3461      * with one or both of those flags.</p>
3462      */
3463     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3464 
3465     /**
3466      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3467      * is compatible with light status bar backgrounds.
3468      *
3469      * <p>For this to take effect, the window must request
3470      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3471      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3472      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3473      *         FLAG_TRANSLUCENT_STATUS}.
3474      *
3475      * @see android.R.attr#windowLightStatusBar
3476      */
3477     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3478 
3479     /**
3480      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3481      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3482      */
3483     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3484 
3485     /**
3486      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3487      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3488      */
3489     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3490 
3491     /**
3492      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3493      * that is compatible with light navigation bar backgrounds.
3494      *
3495      * <p>For this to take effect, the window must request
3496      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3497      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3498      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3499      *         FLAG_TRANSLUCENT_NAVIGATION}.
3500      *
3501      * @see android.R.attr#windowLightNavigationBar
3502      */
3503     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3504 
3505     /**
3506      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3507      */
3508     @Deprecated
3509     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3510 
3511     /**
3512      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3513      */
3514     @Deprecated
3515     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3516 
3517     /**
3518      * @hide
3519      *
3520      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3521      * out of the public fields to keep the undefined bits out of the developer's way.
3522      *
3523      * Flag to make the status bar not expandable.  Unless you also
3524      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3525      */
3526     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3527 
3528     /**
3529      * @hide
3530      *
3531      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3532      * out of the public fields to keep the undefined bits out of the developer's way.
3533      *
3534      * Flag to hide notification icons and scrolling ticker text.
3535      */
3536     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3537 
3538     /**
3539      * @hide
3540      *
3541      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3542      * out of the public fields to keep the undefined bits out of the developer's way.
3543      *
3544      * Flag to disable incoming notification alerts.  This will not block
3545      * icons, but it will block sound, vibrating and other visual or aural notifications.
3546      */
3547     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3548 
3549     /**
3550      * @hide
3551      *
3552      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3553      * out of the public fields to keep the undefined bits out of the developer's way.
3554      *
3555      * Flag to hide only the scrolling ticker.  Note that
3556      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3557      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3558      */
3559     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3560 
3561     /**
3562      * @hide
3563      *
3564      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3565      * out of the public fields to keep the undefined bits out of the developer's way.
3566      *
3567      * Flag to hide the center system info area.
3568      */
3569     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3570 
3571     /**
3572      * @hide
3573      *
3574      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3575      * out of the public fields to keep the undefined bits out of the developer's way.
3576      *
3577      * Flag to hide only the home button.  Don't use this
3578      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3579      */
3580     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3581 
3582     /**
3583      * @hide
3584      *
3585      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3586      * out of the public fields to keep the undefined bits out of the developer's way.
3587      *
3588      * Flag to hide only the back button. Don't use this
3589      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3590      */
3591     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3592 
3593     /**
3594      * @hide
3595      *
3596      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3597      * out of the public fields to keep the undefined bits out of the developer's way.
3598      *
3599      * Flag to hide only the clock.  You might use this if your activity has
3600      * its own clock making the status bar's clock redundant.
3601      */
3602     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3603 
3604     /**
3605      * @hide
3606      *
3607      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3608      * out of the public fields to keep the undefined bits out of the developer's way.
3609      *
3610      * Flag to hide only the recent apps button. Don't use this
3611      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3612      */
3613     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3614 
3615     /**
3616      * @hide
3617      *
3618      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3619      * out of the public fields to keep the undefined bits out of the developer's way.
3620      *
3621      * Flag to disable the global search gesture. Don't use this
3622      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3623      */
3624     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3625 
3626     /**
3627      * @hide
3628      *
3629      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3630      * out of the public fields to keep the undefined bits out of the developer's way.
3631      *
3632      * Flag to specify that the status bar is displayed in transient mode.
3633      */
3634     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3635 
3636     /**
3637      * @hide
3638      *
3639      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3640      * out of the public fields to keep the undefined bits out of the developer's way.
3641      *
3642      * Flag to specify that the navigation bar is displayed in transient mode.
3643      */
3644     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3645 
3646     /**
3647      * @hide
3648      *
3649      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3650      * out of the public fields to keep the undefined bits out of the developer's way.
3651      *
3652      * Flag to specify that the hidden status bar would like to be shown.
3653      */
3654     public static final int STATUS_BAR_UNHIDE = 0x10000000;
3655 
3656     /**
3657      * @hide
3658      *
3659      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3660      * out of the public fields to keep the undefined bits out of the developer's way.
3661      *
3662      * Flag to specify that the hidden navigation bar would like to be shown.
3663      */
3664     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3665 
3666     /**
3667      * @hide
3668      *
3669      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3670      * out of the public fields to keep the undefined bits out of the developer's way.
3671      *
3672      * Flag to specify that the status bar is displayed in translucent mode.
3673      */
3674     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3675 
3676     /**
3677      * @hide
3678      *
3679      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3680      * out of the public fields to keep the undefined bits out of the developer's way.
3681      *
3682      * Flag to specify that the navigation bar is displayed in translucent mode.
3683      */
3684     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3685 
3686     /**
3687      * @hide
3688      *
3689      * Makes navigation bar transparent (but not the status bar).
3690      */
3691     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3692 
3693     /**
3694      * @hide
3695      *
3696      * Makes status bar transparent (but not the navigation bar).
3697      */
3698     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3699 
3700     /**
3701      * @hide
3702      *
3703      * Makes both status bar and navigation bar transparent.
3704      */
3705     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3706             | STATUS_BAR_TRANSPARENT;
3707 
3708     /**
3709      * @hide
3710      */
3711     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3712 
3713     /**
3714      * These are the system UI flags that can be cleared by events outside
3715      * of an application.  Currently this is just the ability to tap on the
3716      * screen while hiding the navigation bar to have it return.
3717      * @hide
3718      */
3719     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3720             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3721             | SYSTEM_UI_FLAG_FULLSCREEN;
3722 
3723     /**
3724      * Flags that can impact the layout in relation to system UI.
3725      */
3726     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3727             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3728             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3729 
3730     /** @hide */
3731     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
3732             FIND_VIEWS_WITH_TEXT,
3733             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
3734     })
3735     @Retention(RetentionPolicy.SOURCE)
3736     public @interface FindViewFlags {}
3737 
3738     /**
3739      * Find views that render the specified text.
3740      *
3741      * @see #findViewsWithText(ArrayList, CharSequence, int)
3742      */
3743     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3744 
3745     /**
3746      * Find find views that contain the specified content description.
3747      *
3748      * @see #findViewsWithText(ArrayList, CharSequence, int)
3749      */
3750     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3751 
3752     /**
3753      * Find views that contain {@link AccessibilityNodeProvider}. Such
3754      * a View is a root of virtual view hierarchy and may contain the searched
3755      * text. If this flag is set Views with providers are automatically
3756      * added and it is a responsibility of the client to call the APIs of
3757      * the provider to determine whether the virtual tree rooted at this View
3758      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3759      * representing the virtual views with this text.
3760      *
3761      * @see #findViewsWithText(ArrayList, CharSequence, int)
3762      *
3763      * @hide
3764      */
3765     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3766 
3767     /**
3768      * The undefined cursor position.
3769      *
3770      * @hide
3771      */
3772     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3773 
3774     /**
3775      * Indicates that the screen has changed state and is now off.
3776      *
3777      * @see #onScreenStateChanged(int)
3778      */
3779     public static final int SCREEN_STATE_OFF = 0x0;
3780 
3781     /**
3782      * Indicates that the screen has changed state and is now on.
3783      *
3784      * @see #onScreenStateChanged(int)
3785      */
3786     public static final int SCREEN_STATE_ON = 0x1;
3787 
3788     /**
3789      * Indicates no axis of view scrolling.
3790      */
3791     public static final int SCROLL_AXIS_NONE = 0;
3792 
3793     /**
3794      * Indicates scrolling along the horizontal axis.
3795      */
3796     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3797 
3798     /**
3799      * Indicates scrolling along the vertical axis.
3800      */
3801     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3802 
3803     /**
3804      * Controls the over-scroll mode for this view.
3805      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3806      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3807      * and {@link #OVER_SCROLL_NEVER}.
3808      */
3809     private int mOverScrollMode;
3810 
3811     /**
3812      * The parent this view is attached to.
3813      * {@hide}
3814      *
3815      * @see #getParent()
3816      */
3817     protected ViewParent mParent;
3818 
3819     /**
3820      * {@hide}
3821      */
3822     AttachInfo mAttachInfo;
3823 
3824     /**
3825      * {@hide}
3826      */
3827     @ViewDebug.ExportedProperty(flagMapping = {
3828         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3829                 name = "FORCE_LAYOUT"),
3830         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3831                 name = "LAYOUT_REQUIRED"),
3832         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3833             name = "DRAWING_CACHE_INVALID", outputIf = false),
3834         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3835         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3836         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3837         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3838     }, formatToHexString = true)
3839 
3840     /* @hide */
3841     public int mPrivateFlags;
3842     int mPrivateFlags2;
3843     int mPrivateFlags3;
3844 
3845     /**
3846      * This view's request for the visibility of the status bar.
3847      * @hide
3848      */
3849     @ViewDebug.ExportedProperty(flagMapping = {
3850             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3851                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3852                     name = "LOW_PROFILE"),
3853             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3854                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3855                     name = "HIDE_NAVIGATION"),
3856             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
3857                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
3858                     name = "FULLSCREEN"),
3859             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
3860                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
3861                     name = "LAYOUT_STABLE"),
3862             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
3863                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
3864                     name = "LAYOUT_HIDE_NAVIGATION"),
3865             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
3866                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
3867                     name = "LAYOUT_FULLSCREEN"),
3868             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
3869                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
3870                     name = "IMMERSIVE"),
3871             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
3872                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
3873                     name = "IMMERSIVE_STICKY"),
3874             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
3875                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
3876                     name = "LIGHT_STATUS_BAR"),
3877             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
3878                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
3879                     name = "LIGHT_NAVIGATION_BAR"),
3880             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
3881                     equals = STATUS_BAR_DISABLE_EXPAND,
3882                     name = "STATUS_BAR_DISABLE_EXPAND"),
3883             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
3884                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
3885                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
3886             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
3887                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
3888                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
3889             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
3890                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
3891                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
3892             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
3893                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
3894                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
3895             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
3896                     equals = STATUS_BAR_DISABLE_HOME,
3897                     name = "STATUS_BAR_DISABLE_HOME"),
3898             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
3899                     equals = STATUS_BAR_DISABLE_BACK,
3900                     name = "STATUS_BAR_DISABLE_BACK"),
3901             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
3902                     equals = STATUS_BAR_DISABLE_CLOCK,
3903                     name = "STATUS_BAR_DISABLE_CLOCK"),
3904             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
3905                     equals = STATUS_BAR_DISABLE_RECENT,
3906                     name = "STATUS_BAR_DISABLE_RECENT"),
3907             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
3908                     equals = STATUS_BAR_DISABLE_SEARCH,
3909                     name = "STATUS_BAR_DISABLE_SEARCH"),
3910             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT,
3911                     equals = STATUS_BAR_TRANSIENT,
3912                     name = "STATUS_BAR_TRANSIENT"),
3913             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT,
3914                     equals = NAVIGATION_BAR_TRANSIENT,
3915                     name = "NAVIGATION_BAR_TRANSIENT"),
3916             @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE,
3917                     equals = STATUS_BAR_UNHIDE,
3918                     name = "STATUS_BAR_UNHIDE"),
3919             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE,
3920                     equals = NAVIGATION_BAR_UNHIDE,
3921                     name = "NAVIGATION_BAR_UNHIDE"),
3922             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT,
3923                     equals = STATUS_BAR_TRANSLUCENT,
3924                     name = "STATUS_BAR_TRANSLUCENT"),
3925             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT,
3926                     equals = NAVIGATION_BAR_TRANSLUCENT,
3927                     name = "NAVIGATION_BAR_TRANSLUCENT"),
3928             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT,
3929                     equals = NAVIGATION_BAR_TRANSPARENT,
3930                     name = "NAVIGATION_BAR_TRANSPARENT"),
3931             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT,
3932                     equals = STATUS_BAR_TRANSPARENT,
3933                     name = "STATUS_BAR_TRANSPARENT")
3934     }, formatToHexString = true)
3935     int mSystemUiVisibility;
3936 
3937     /**
3938      * Reference count for transient state.
3939      * @see #setHasTransientState(boolean)
3940      */
3941     int mTransientStateCount = 0;
3942 
3943     /**
3944      * Count of how many windows this view has been attached to.
3945      */
3946     int mWindowAttachCount;
3947 
3948     /**
3949      * The layout parameters associated with this view and used by the parent
3950      * {@link android.view.ViewGroup} to determine how this view should be
3951      * laid out.
3952      * {@hide}
3953      */
3954     protected ViewGroup.LayoutParams mLayoutParams;
3955 
3956     /**
3957      * The view flags hold various views states.
3958      * {@hide}
3959      */
3960     @ViewDebug.ExportedProperty(formatToHexString = true)
3961     int mViewFlags;
3962 
3963     static class TransformationInfo {
3964         /**
3965          * The transform matrix for the View. This transform is calculated internally
3966          * based on the translation, rotation, and scale properties.
3967          *
3968          * Do *not* use this variable directly; instead call getMatrix(), which will
3969          * load the value from the View's RenderNode.
3970          */
3971         private final Matrix mMatrix = new Matrix();
3972 
3973         /**
3974          * The inverse transform matrix for the View. This transform is calculated
3975          * internally based on the translation, rotation, and scale properties.
3976          *
3977          * Do *not* use this variable directly; instead call getInverseMatrix(),
3978          * which will load the value from the View's RenderNode.
3979          */
3980         private Matrix mInverseMatrix;
3981 
3982         /**
3983          * The opacity of the View. This is a value from 0 to 1, where 0 means
3984          * completely transparent and 1 means completely opaque.
3985          */
3986         @ViewDebug.ExportedProperty
3987         float mAlpha = 1f;
3988 
3989         /**
3990          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3991          * property only used by transitions, which is composited with the other alpha
3992          * values to calculate the final visual alpha value.
3993          */
3994         float mTransitionAlpha = 1f;
3995     }
3996 
3997     /** @hide */
3998     public TransformationInfo mTransformationInfo;
3999 
4000     /**
4001      * Current clip bounds. to which all drawing of this view are constrained.
4002      */
4003     @ViewDebug.ExportedProperty(category = "drawing")
4004     Rect mClipBounds = null;
4005 
4006     private boolean mLastIsOpaque;
4007 
4008     /**
4009      * The distance in pixels from the left edge of this view's parent
4010      * to the left edge of this view.
4011      * {@hide}
4012      */
4013     @ViewDebug.ExportedProperty(category = "layout")
4014     protected int mLeft;
4015     /**
4016      * The distance in pixels from the left edge of this view's parent
4017      * to the right edge of this view.
4018      * {@hide}
4019      */
4020     @ViewDebug.ExportedProperty(category = "layout")
4021     protected int mRight;
4022     /**
4023      * The distance in pixels from the top edge of this view's parent
4024      * to the top edge of this view.
4025      * {@hide}
4026      */
4027     @ViewDebug.ExportedProperty(category = "layout")
4028     protected int mTop;
4029     /**
4030      * The distance in pixels from the top edge of this view's parent
4031      * to the bottom edge of this view.
4032      * {@hide}
4033      */
4034     @ViewDebug.ExportedProperty(category = "layout")
4035     protected int mBottom;
4036 
4037     /**
4038      * The offset, in pixels, by which the content of this view is scrolled
4039      * horizontally.
4040      * {@hide}
4041      */
4042     @ViewDebug.ExportedProperty(category = "scrolling")
4043     protected int mScrollX;
4044     /**
4045      * The offset, in pixels, by which the content of this view is scrolled
4046      * vertically.
4047      * {@hide}
4048      */
4049     @ViewDebug.ExportedProperty(category = "scrolling")
4050     protected int mScrollY;
4051 
4052     /**
4053      * The left padding in pixels, that is the distance in pixels between the
4054      * left edge of this view and the left edge of its content.
4055      * {@hide}
4056      */
4057     @ViewDebug.ExportedProperty(category = "padding")
4058     protected int mPaddingLeft = 0;
4059     /**
4060      * The right padding in pixels, that is the distance in pixels between the
4061      * right edge of this view and the right edge of its content.
4062      * {@hide}
4063      */
4064     @ViewDebug.ExportedProperty(category = "padding")
4065     protected int mPaddingRight = 0;
4066     /**
4067      * The top padding in pixels, that is the distance in pixels between the
4068      * top edge of this view and the top edge of its content.
4069      * {@hide}
4070      */
4071     @ViewDebug.ExportedProperty(category = "padding")
4072     protected int mPaddingTop;
4073     /**
4074      * The bottom padding in pixels, that is the distance in pixels between the
4075      * bottom edge of this view and the bottom edge of its content.
4076      * {@hide}
4077      */
4078     @ViewDebug.ExportedProperty(category = "padding")
4079     protected int mPaddingBottom;
4080 
4081     /**
4082      * The layout insets in pixels, that is the distance in pixels between the
4083      * visible edges of this view its bounds.
4084      */
4085     private Insets mLayoutInsets;
4086 
4087     /**
4088      * Briefly describes the view and is primarily used for accessibility support.
4089      */
4090     private CharSequence mContentDescription;
4091 
4092     /**
4093      * If this view represents a distinct part of the window, it can have a title that labels the
4094      * area.
4095      */
4096     private CharSequence mAccessibilityPaneTitle;
4097 
4098     /**
4099      * Specifies the id of a view for which this view serves as a label for
4100      * accessibility purposes.
4101      */
4102     private int mLabelForId = View.NO_ID;
4103 
4104     /**
4105      * Predicate for matching labeled view id with its label for
4106      * accessibility purposes.
4107      */
4108     private MatchLabelForPredicate mMatchLabelForPredicate;
4109 
4110     /**
4111      * Specifies a view before which this one is visited in accessibility traversal.
4112      */
4113     private int mAccessibilityTraversalBeforeId = NO_ID;
4114 
4115     /**
4116      * Specifies a view after which this one is visited in accessibility traversal.
4117      */
4118     private int mAccessibilityTraversalAfterId = NO_ID;
4119 
4120     /**
4121      * Predicate for matching a view by its id.
4122      */
4123     private MatchIdPredicate mMatchIdPredicate;
4124 
4125     /**
4126      * Cache the paddingRight set by the user to append to the scrollbar's size.
4127      *
4128      * @hide
4129      */
4130     @ViewDebug.ExportedProperty(category = "padding")
4131     protected int mUserPaddingRight;
4132 
4133     /**
4134      * Cache the paddingBottom set by the user to append to the scrollbar's size.
4135      *
4136      * @hide
4137      */
4138     @ViewDebug.ExportedProperty(category = "padding")
4139     protected int mUserPaddingBottom;
4140 
4141     /**
4142      * Cache the paddingLeft set by the user to append to the scrollbar's size.
4143      *
4144      * @hide
4145      */
4146     @ViewDebug.ExportedProperty(category = "padding")
4147     protected int mUserPaddingLeft;
4148 
4149     /**
4150      * Cache the paddingStart set by the user to append to the scrollbar's size.
4151      *
4152      */
4153     @ViewDebug.ExportedProperty(category = "padding")
4154     int mUserPaddingStart;
4155 
4156     /**
4157      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4158      *
4159      */
4160     @ViewDebug.ExportedProperty(category = "padding")
4161     int mUserPaddingEnd;
4162 
4163     /**
4164      * Cache initial left padding.
4165      *
4166      * @hide
4167      */
4168     int mUserPaddingLeftInitial;
4169 
4170     /**
4171      * Cache initial right padding.
4172      *
4173      * @hide
4174      */
4175     int mUserPaddingRightInitial;
4176 
4177     /**
4178      * Default undefined padding
4179      */
4180     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4181 
4182     /**
4183      * Cache if a left padding has been defined
4184      */
4185     private boolean mLeftPaddingDefined = false;
4186 
4187     /**
4188      * Cache if a right padding has been defined
4189      */
4190     private boolean mRightPaddingDefined = false;
4191 
4192     /**
4193      * @hide
4194      */
4195     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4196     /**
4197      * @hide
4198      */
4199     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4200 
4201     private LongSparseLongArray mMeasureCache;
4202 
4203     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4204     private Drawable mBackground;
4205     private TintInfo mBackgroundTint;
4206 
4207     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4208     private ForegroundInfo mForegroundInfo;
4209 
4210     private Drawable mScrollIndicatorDrawable;
4211 
4212     /**
4213      * RenderNode used for backgrounds.
4214      * <p>
4215      * When non-null and valid, this is expected to contain an up-to-date copy
4216      * of the background drawable. It is cleared on temporary detach, and reset
4217      * on cleanup.
4218      */
4219     private RenderNode mBackgroundRenderNode;
4220 
4221     private int mBackgroundResource;
4222     private boolean mBackgroundSizeChanged;
4223 
4224     /** The default focus highlight.
4225      * @see #mDefaultFocusHighlightEnabled
4226      * @see Drawable#hasFocusStateSpecified()
4227      */
4228     private Drawable mDefaultFocusHighlight;
4229     private Drawable mDefaultFocusHighlightCache;
4230     private boolean mDefaultFocusHighlightSizeChanged;
4231     /**
4232      * True if the default focus highlight is needed on the target device.
4233      */
4234     private static boolean sUseDefaultFocusHighlight;
4235 
4236     /**
4237      * True if zero-sized views can be focused.
4238      */
4239     private static boolean sCanFocusZeroSized;
4240 
4241     /**
4242      * Always assign focus if a focusable View is available.
4243      */
4244     private static boolean sAlwaysAssignFocus;
4245 
4246     private String mTransitionName;
4247 
4248     static class TintInfo {
4249         ColorStateList mTintList;
4250         PorterDuff.Mode mTintMode;
4251         boolean mHasTintMode;
4252         boolean mHasTintList;
4253     }
4254 
4255     private static class ForegroundInfo {
4256         private Drawable mDrawable;
4257         private TintInfo mTintInfo;
4258         private int mGravity = Gravity.FILL;
4259         private boolean mInsidePadding = true;
4260         private boolean mBoundsChanged = true;
4261         private final Rect mSelfBounds = new Rect();
4262         private final Rect mOverlayBounds = new Rect();
4263     }
4264 
4265     static class ListenerInfo {
4266         /**
4267          * Listener used to dispatch focus change events.
4268          * This field should be made private, so it is hidden from the SDK.
4269          * {@hide}
4270          */
4271         protected OnFocusChangeListener mOnFocusChangeListener;
4272 
4273         /**
4274          * Listeners for layout change events.
4275          */
4276         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4277 
4278         protected OnScrollChangeListener mOnScrollChangeListener;
4279 
4280         /**
4281          * Listeners for attach events.
4282          */
4283         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4284 
4285         /**
4286          * Listener used to dispatch click events.
4287          * This field should be made private, so it is hidden from the SDK.
4288          * {@hide}
4289          */
4290         public OnClickListener mOnClickListener;
4291 
4292         /**
4293          * Listener used to dispatch long click events.
4294          * This field should be made private, so it is hidden from the SDK.
4295          * {@hide}
4296          */
4297         protected OnLongClickListener mOnLongClickListener;
4298 
4299         /**
4300          * Listener used to dispatch context click events. This field should be made private, so it
4301          * is hidden from the SDK.
4302          * {@hide}
4303          */
4304         protected OnContextClickListener mOnContextClickListener;
4305 
4306         /**
4307          * Listener used to build the context menu.
4308          * This field should be made private, so it is hidden from the SDK.
4309          * {@hide}
4310          */
4311         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4312 
4313         private OnKeyListener mOnKeyListener;
4314 
4315         private OnTouchListener mOnTouchListener;
4316 
4317         private OnHoverListener mOnHoverListener;
4318 
4319         private OnGenericMotionListener mOnGenericMotionListener;
4320 
4321         private OnDragListener mOnDragListener;
4322 
4323         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4324 
4325         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4326 
4327         OnCapturedPointerListener mOnCapturedPointerListener;
4328 
4329         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4330     }
4331 
4332     ListenerInfo mListenerInfo;
4333 
4334     private static class TooltipInfo {
4335         /**
4336          * Text to be displayed in a tooltip popup.
4337          */
4338         @Nullable
4339         CharSequence mTooltipText;
4340 
4341         /**
4342          * View-relative position of the tooltip anchor point.
4343          */
4344         int mAnchorX;
4345         int mAnchorY;
4346 
4347         /**
4348          * The tooltip popup.
4349          */
4350         @Nullable
4351         TooltipPopup mTooltipPopup;
4352 
4353         /**
4354          * Set to true if the tooltip was shown as a result of a long click.
4355          */
4356         boolean mTooltipFromLongClick;
4357 
4358         /**
4359          * Keep these Runnables so that they can be used to reschedule.
4360          */
4361         Runnable mShowTooltipRunnable;
4362         Runnable mHideTooltipRunnable;
4363 
4364         /**
4365          * Hover move is ignored if it is within this distance in pixels from the previous one.
4366          */
4367         int mHoverSlop;
4368 
4369         /**
4370          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4371          * different from the previously stored position. Ignoring insignificant changes
4372          * filters out the jitter which is typical for such input sources as stylus.
4373          *
4374          * @return True if the position has been updated.
4375          */
updateAnchorPos(MotionEvent event)4376         private boolean updateAnchorPos(MotionEvent event) {
4377             final int newAnchorX = (int) event.getX();
4378             final int newAnchorY = (int) event.getY();
4379             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4380                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4381                 return false;
4382             }
4383             mAnchorX = newAnchorX;
4384             mAnchorY = newAnchorY;
4385             return true;
4386         }
4387 
4388         /**
4389          *  Clear the anchor position to ensure that the next change is considered significant.
4390          */
clearAnchorPos()4391         private void clearAnchorPos() {
4392             mAnchorX = Integer.MAX_VALUE;
4393             mAnchorY = Integer.MAX_VALUE;
4394         }
4395     }
4396 
4397     TooltipInfo mTooltipInfo;
4398 
4399     // Temporary values used to hold (x,y) coordinates when delegating from the
4400     // two-arg performLongClick() method to the legacy no-arg version.
4401     private float mLongClickX = Float.NaN;
4402     private float mLongClickY = Float.NaN;
4403 
4404     /**
4405      * The application environment this view lives in.
4406      * This field should be made private, so it is hidden from the SDK.
4407      * {@hide}
4408      */
4409     @ViewDebug.ExportedProperty(deepExport = true)
4410     protected Context mContext;
4411 
4412     private final Resources mResources;
4413 
4414     private ScrollabilityCache mScrollCache;
4415 
4416     private int[] mDrawableState = null;
4417 
4418     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4419 
4420     /**
4421      * Animator that automatically runs based on state changes.
4422      */
4423     private StateListAnimator mStateListAnimator;
4424 
4425     /**
4426      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4427      * the user may specify which view to go to next.
4428      */
4429     private int mNextFocusLeftId = View.NO_ID;
4430 
4431     /**
4432      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4433      * the user may specify which view to go to next.
4434      */
4435     private int mNextFocusRightId = View.NO_ID;
4436 
4437     /**
4438      * When this view has focus and the next focus is {@link #FOCUS_UP},
4439      * the user may specify which view to go to next.
4440      */
4441     private int mNextFocusUpId = View.NO_ID;
4442 
4443     /**
4444      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4445      * the user may specify which view to go to next.
4446      */
4447     private int mNextFocusDownId = View.NO_ID;
4448 
4449     /**
4450      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4451      * the user may specify which view to go to next.
4452      */
4453     int mNextFocusForwardId = View.NO_ID;
4454 
4455     /**
4456      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4457      *
4458      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4459      */
4460     int mNextClusterForwardId = View.NO_ID;
4461 
4462     /**
4463      * Whether this View should use a default focus highlight when it gets focused but doesn't
4464      * have {@link android.R.attr#state_focused} defined in its background.
4465      */
4466     boolean mDefaultFocusHighlightEnabled = true;
4467 
4468     private CheckForLongPress mPendingCheckForLongPress;
4469     private CheckForTap mPendingCheckForTap = null;
4470     private PerformClick mPerformClick;
4471     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4472 
4473     private UnsetPressedState mUnsetPressedState;
4474 
4475     /**
4476      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4477      * up event while a long press is invoked as soon as the long press duration is reached, so
4478      * a long press could be performed before the tap is checked, in which case the tap's action
4479      * should not be invoked.
4480      */
4481     private boolean mHasPerformedLongPress;
4482 
4483     /**
4484      * Whether a context click button is currently pressed down. This is true when the stylus is
4485      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4486      * pressed. This is false once the button is released or if the stylus has been lifted.
4487      */
4488     private boolean mInContextButtonPress;
4489 
4490     /**
4491      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4492      * true after a stylus button press has occured, when the next up event should not be recognized
4493      * as a tap.
4494      */
4495     private boolean mIgnoreNextUpEvent;
4496 
4497     /**
4498      * The minimum height of the view. We'll try our best to have the height
4499      * of this view to at least this amount.
4500      */
4501     @ViewDebug.ExportedProperty(category = "measurement")
4502     private int mMinHeight;
4503 
4504     /**
4505      * The minimum width of the view. We'll try our best to have the width
4506      * of this view to at least this amount.
4507      */
4508     @ViewDebug.ExportedProperty(category = "measurement")
4509     private int mMinWidth;
4510 
4511     /**
4512      * The delegate to handle touch events that are physically in this view
4513      * but should be handled by another view.
4514      */
4515     private TouchDelegate mTouchDelegate = null;
4516 
4517     /**
4518      * Solid color to use as a background when creating the drawing cache. Enables
4519      * the cache to use 16 bit bitmaps instead of 32 bit.
4520      */
4521     private int mDrawingCacheBackgroundColor = 0;
4522 
4523     /**
4524      * Special tree observer used when mAttachInfo is null.
4525      */
4526     private ViewTreeObserver mFloatingTreeObserver;
4527 
4528     /**
4529      * Cache the touch slop from the context that created the view.
4530      */
4531     private int mTouchSlop;
4532 
4533     /**
4534      * Object that handles automatic animation of view properties.
4535      */
4536     private ViewPropertyAnimator mAnimator = null;
4537 
4538     /**
4539      * List of registered FrameMetricsObservers.
4540      */
4541     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4542 
4543     /**
4544      * Flag indicating that a drag can cross window boundaries.  When
4545      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4546      * with this flag set, all visible applications with targetSdkVersion >=
4547      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4548      * in the drag operation and receive the dragged content.
4549      *
4550      * <p>If this is the only flag set, then the drag recipient will only have access to text data
4551      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4552      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4553      */
4554     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4555 
4556     /**
4557      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4558      * request read access to the content URI(s) contained in the {@link ClipData} object.
4559      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4560      */
4561     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4562 
4563     /**
4564      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4565      * request write access to the content URI(s) contained in the {@link ClipData} object.
4566      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4567      */
4568     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4569 
4570     /**
4571      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4572      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4573      * reboots until explicitly revoked with
4574      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4575      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4576      */
4577     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4578             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4579 
4580     /**
4581      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4582      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4583      * match against the original granted URI.
4584      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4585      */
4586     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4587             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4588 
4589     /**
4590      * Flag indicating that the drag shadow will be opaque.  When
4591      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4592      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4593      */
4594     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4595 
4596     /**
4597      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4598      */
4599     private float mVerticalScrollFactor;
4600 
4601     /**
4602      * Position of the vertical scroll bar.
4603      */
4604     private int mVerticalScrollbarPosition;
4605 
4606     /**
4607      * Position the scroll bar at the default position as determined by the system.
4608      */
4609     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4610 
4611     /**
4612      * Position the scroll bar along the left edge.
4613      */
4614     public static final int SCROLLBAR_POSITION_LEFT = 1;
4615 
4616     /**
4617      * Position the scroll bar along the right edge.
4618      */
4619     public static final int SCROLLBAR_POSITION_RIGHT = 2;
4620 
4621     /**
4622      * Indicates that the view does not have a layer.
4623      *
4624      * @see #getLayerType()
4625      * @see #setLayerType(int, android.graphics.Paint)
4626      * @see #LAYER_TYPE_SOFTWARE
4627      * @see #LAYER_TYPE_HARDWARE
4628      */
4629     public static final int LAYER_TYPE_NONE = 0;
4630 
4631     /**
4632      * <p>Indicates that the view has a software layer. A software layer is backed
4633      * by a bitmap and causes the view to be rendered using Android's software
4634      * rendering pipeline, even if hardware acceleration is enabled.</p>
4635      *
4636      * <p>Software layers have various usages:</p>
4637      * <p>When the application is not using hardware acceleration, a software layer
4638      * is useful to apply a specific color filter and/or blending mode and/or
4639      * translucency to a view and all its children.</p>
4640      * <p>When the application is using hardware acceleration, a software layer
4641      * is useful to render drawing primitives not supported by the hardware
4642      * accelerated pipeline. It can also be used to cache a complex view tree
4643      * into a texture and reduce the complexity of drawing operations. For instance,
4644      * when animating a complex view tree with a translation, a software layer can
4645      * be used to render the view tree only once.</p>
4646      * <p>Software layers should be avoided when the affected view tree updates
4647      * often. Every update will require to re-render the software layer, which can
4648      * potentially be slow (particularly when hardware acceleration is turned on
4649      * since the layer will have to be uploaded into a hardware texture after every
4650      * update.)</p>
4651      *
4652      * @see #getLayerType()
4653      * @see #setLayerType(int, android.graphics.Paint)
4654      * @see #LAYER_TYPE_NONE
4655      * @see #LAYER_TYPE_HARDWARE
4656      */
4657     public static final int LAYER_TYPE_SOFTWARE = 1;
4658 
4659     /**
4660      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4661      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4662      * OpenGL hardware) and causes the view to be rendered using Android's hardware
4663      * rendering pipeline, but only if hardware acceleration is turned on for the
4664      * view hierarchy. When hardware acceleration is turned off, hardware layers
4665      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4666      *
4667      * <p>A hardware layer is useful to apply a specific color filter and/or
4668      * blending mode and/or translucency to a view and all its children.</p>
4669      * <p>A hardware layer can be used to cache a complex view tree into a
4670      * texture and reduce the complexity of drawing operations. For instance,
4671      * when animating a complex view tree with a translation, a hardware layer can
4672      * be used to render the view tree only once.</p>
4673      * <p>A hardware layer can also be used to increase the rendering quality when
4674      * rotation transformations are applied on a view. It can also be used to
4675      * prevent potential clipping issues when applying 3D transforms on a view.</p>
4676      *
4677      * @see #getLayerType()
4678      * @see #setLayerType(int, android.graphics.Paint)
4679      * @see #LAYER_TYPE_NONE
4680      * @see #LAYER_TYPE_SOFTWARE
4681      */
4682     public static final int LAYER_TYPE_HARDWARE = 2;
4683 
4684     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4685             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4686             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4687             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4688     })
4689     int mLayerType = LAYER_TYPE_NONE;
4690     Paint mLayerPaint;
4691 
4692     /**
4693      * Set to true when drawing cache is enabled and cannot be created.
4694      *
4695      * @hide
4696      */
4697     public boolean mCachingFailed;
4698     private Bitmap mDrawingCache;
4699     private Bitmap mUnscaledDrawingCache;
4700 
4701     /**
4702      * RenderNode holding View properties, potentially holding a DisplayList of View content.
4703      * <p>
4704      * When non-null and valid, this is expected to contain an up-to-date copy
4705      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4706      * cleanup.
4707      */
4708     final RenderNode mRenderNode;
4709 
4710     /**
4711      * Set to true when the view is sending hover accessibility events because it
4712      * is the innermost hovered view.
4713      */
4714     private boolean mSendingHoverAccessibilityEvents;
4715 
4716     /**
4717      * Delegate for injecting accessibility functionality.
4718      */
4719     AccessibilityDelegate mAccessibilityDelegate;
4720 
4721     /**
4722      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4723      * and add/remove objects to/from the overlay directly through the Overlay methods.
4724      */
4725     ViewOverlay mOverlay;
4726 
4727     /**
4728      * The currently active parent view for receiving delegated nested scrolling events.
4729      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4730      * by {@link #stopNestedScroll()} at the same point where we clear
4731      * requestDisallowInterceptTouchEvent.
4732      */
4733     private ViewParent mNestedScrollingParent;
4734 
4735     /**
4736      * Consistency verifier for debugging purposes.
4737      * @hide
4738      */
4739     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4740             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4741                     new InputEventConsistencyVerifier(this, 0) : null;
4742 
4743     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4744 
4745     private int[] mTempNestedScrollConsumed;
4746 
4747     /**
4748      * An overlay is going to draw this View instead of being drawn as part of this
4749      * View's parent. mGhostView is the View in the Overlay that must be invalidated
4750      * when this view is invalidated.
4751      */
4752     GhostView mGhostView;
4753 
4754     /**
4755      * Holds pairs of adjacent attribute data: attribute name followed by its value.
4756      * @hide
4757      */
4758     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4759     public String[] mAttributes;
4760 
4761     /**
4762      * Maps a Resource id to its name.
4763      */
4764     private static SparseArray<String> mAttributeMap;
4765 
4766     /**
4767      * Queue of pending runnables. Used to postpone calls to post() until this
4768      * view is attached and has a handler.
4769      */
4770     private HandlerActionQueue mRunQueue;
4771 
4772     /**
4773      * The pointer icon when the mouse hovers on this view. The default is null.
4774      */
4775     private PointerIcon mPointerIcon;
4776 
4777     /**
4778      * @hide
4779      */
4780     String mStartActivityRequestWho;
4781 
4782     @Nullable
4783     private RoundScrollbarRenderer mRoundScrollbarRenderer;
4784 
4785     /** Used to delay visibility updates sent to the autofill manager */
4786     private Handler mVisibilityChangeForAutofillHandler;
4787 
4788     /**
4789      * Simple constructor to use when creating a view from code.
4790      *
4791      * @param context The Context the view is running in, through which it can
4792      *        access the current theme, resources, etc.
4793      */
View(Context context)4794     public View(Context context) {
4795         mContext = context;
4796         mResources = context != null ? context.getResources() : null;
4797         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4798         // Set some flags defaults
4799         mPrivateFlags2 =
4800                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4801                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4802                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4803                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4804                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4805                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4806         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4807         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4808         mUserPaddingStart = UNDEFINED_PADDING;
4809         mUserPaddingEnd = UNDEFINED_PADDING;
4810         mRenderNode = RenderNode.create(getClass().getName(), this);
4811 
4812         if (!sCompatibilityDone && context != null) {
4813             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4814 
4815             // Older apps may need this compatibility hack for measurement.
4816             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4817 
4818             // Older apps expect onMeasure() to always be called on a layout pass, regardless
4819             // of whether a layout was requested on that View.
4820             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4821 
4822             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4823             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
4824             Canvas.setCompatibilityVersion(targetSdkVersion);
4825 
4826             // In M and newer, our widgets can pass a "hint" value in the size
4827             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4828             // know what the expected parent size is going to be, so e.g. list items can size
4829             // themselves at 1/3 the size of their container. It breaks older apps though,
4830             // specifically apps that use some popular open source libraries.
4831             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4832 
4833             // Old versions of the platform would give different results from
4834             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4835             // modes, so we always need to run an additional EXACTLY pass.
4836             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4837 
4838             // Prior to N, layout params could change without requiring a
4839             // subsequent call to setLayoutParams() and they would usually
4840             // work. Partial layout breaks this assumption.
4841             sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4842 
4843             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4844             // On N+, we throw, but that breaks compatibility with apps that use these methods.
4845             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4846 
4847             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4848             // in apps so we target check it to avoid breaking existing apps.
4849             sPreserveMarginParamsInLayoutParamConversion =
4850                     targetSdkVersion >= Build.VERSION_CODES.N;
4851 
4852             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4853 
4854             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4855 
4856             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4857 
4858             sUseDefaultFocusHighlight = context.getResources().getBoolean(
4859                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
4860 
4861             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
4862 
4863             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
4864 
4865             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
4866 
4867             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
4868 
4869             sCompatibilityDone = true;
4870         }
4871     }
4872 
4873     /**
4874      * Constructor that is called when inflating a view from XML. This is called
4875      * when a view is being constructed from an XML file, supplying attributes
4876      * that were specified in the XML file. This version uses a default style of
4877      * 0, so the only attribute values applied are those in the Context's Theme
4878      * and the given AttributeSet.
4879      *
4880      * <p>
4881      * The method onFinishInflate() will be called after all children have been
4882      * added.
4883      *
4884      * @param context The Context the view is running in, through which it can
4885      *        access the current theme, resources, etc.
4886      * @param attrs The attributes of the XML tag that is inflating the view.
4887      * @see #View(Context, AttributeSet, int)
4888      */
4889     public View(Context context, @Nullable AttributeSet attrs) {
4890         this(context, attrs, 0);
4891     }
4892 
4893     /**
4894      * Perform inflation from XML and apply a class-specific base style from a
4895      * theme attribute. This constructor of View allows subclasses to use their
4896      * own base style when they are inflating. For example, a Button class's
4897      * constructor would call this version of the super class constructor and
4898      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4899      * allows the theme's button style to modify all of the base view attributes
4900      * (in particular its background) as well as the Button class's attributes.
4901      *
4902      * @param context The Context the view is running in, through which it can
4903      *        access the current theme, resources, etc.
4904      * @param attrs The attributes of the XML tag that is inflating the view.
4905      * @param defStyleAttr An attribute in the current theme that contains a
4906      *        reference to a style resource that supplies default values for
4907      *        the view. Can be 0 to not look for defaults.
4908      * @see #View(Context, AttributeSet)
4909      */
4910     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4911         this(context, attrs, defStyleAttr, 0);
4912     }
4913 
4914     /**
4915      * Perform inflation from XML and apply a class-specific base style from a
4916      * theme attribute or style resource. This constructor of View allows
4917      * subclasses to use their own base style when they are inflating.
4918      * <p>
4919      * When determining the final value of a particular attribute, there are
4920      * four inputs that come into play:
4921      * <ol>
4922      * <li>Any attribute values in the given AttributeSet.
4923      * <li>The style resource specified in the AttributeSet (named "style").
4924      * <li>The default style specified by <var>defStyleAttr</var>.
4925      * <li>The default style specified by <var>defStyleRes</var>.
4926      * <li>The base values in this theme.
4927      * </ol>
4928      * <p>
4929      * Each of these inputs is considered in-order, with the first listed taking
4930      * precedence over the following ones. In other words, if in the
4931      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4932      * , then the button's text will <em>always</em> be black, regardless of
4933      * what is specified in any of the styles.
4934      *
4935      * @param context The Context the view is running in, through which it can
4936      *        access the current theme, resources, etc.
4937      * @param attrs The attributes of the XML tag that is inflating the view.
4938      * @param defStyleAttr An attribute in the current theme that contains a
4939      *        reference to a style resource that supplies default values for
4940      *        the view. Can be 0 to not look for defaults.
4941      * @param defStyleRes A resource identifier of a style resource that
4942      *        supplies default values for the view, used only if
4943      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4944      *        to not look for defaults.
4945      * @see #View(Context, AttributeSet, int)
4946      */
4947     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4948         this(context);
4949 
4950         final TypedArray a = context.obtainStyledAttributes(
4951                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4952 
4953         if (mDebugViewAttributes) {
4954             saveAttributeData(attrs, a);
4955         }
4956 
4957         Drawable background = null;
4958 
4959         int leftPadding = -1;
4960         int topPadding = -1;
4961         int rightPadding = -1;
4962         int bottomPadding = -1;
4963         int startPadding = UNDEFINED_PADDING;
4964         int endPadding = UNDEFINED_PADDING;
4965 
4966         int padding = -1;
4967         int paddingHorizontal = -1;
4968         int paddingVertical = -1;
4969 
4970         int viewFlagValues = 0;
4971         int viewFlagMasks = 0;
4972 
4973         boolean setScrollContainer = false;
4974 
4975         int x = 0;
4976         int y = 0;
4977 
4978         float tx = 0;
4979         float ty = 0;
4980         float tz = 0;
4981         float elevation = 0;
4982         float rotation = 0;
4983         float rotationX = 0;
4984         float rotationY = 0;
4985         float sx = 1f;
4986         float sy = 1f;
4987         boolean transformSet = false;
4988 
4989         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4990         int overScrollMode = mOverScrollMode;
4991         boolean initializeScrollbars = false;
4992         boolean initializeScrollIndicators = false;
4993 
4994         boolean startPaddingDefined = false;
4995         boolean endPaddingDefined = false;
4996         boolean leftPaddingDefined = false;
4997         boolean rightPaddingDefined = false;
4998 
4999         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5000 
5001         // Set default values.
5002         viewFlagValues |= FOCUSABLE_AUTO;
5003         viewFlagMasks |= FOCUSABLE_AUTO;
5004 
5005         final int N = a.getIndexCount();
5006         for (int i = 0; i < N; i++) {
5007             int attr = a.getIndex(i);
5008             switch (attr) {
5009                 case com.android.internal.R.styleable.View_background:
5010                     background = a.getDrawable(attr);
5011                     break;
5012                 case com.android.internal.R.styleable.View_padding:
5013                     padding = a.getDimensionPixelSize(attr, -1);
5014                     mUserPaddingLeftInitial = padding;
5015                     mUserPaddingRightInitial = padding;
5016                     leftPaddingDefined = true;
5017                     rightPaddingDefined = true;
5018                     break;
5019                 case com.android.internal.R.styleable.View_paddingHorizontal:
5020                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5021                     mUserPaddingLeftInitial = paddingHorizontal;
5022                     mUserPaddingRightInitial = paddingHorizontal;
5023                     leftPaddingDefined = true;
5024                     rightPaddingDefined = true;
5025                     break;
5026                 case com.android.internal.R.styleable.View_paddingVertical:
5027                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5028                     break;
5029                  case com.android.internal.R.styleable.View_paddingLeft:
5030                     leftPadding = a.getDimensionPixelSize(attr, -1);
5031                     mUserPaddingLeftInitial = leftPadding;
5032                     leftPaddingDefined = true;
5033                     break;
5034                 case com.android.internal.R.styleable.View_paddingTop:
5035                     topPadding = a.getDimensionPixelSize(attr, -1);
5036                     break;
5037                 case com.android.internal.R.styleable.View_paddingRight:
5038                     rightPadding = a.getDimensionPixelSize(attr, -1);
5039                     mUserPaddingRightInitial = rightPadding;
5040                     rightPaddingDefined = true;
5041                     break;
5042                 case com.android.internal.R.styleable.View_paddingBottom:
5043                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5044                     break;
5045                 case com.android.internal.R.styleable.View_paddingStart:
5046                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5047                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5048                     break;
5049                 case com.android.internal.R.styleable.View_paddingEnd:
5050                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5051                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5052                     break;
5053                 case com.android.internal.R.styleable.View_scrollX:
5054                     x = a.getDimensionPixelOffset(attr, 0);
5055                     break;
5056                 case com.android.internal.R.styleable.View_scrollY:
5057                     y = a.getDimensionPixelOffset(attr, 0);
5058                     break;
5059                 case com.android.internal.R.styleable.View_alpha:
5060                     setAlpha(a.getFloat(attr, 1f));
5061                     break;
5062                 case com.android.internal.R.styleable.View_transformPivotX:
5063                     setPivotX(a.getDimension(attr, 0));
5064                     break;
5065                 case com.android.internal.R.styleable.View_transformPivotY:
5066                     setPivotY(a.getDimension(attr, 0));
5067                     break;
5068                 case com.android.internal.R.styleable.View_translationX:
5069                     tx = a.getDimension(attr, 0);
5070                     transformSet = true;
5071                     break;
5072                 case com.android.internal.R.styleable.View_translationY:
5073                     ty = a.getDimension(attr, 0);
5074                     transformSet = true;
5075                     break;
5076                 case com.android.internal.R.styleable.View_translationZ:
5077                     tz = a.getDimension(attr, 0);
5078                     transformSet = true;
5079                     break;
5080                 case com.android.internal.R.styleable.View_elevation:
5081                     elevation = a.getDimension(attr, 0);
5082                     transformSet = true;
5083                     break;
5084                 case com.android.internal.R.styleable.View_rotation:
5085                     rotation = a.getFloat(attr, 0);
5086                     transformSet = true;
5087                     break;
5088                 case com.android.internal.R.styleable.View_rotationX:
5089                     rotationX = a.getFloat(attr, 0);
5090                     transformSet = true;
5091                     break;
5092                 case com.android.internal.R.styleable.View_rotationY:
5093                     rotationY = a.getFloat(attr, 0);
5094                     transformSet = true;
5095                     break;
5096                 case com.android.internal.R.styleable.View_scaleX:
5097                     sx = a.getFloat(attr, 1f);
5098                     transformSet = true;
5099                     break;
5100                 case com.android.internal.R.styleable.View_scaleY:
5101                     sy = a.getFloat(attr, 1f);
5102                     transformSet = true;
5103                     break;
5104                 case com.android.internal.R.styleable.View_id:
5105                     mID = a.getResourceId(attr, NO_ID);
5106                     break;
5107                 case com.android.internal.R.styleable.View_tag:
5108                     mTag = a.getText(attr);
5109                     break;
5110                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5111                     if (a.getBoolean(attr, false)) {
5112                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5113                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5114                     }
5115                     break;
5116                 case com.android.internal.R.styleable.View_focusable:
5117                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5118                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5119                         viewFlagMasks |= FOCUSABLE_MASK;
5120                     }
5121                     break;
5122                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5123                     if (a.getBoolean(attr, false)) {
5124                         // unset auto focus since focusableInTouchMode implies explicit focusable
5125                         viewFlagValues &= ~FOCUSABLE_AUTO;
5126                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5127                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5128                     }
5129                     break;
5130                 case com.android.internal.R.styleable.View_clickable:
5131                     if (a.getBoolean(attr, false)) {
5132                         viewFlagValues |= CLICKABLE;
5133                         viewFlagMasks |= CLICKABLE;
5134                     }
5135                     break;
5136                 case com.android.internal.R.styleable.View_longClickable:
5137                     if (a.getBoolean(attr, false)) {
5138                         viewFlagValues |= LONG_CLICKABLE;
5139                         viewFlagMasks |= LONG_CLICKABLE;
5140                     }
5141                     break;
5142                 case com.android.internal.R.styleable.View_contextClickable:
5143                     if (a.getBoolean(attr, false)) {
5144                         viewFlagValues |= CONTEXT_CLICKABLE;
5145                         viewFlagMasks |= CONTEXT_CLICKABLE;
5146                     }
5147                     break;
5148                 case com.android.internal.R.styleable.View_saveEnabled:
5149                     if (!a.getBoolean(attr, true)) {
5150                         viewFlagValues |= SAVE_DISABLED;
5151                         viewFlagMasks |= SAVE_DISABLED_MASK;
5152                     }
5153                     break;
5154                 case com.android.internal.R.styleable.View_duplicateParentState:
5155                     if (a.getBoolean(attr, false)) {
5156                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5157                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5158                     }
5159                     break;
5160                 case com.android.internal.R.styleable.View_visibility:
5161                     final int visibility = a.getInt(attr, 0);
5162                     if (visibility != 0) {
5163                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5164                         viewFlagMasks |= VISIBILITY_MASK;
5165                     }
5166                     break;
5167                 case com.android.internal.R.styleable.View_layoutDirection:
5168                     // Clear any layout direction flags (included resolved bits) already set
5169                     mPrivateFlags2 &=
5170                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5171                     // Set the layout direction flags depending on the value of the attribute
5172                     final int layoutDirection = a.getInt(attr, -1);
5173                     final int value = (layoutDirection != -1) ?
5174                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5175                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5176                     break;
5177                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5178                     final int cacheQuality = a.getInt(attr, 0);
5179                     if (cacheQuality != 0) {
5180                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5181                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5182                     }
5183                     break;
5184                 case com.android.internal.R.styleable.View_contentDescription:
5185                     setContentDescription(a.getString(attr));
5186                     break;
5187                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5188                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5189                     break;
5190                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5191                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5192                     break;
5193                 case com.android.internal.R.styleable.View_labelFor:
5194                     setLabelFor(a.getResourceId(attr, NO_ID));
5195                     break;
5196                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5197                     if (!a.getBoolean(attr, true)) {
5198                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5199                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5200                     }
5201                     break;
5202                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5203                     if (!a.getBoolean(attr, true)) {
5204                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5205                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5206                     }
5207                     break;
5208                 case R.styleable.View_scrollbars:
5209                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5210                     if (scrollbars != SCROLLBARS_NONE) {
5211                         viewFlagValues |= scrollbars;
5212                         viewFlagMasks |= SCROLLBARS_MASK;
5213                         initializeScrollbars = true;
5214                     }
5215                     break;
5216                 //noinspection deprecation
5217                 case R.styleable.View_fadingEdge:
5218                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5219                         // Ignore the attribute starting with ICS
5220                         break;
5221                     }
5222                     // With builds < ICS, fall through and apply fading edges
5223                 case R.styleable.View_requiresFadingEdge:
5224                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5225                     if (fadingEdge != FADING_EDGE_NONE) {
5226                         viewFlagValues |= fadingEdge;
5227                         viewFlagMasks |= FADING_EDGE_MASK;
5228                         initializeFadingEdgeInternal(a);
5229                     }
5230                     break;
5231                 case R.styleable.View_scrollbarStyle:
5232                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5233                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5234                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5235                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5236                     }
5237                     break;
5238                 case R.styleable.View_isScrollContainer:
5239                     setScrollContainer = true;
5240                     if (a.getBoolean(attr, false)) {
5241                         setScrollContainer(true);
5242                     }
5243                     break;
5244                 case com.android.internal.R.styleable.View_keepScreenOn:
5245                     if (a.getBoolean(attr, false)) {
5246                         viewFlagValues |= KEEP_SCREEN_ON;
5247                         viewFlagMasks |= KEEP_SCREEN_ON;
5248                     }
5249                     break;
5250                 case R.styleable.View_filterTouchesWhenObscured:
5251                     if (a.getBoolean(attr, false)) {
5252                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5253                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5254                     }
5255                     break;
5256                 case R.styleable.View_nextFocusLeft:
5257                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5258                     break;
5259                 case R.styleable.View_nextFocusRight:
5260                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5261                     break;
5262                 case R.styleable.View_nextFocusUp:
5263                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5264                     break;
5265                 case R.styleable.View_nextFocusDown:
5266                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5267                     break;
5268                 case R.styleable.View_nextFocusForward:
5269                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5270                     break;
5271                 case R.styleable.View_nextClusterForward:
5272                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5273                     break;
5274                 case R.styleable.View_minWidth:
5275                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5276                     break;
5277                 case R.styleable.View_minHeight:
5278                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5279                     break;
5280                 case R.styleable.View_onClick:
5281                     if (context.isRestricted()) {
5282                         throw new IllegalStateException("The android:onClick attribute cannot "
5283                                 + "be used within a restricted context");
5284                     }
5285 
5286                     final String handlerName = a.getString(attr);
5287                     if (handlerName != null) {
5288                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5289                     }
5290                     break;
5291                 case R.styleable.View_overScrollMode:
5292                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5293                     break;
5294                 case R.styleable.View_verticalScrollbarPosition:
5295                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5296                     break;
5297                 case R.styleable.View_layerType:
5298                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5299                     break;
5300                 case R.styleable.View_textDirection:
5301                     // Clear any text direction flag already set
5302                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5303                     // Set the text direction flags depending on the value of the attribute
5304                     final int textDirection = a.getInt(attr, -1);
5305                     if (textDirection != -1) {
5306                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5307                     }
5308                     break;
5309                 case R.styleable.View_textAlignment:
5310                     // Clear any text alignment flag already set
5311                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5312                     // Set the text alignment flag depending on the value of the attribute
5313                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5314                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5315                     break;
5316                 case R.styleable.View_importantForAccessibility:
5317                     setImportantForAccessibility(a.getInt(attr,
5318                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5319                     break;
5320                 case R.styleable.View_accessibilityLiveRegion:
5321                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5322                     break;
5323                 case R.styleable.View_transitionName:
5324                     setTransitionName(a.getString(attr));
5325                     break;
5326                 case R.styleable.View_nestedScrollingEnabled:
5327                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5328                     break;
5329                 case R.styleable.View_stateListAnimator:
5330                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5331                             a.getResourceId(attr, 0)));
5332                     break;
5333                 case R.styleable.View_backgroundTint:
5334                     // This will get applied later during setBackground().
5335                     if (mBackgroundTint == null) {
5336                         mBackgroundTint = new TintInfo();
5337                     }
5338                     mBackgroundTint.mTintList = a.getColorStateList(
5339                             R.styleable.View_backgroundTint);
5340                     mBackgroundTint.mHasTintList = true;
5341                     break;
5342                 case R.styleable.View_backgroundTintMode:
5343                     // This will get applied later during setBackground().
5344                     if (mBackgroundTint == null) {
5345                         mBackgroundTint = new TintInfo();
5346                     }
5347                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
5348                             R.styleable.View_backgroundTintMode, -1), null);
5349                     mBackgroundTint.mHasTintMode = true;
5350                     break;
5351                 case R.styleable.View_outlineProvider:
5352                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5353                             PROVIDER_BACKGROUND));
5354                     break;
5355                 case R.styleable.View_foreground:
5356                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5357                         setForeground(a.getDrawable(attr));
5358                     }
5359                     break;
5360                 case R.styleable.View_foregroundGravity:
5361                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5362                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5363                     }
5364                     break;
5365                 case R.styleable.View_foregroundTintMode:
5366                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5367                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5368                     }
5369                     break;
5370                 case R.styleable.View_foregroundTint:
5371                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5372                         setForegroundTintList(a.getColorStateList(attr));
5373                     }
5374                     break;
5375                 case R.styleable.View_foregroundInsidePadding:
5376                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5377                         if (mForegroundInfo == null) {
5378                             mForegroundInfo = new ForegroundInfo();
5379                         }
5380                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5381                                 mForegroundInfo.mInsidePadding);
5382                     }
5383                     break;
5384                 case R.styleable.View_scrollIndicators:
5385                     final int scrollIndicators =
5386                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5387                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5388                     if (scrollIndicators != 0) {
5389                         mPrivateFlags3 |= scrollIndicators;
5390                         initializeScrollIndicators = true;
5391                     }
5392                     break;
5393                 case R.styleable.View_pointerIcon:
5394                     final int resourceId = a.getResourceId(attr, 0);
5395                     if (resourceId != 0) {
5396                         setPointerIcon(PointerIcon.load(
5397                                 context.getResources(), resourceId));
5398                     } else {
5399                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5400                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5401                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5402                         }
5403                     }
5404                     break;
5405                 case R.styleable.View_forceHasOverlappingRendering:
5406                     if (a.peekValue(attr) != null) {
5407                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5408                     }
5409                     break;
5410                 case R.styleable.View_tooltipText:
5411                     setTooltipText(a.getText(attr));
5412                     break;
5413                 case R.styleable.View_keyboardNavigationCluster:
5414                     if (a.peekValue(attr) != null) {
5415                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5416                     }
5417                     break;
5418                 case R.styleable.View_focusedByDefault:
5419                     if (a.peekValue(attr) != null) {
5420                         setFocusedByDefault(a.getBoolean(attr, true));
5421                     }
5422                     break;
5423                 case R.styleable.View_autofillHints:
5424                     if (a.peekValue(attr) != null) {
5425                         CharSequence[] rawHints = null;
5426                         String rawString = null;
5427 
5428                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5429                             int resId = a.getResourceId(attr, 0);
5430 
5431                             try {
5432                                 rawHints = a.getTextArray(attr);
5433                             } catch (Resources.NotFoundException e) {
5434                                 rawString = getResources().getString(resId);
5435                             }
5436                         } else {
5437                             rawString = a.getString(attr);
5438                         }
5439 
5440                         if (rawHints == null) {
5441                             if (rawString == null) {
5442                                 throw new IllegalArgumentException(
5443                                         "Could not resolve autofillHints");
5444                             } else {
5445                                 rawHints = rawString.split(",");
5446                             }
5447                         }
5448 
5449                         String[] hints = new String[rawHints.length];
5450 
5451                         int numHints = rawHints.length;
5452                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5453                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5454                         }
5455                         setAutofillHints(hints);
5456                     }
5457                     break;
5458                 case R.styleable.View_importantForAutofill:
5459                     if (a.peekValue(attr) != null) {
5460                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5461                     }
5462                     break;
5463                 case R.styleable.View_defaultFocusHighlightEnabled:
5464                     if (a.peekValue(attr) != null) {
5465                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5466                     }
5467                     break;
5468                 case R.styleable.View_screenReaderFocusable:
5469                     if (a.peekValue(attr) != null) {
5470                         setScreenReaderFocusable(a.getBoolean(attr, false));
5471                     }
5472                     break;
5473                 case R.styleable.View_accessibilityPaneTitle:
5474                     if (a.peekValue(attr) != null) {
5475                         setAccessibilityPaneTitle(a.getString(attr));
5476                     }
5477                     break;
5478                 case R.styleable.View_outlineSpotShadowColor:
5479                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
5480                     break;
5481                 case R.styleable.View_outlineAmbientShadowColor:
5482                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
5483                     break;
5484                 case com.android.internal.R.styleable.View_accessibilityHeading:
5485                     setAccessibilityHeading(a.getBoolean(attr, false));
5486             }
5487         }
5488 
5489         setOverScrollMode(overScrollMode);
5490 
5491         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5492         // the resolved layout direction). Those cached values will be used later during padding
5493         // resolution.
5494         mUserPaddingStart = startPadding;
5495         mUserPaddingEnd = endPadding;
5496 
5497         if (background != null) {
5498             setBackground(background);
5499         }
5500 
5501         // setBackground above will record that padding is currently provided by the background.
5502         // If we have padding specified via xml, record that here instead and use it.
5503         mLeftPaddingDefined = leftPaddingDefined;
5504         mRightPaddingDefined = rightPaddingDefined;
5505 
5506         if (padding >= 0) {
5507             leftPadding = padding;
5508             topPadding = padding;
5509             rightPadding = padding;
5510             bottomPadding = padding;
5511             mUserPaddingLeftInitial = padding;
5512             mUserPaddingRightInitial = padding;
5513         } else {
5514             if (paddingHorizontal >= 0) {
5515                 leftPadding = paddingHorizontal;
5516                 rightPadding = paddingHorizontal;
5517                 mUserPaddingLeftInitial = paddingHorizontal;
5518                 mUserPaddingRightInitial = paddingHorizontal;
5519             }
5520             if (paddingVertical >= 0) {
5521                 topPadding = paddingVertical;
5522                 bottomPadding = paddingVertical;
5523             }
5524         }
5525 
5526         if (isRtlCompatibilityMode()) {
5527             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5528             // left / right padding are used if defined (meaning here nothing to do). If they are not
5529             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5530             // start / end and resolve them as left / right (layout direction is not taken into account).
5531             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5532             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5533             // defined.
5534             if (!mLeftPaddingDefined && startPaddingDefined) {
5535                 leftPadding = startPadding;
5536             }
5537             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5538             if (!mRightPaddingDefined && endPaddingDefined) {
5539                 rightPadding = endPadding;
5540             }
5541             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5542         } else {
5543             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5544             // values defined. Otherwise, left /right values are used.
5545             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5546             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5547             // defined.
5548             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5549 
5550             if (mLeftPaddingDefined && !hasRelativePadding) {
5551                 mUserPaddingLeftInitial = leftPadding;
5552             }
5553             if (mRightPaddingDefined && !hasRelativePadding) {
5554                 mUserPaddingRightInitial = rightPadding;
5555             }
5556         }
5557 
5558         internalSetPadding(
5559                 mUserPaddingLeftInitial,
5560                 topPadding >= 0 ? topPadding : mPaddingTop,
5561                 mUserPaddingRightInitial,
5562                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5563 
5564         if (viewFlagMasks != 0) {
5565             setFlags(viewFlagValues, viewFlagMasks);
5566         }
5567 
5568         if (initializeScrollbars) {
5569             initializeScrollbarsInternal(a);
5570         }
5571 
5572         if (initializeScrollIndicators) {
5573             initializeScrollIndicatorsInternal();
5574         }
5575 
5576         a.recycle();
5577 
5578         // Needs to be called after mViewFlags is set
5579         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5580             recomputePadding();
5581         }
5582 
5583         if (x != 0 || y != 0) {
5584             scrollTo(x, y);
5585         }
5586 
5587         if (transformSet) {
5588             setTranslationX(tx);
5589             setTranslationY(ty);
5590             setTranslationZ(tz);
5591             setElevation(elevation);
5592             setRotation(rotation);
5593             setRotationX(rotationX);
5594             setRotationY(rotationY);
5595             setScaleX(sx);
5596             setScaleY(sy);
5597         }
5598 
5599         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5600             setScrollContainer(true);
5601         }
5602 
5603         computeOpaqueFlags();
5604     }
5605 
5606     /**
5607      * An implementation of OnClickListener that attempts to lazily load a
5608      * named click handling method from a parent or ancestor context.
5609      */
5610     private static class DeclaredOnClickListener implements OnClickListener {
5611         private final View mHostView;
5612         private final String mMethodName;
5613 
5614         private Method mResolvedMethod;
5615         private Context mResolvedContext;
5616 
5617         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5618             mHostView = hostView;
5619             mMethodName = methodName;
5620         }
5621 
5622         @Override
5623         public void onClick(@NonNull View v) {
5624             if (mResolvedMethod == null) {
5625                 resolveMethod(mHostView.getContext(), mMethodName);
5626             }
5627 
5628             try {
5629                 mResolvedMethod.invoke(mResolvedContext, v);
5630             } catch (IllegalAccessException e) {
5631                 throw new IllegalStateException(
5632                         "Could not execute non-public method for android:onClick", e);
5633             } catch (InvocationTargetException e) {
5634                 throw new IllegalStateException(
5635                         "Could not execute method for android:onClick", e);
5636             }
5637         }
5638 
5639         @NonNull
5640         private void resolveMethod(@Nullable Context context, @NonNull String name) {
5641             while (context != null) {
5642                 try {
5643                     if (!context.isRestricted()) {
5644                         final Method method = context.getClass().getMethod(mMethodName, View.class);
5645                         if (method != null) {
5646                             mResolvedMethod = method;
5647                             mResolvedContext = context;
5648                             return;
5649                         }
5650                     }
5651                 } catch (NoSuchMethodException e) {
5652                     // Failed to find method, keep searching up the hierarchy.
5653                 }
5654 
5655                 if (context instanceof ContextWrapper) {
5656                     context = ((ContextWrapper) context).getBaseContext();
5657                 } else {
5658                     // Can't search up the hierarchy, null out and fail.
5659                     context = null;
5660                 }
5661             }
5662 
5663             final int id = mHostView.getId();
5664             final String idText = id == NO_ID ? "" : " with id '"
5665                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5666             throw new IllegalStateException("Could not find method " + mMethodName
5667                     + "(View) in a parent or ancestor Context for android:onClick "
5668                     + "attribute defined on view " + mHostView.getClass() + idText);
5669         }
5670     }
5671 
5672     /**
5673      * Non-public constructor for use in testing
5674      */
5675     View() {
5676         mResources = null;
5677         mRenderNode = RenderNode.create(getClass().getName(), this);
5678     }
5679 
5680     final boolean debugDraw() {
5681         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5682     }
5683 
5684     private static SparseArray<String> getAttributeMap() {
5685         if (mAttributeMap == null) {
5686             mAttributeMap = new SparseArray<>();
5687         }
5688         return mAttributeMap;
5689     }
5690 
5691     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5692         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5693         final int indexCount = t.getIndexCount();
5694         final String[] attributes = new String[(attrsCount + indexCount) * 2];
5695 
5696         int i = 0;
5697 
5698         // Store raw XML attributes.
5699         for (int j = 0; j < attrsCount; ++j) {
5700             attributes[i] = attrs.getAttributeName(j);
5701             attributes[i + 1] = attrs.getAttributeValue(j);
5702             i += 2;
5703         }
5704 
5705         // Store resolved styleable attributes.
5706         final Resources res = t.getResources();
5707         final SparseArray<String> attributeMap = getAttributeMap();
5708         for (int j = 0; j < indexCount; ++j) {
5709             final int index = t.getIndex(j);
5710             if (!t.hasValueOrEmpty(index)) {
5711                 // Value is undefined. Skip it.
5712                 continue;
5713             }
5714 
5715             final int resourceId = t.getResourceId(index, 0);
5716             if (resourceId == 0) {
5717                 // Value is not a reference. Skip it.
5718                 continue;
5719             }
5720 
5721             String resourceName = attributeMap.get(resourceId);
5722             if (resourceName == null) {
5723                 try {
5724                     resourceName = res.getResourceName(resourceId);
5725                 } catch (Resources.NotFoundException e) {
5726                     resourceName = "0x" + Integer.toHexString(resourceId);
5727                 }
5728                 attributeMap.put(resourceId, resourceName);
5729             }
5730 
5731             attributes[i] = resourceName;
5732             attributes[i + 1] = t.getString(index);
5733             i += 2;
5734         }
5735 
5736         // Trim to fit contents.
5737         final String[] trimmed = new String[i];
5738         System.arraycopy(attributes, 0, trimmed, 0, i);
5739         mAttributes = trimmed;
5740     }
5741 
5742     public String toString() {
5743         StringBuilder out = new StringBuilder(128);
5744         out.append(getClass().getName());
5745         out.append('{');
5746         out.append(Integer.toHexString(System.identityHashCode(this)));
5747         out.append(' ');
5748         switch (mViewFlags&VISIBILITY_MASK) {
5749             case VISIBLE: out.append('V'); break;
5750             case INVISIBLE: out.append('I'); break;
5751             case GONE: out.append('G'); break;
5752             default: out.append('.'); break;
5753         }
5754         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5755         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5756         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5757         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5758         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5759         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5760         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5761         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5762         out.append(' ');
5763         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5764         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5765         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5766         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5767             out.append('p');
5768         } else {
5769             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5770         }
5771         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5772         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5773         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5774         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5775         out.append(' ');
5776         out.append(mLeft);
5777         out.append(',');
5778         out.append(mTop);
5779         out.append('-');
5780         out.append(mRight);
5781         out.append(',');
5782         out.append(mBottom);
5783         final int id = getId();
5784         if (id != NO_ID) {
5785             out.append(" #");
5786             out.append(Integer.toHexString(id));
5787             final Resources r = mResources;
5788             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5789                 try {
5790                     String pkgname;
5791                     switch (id&0xff000000) {
5792                         case 0x7f000000:
5793                             pkgname="app";
5794                             break;
5795                         case 0x01000000:
5796                             pkgname="android";
5797                             break;
5798                         default:
5799                             pkgname = r.getResourcePackageName(id);
5800                             break;
5801                     }
5802                     String typename = r.getResourceTypeName(id);
5803                     String entryname = r.getResourceEntryName(id);
5804                     out.append(" ");
5805                     out.append(pkgname);
5806                     out.append(":");
5807                     out.append(typename);
5808                     out.append("/");
5809                     out.append(entryname);
5810                 } catch (Resources.NotFoundException e) {
5811                 }
5812             }
5813         }
5814         out.append("}");
5815         return out.toString();
5816     }
5817 
5818     /**
5819      * <p>
5820      * Initializes the fading edges from a given set of styled attributes. This
5821      * method should be called by subclasses that need fading edges and when an
5822      * instance of these subclasses is created programmatically rather than
5823      * being inflated from XML. This method is automatically called when the XML
5824      * is inflated.
5825      * </p>
5826      *
5827      * @param a the styled attributes set to initialize the fading edges from
5828      *
5829      * @removed
5830      */
5831     protected void initializeFadingEdge(TypedArray a) {
5832         // This method probably shouldn't have been included in the SDK to begin with.
5833         // It relies on 'a' having been initialized using an attribute filter array that is
5834         // not publicly available to the SDK. The old method has been renamed
5835         // to initializeFadingEdgeInternal and hidden for framework use only;
5836         // this one initializes using defaults to make it safe to call for apps.
5837 
5838         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5839 
5840         initializeFadingEdgeInternal(arr);
5841 
5842         arr.recycle();
5843     }
5844 
5845     /**
5846      * <p>
5847      * Initializes the fading edges from a given set of styled attributes. This
5848      * method should be called by subclasses that need fading edges and when an
5849      * instance of these subclasses is created programmatically rather than
5850      * being inflated from XML. This method is automatically called when the XML
5851      * is inflated.
5852      * </p>
5853      *
5854      * @param a the styled attributes set to initialize the fading edges from
5855      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5856      */
5857     protected void initializeFadingEdgeInternal(TypedArray a) {
5858         initScrollCache();
5859 
5860         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5861                 R.styleable.View_fadingEdgeLength,
5862                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5863     }
5864 
5865     /**
5866      * Returns the size of the vertical faded edges used to indicate that more
5867      * content in this view is visible.
5868      *
5869      * @return The size in pixels of the vertical faded edge or 0 if vertical
5870      *         faded edges are not enabled for this view.
5871      * @attr ref android.R.styleable#View_fadingEdgeLength
5872      */
5873     public int getVerticalFadingEdgeLength() {
5874         if (isVerticalFadingEdgeEnabled()) {
5875             ScrollabilityCache cache = mScrollCache;
5876             if (cache != null) {
5877                 return cache.fadingEdgeLength;
5878             }
5879         }
5880         return 0;
5881     }
5882 
5883     /**
5884      * Set the size of the faded edge used to indicate that more content in this
5885      * view is available.  Will not change whether the fading edge is enabled; use
5886      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5887      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5888      * for the vertical or horizontal fading edges.
5889      *
5890      * @param length The size in pixels of the faded edge used to indicate that more
5891      *        content in this view is visible.
5892      */
5893     public void setFadingEdgeLength(int length) {
5894         initScrollCache();
5895         mScrollCache.fadingEdgeLength = length;
5896     }
5897 
5898     /**
5899      * Returns the size of the horizontal faded edges used to indicate that more
5900      * content in this view is visible.
5901      *
5902      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5903      *         faded edges are not enabled for this view.
5904      * @attr ref android.R.styleable#View_fadingEdgeLength
5905      */
5906     public int getHorizontalFadingEdgeLength() {
5907         if (isHorizontalFadingEdgeEnabled()) {
5908             ScrollabilityCache cache = mScrollCache;
5909             if (cache != null) {
5910                 return cache.fadingEdgeLength;
5911             }
5912         }
5913         return 0;
5914     }
5915 
5916     /**
5917      * Returns the width of the vertical scrollbar.
5918      *
5919      * @return The width in pixels of the vertical scrollbar or 0 if there
5920      *         is no vertical scrollbar.
5921      */
5922     public int getVerticalScrollbarWidth() {
5923         ScrollabilityCache cache = mScrollCache;
5924         if (cache != null) {
5925             ScrollBarDrawable scrollBar = cache.scrollBar;
5926             if (scrollBar != null) {
5927                 int size = scrollBar.getSize(true);
5928                 if (size <= 0) {
5929                     size = cache.scrollBarSize;
5930                 }
5931                 return size;
5932             }
5933             return 0;
5934         }
5935         return 0;
5936     }
5937 
5938     /**
5939      * Returns the height of the horizontal scrollbar.
5940      *
5941      * @return The height in pixels of the horizontal scrollbar or 0 if
5942      *         there is no horizontal scrollbar.
5943      */
5944     protected int getHorizontalScrollbarHeight() {
5945         ScrollabilityCache cache = mScrollCache;
5946         if (cache != null) {
5947             ScrollBarDrawable scrollBar = cache.scrollBar;
5948             if (scrollBar != null) {
5949                 int size = scrollBar.getSize(false);
5950                 if (size <= 0) {
5951                     size = cache.scrollBarSize;
5952                 }
5953                 return size;
5954             }
5955             return 0;
5956         }
5957         return 0;
5958     }
5959 
5960     /**
5961      * <p>
5962      * Initializes the scrollbars from a given set of styled attributes. This
5963      * method should be called by subclasses that need scrollbars and when an
5964      * instance of these subclasses is created programmatically rather than
5965      * being inflated from XML. This method is automatically called when the XML
5966      * is inflated.
5967      * </p>
5968      *
5969      * @param a the styled attributes set to initialize the scrollbars from
5970      *
5971      * @removed
5972      */
5973     protected void initializeScrollbars(TypedArray a) {
5974         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5975         // using the View filter array which is not available to the SDK. As such, internal
5976         // framework usage now uses initializeScrollbarsInternal and we grab a default
5977         // TypedArray with the right filter instead here.
5978         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5979 
5980         initializeScrollbarsInternal(arr);
5981 
5982         // We ignored the method parameter. Recycle the one we actually did use.
5983         arr.recycle();
5984     }
5985 
5986     /**
5987      * <p>
5988      * Initializes the scrollbars from a given set of styled attributes. This
5989      * method should be called by subclasses that need scrollbars and when an
5990      * instance of these subclasses is created programmatically rather than
5991      * being inflated from XML. This method is automatically called when the XML
5992      * is inflated.
5993      * </p>
5994      *
5995      * @param a the styled attributes set to initialize the scrollbars from
5996      * @hide
5997      */
5998     protected void initializeScrollbarsInternal(TypedArray a) {
5999         initScrollCache();
6000 
6001         final ScrollabilityCache scrollabilityCache = mScrollCache;
6002 
6003         if (scrollabilityCache.scrollBar == null) {
6004             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6005             scrollabilityCache.scrollBar.setState(getDrawableState());
6006             scrollabilityCache.scrollBar.setCallback(this);
6007         }
6008 
6009         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6010 
6011         if (!fadeScrollbars) {
6012             scrollabilityCache.state = ScrollabilityCache.ON;
6013         }
6014         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6015 
6016 
6017         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6018                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6019                         .getScrollBarFadeDuration());
6020         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6021                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6022                 ViewConfiguration.getScrollDefaultDelay());
6023 
6024 
6025         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6026                 com.android.internal.R.styleable.View_scrollbarSize,
6027                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6028 
6029         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6030         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6031 
6032         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6033         if (thumb != null) {
6034             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6035         }
6036 
6037         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6038                 false);
6039         if (alwaysDraw) {
6040             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6041         }
6042 
6043         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6044         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6045 
6046         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6047         if (thumb != null) {
6048             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6049         }
6050 
6051         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6052                 false);
6053         if (alwaysDraw) {
6054             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6055         }
6056 
6057         // Apply layout direction to the new Drawables if needed
6058         final int layoutDirection = getLayoutDirection();
6059         if (track != null) {
6060             track.setLayoutDirection(layoutDirection);
6061         }
6062         if (thumb != null) {
6063             thumb.setLayoutDirection(layoutDirection);
6064         }
6065 
6066         // Re-apply user/background padding so that scrollbar(s) get added
6067         resolvePadding();
6068     }
6069 
6070     private void initializeScrollIndicatorsInternal() {
6071         // Some day maybe we'll break this into top/left/start/etc. and let the
6072         // client control it. Until then, you can have any scroll indicator you
6073         // want as long as it's a 1dp foreground-colored rectangle.
6074         if (mScrollIndicatorDrawable == null) {
6075             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
6076         }
6077     }
6078 
6079     /**
6080      * <p>
6081      * Initalizes the scrollability cache if necessary.
6082      * </p>
6083      */
6084     private void initScrollCache() {
6085         if (mScrollCache == null) {
6086             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
6087         }
6088     }
6089 
6090     private ScrollabilityCache getScrollCache() {
6091         initScrollCache();
6092         return mScrollCache;
6093     }
6094 
6095     /**
6096      * Set the position of the vertical scroll bar. Should be one of
6097      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
6098      * {@link #SCROLLBAR_POSITION_RIGHT}.
6099      *
6100      * @param position Where the vertical scroll bar should be positioned.
6101      */
6102     public void setVerticalScrollbarPosition(int position) {
6103         if (mVerticalScrollbarPosition != position) {
6104             mVerticalScrollbarPosition = position;
6105             computeOpaqueFlags();
6106             resolvePadding();
6107         }
6108     }
6109 
6110     /**
6111      * @return The position where the vertical scroll bar will show, if applicable.
6112      * @see #setVerticalScrollbarPosition(int)
6113      */
6114     public int getVerticalScrollbarPosition() {
6115         return mVerticalScrollbarPosition;
6116     }
6117 
6118     boolean isOnScrollbar(float x, float y) {
6119         if (mScrollCache == null) {
6120             return false;
6121         }
6122         x += getScrollX();
6123         y += getScrollY();
6124         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
6125             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6126             getVerticalScrollBarBounds(null, touchBounds);
6127             if (touchBounds.contains((int) x, (int) y)) {
6128                 return true;
6129             }
6130         }
6131         if (isHorizontalScrollBarEnabled()) {
6132             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6133             getHorizontalScrollBarBounds(null, touchBounds);
6134             if (touchBounds.contains((int) x, (int) y)) {
6135                 return true;
6136             }
6137         }
6138         return false;
6139     }
6140 
6141     boolean isOnScrollbarThumb(float x, float y) {
6142         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
6143     }
6144 
6145     private boolean isOnVerticalScrollbarThumb(float x, float y) {
6146         if (mScrollCache == null) {
6147             return false;
6148         }
6149         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
6150             x += getScrollX();
6151             y += getScrollY();
6152             final Rect bounds = mScrollCache.mScrollBarBounds;
6153             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6154             getVerticalScrollBarBounds(bounds, touchBounds);
6155             final int range = computeVerticalScrollRange();
6156             final int offset = computeVerticalScrollOffset();
6157             final int extent = computeVerticalScrollExtent();
6158             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
6159                     extent, range);
6160             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
6161                     extent, range, offset);
6162             final int thumbTop = bounds.top + thumbOffset;
6163             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6164             if (x >= touchBounds.left && x <= touchBounds.right
6165                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
6166                 return true;
6167             }
6168         }
6169         return false;
6170     }
6171 
6172     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
6173         if (mScrollCache == null) {
6174             return false;
6175         }
6176         if (isHorizontalScrollBarEnabled()) {
6177             x += getScrollX();
6178             y += getScrollY();
6179             final Rect bounds = mScrollCache.mScrollBarBounds;
6180             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6181             getHorizontalScrollBarBounds(bounds, touchBounds);
6182             final int range = computeHorizontalScrollRange();
6183             final int offset = computeHorizontalScrollOffset();
6184             final int extent = computeHorizontalScrollExtent();
6185             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
6186                     extent, range);
6187             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
6188                     extent, range, offset);
6189             final int thumbLeft = bounds.left + thumbOffset;
6190             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6191             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
6192                     && y >= touchBounds.top && y <= touchBounds.bottom) {
6193                 return true;
6194             }
6195         }
6196         return false;
6197     }
6198 
6199     boolean isDraggingScrollBar() {
6200         return mScrollCache != null
6201                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
6202     }
6203 
6204     /**
6205      * Sets the state of all scroll indicators.
6206      * <p>
6207      * See {@link #setScrollIndicators(int, int)} for usage information.
6208      *
6209      * @param indicators a bitmask of indicators that should be enabled, or
6210      *                   {@code 0} to disable all indicators
6211      * @see #setScrollIndicators(int, int)
6212      * @see #getScrollIndicators()
6213      * @attr ref android.R.styleable#View_scrollIndicators
6214      */
6215     public void setScrollIndicators(@ScrollIndicators int indicators) {
6216         setScrollIndicators(indicators,
6217                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
6218     }
6219 
6220     /**
6221      * Sets the state of the scroll indicators specified by the mask. To change
6222      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
6223      * <p>
6224      * When a scroll indicator is enabled, it will be displayed if the view
6225      * can scroll in the direction of the indicator.
6226      * <p>
6227      * Multiple indicator types may be enabled or disabled by passing the
6228      * logical OR of the desired types. If multiple types are specified, they
6229      * will all be set to the same enabled state.
6230      * <p>
6231      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
6232      *
6233      * @param indicators the indicator direction, or the logical OR of multiple
6234      *             indicator directions. One or more of:
6235      *             <ul>
6236      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
6237      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
6238      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
6239      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
6240      *               <li>{@link #SCROLL_INDICATOR_START}</li>
6241      *               <li>{@link #SCROLL_INDICATOR_END}</li>
6242      *             </ul>
6243      * @see #setScrollIndicators(int)
6244      * @see #getScrollIndicators()
6245      * @attr ref android.R.styleable#View_scrollIndicators
6246      */
6247     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
6248         // Shift and sanitize mask.
6249         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6250         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
6251 
6252         // Shift and mask indicators.
6253         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6254         indicators &= mask;
6255 
6256         // Merge with non-masked flags.
6257         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
6258 
6259         if (mPrivateFlags3 != updatedFlags) {
6260             mPrivateFlags3 = updatedFlags;
6261 
6262             if (indicators != 0) {
6263                 initializeScrollIndicatorsInternal();
6264             }
6265             invalidate();
6266         }
6267     }
6268 
6269     /**
6270      * Returns a bitmask representing the enabled scroll indicators.
6271      * <p>
6272      * For example, if the top and left scroll indicators are enabled and all
6273      * other indicators are disabled, the return value will be
6274      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
6275      * <p>
6276      * To check whether the bottom scroll indicator is enabled, use the value
6277      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
6278      *
6279      * @return a bitmask representing the enabled scroll indicators
6280      */
6281     @ScrollIndicators
6282     public int getScrollIndicators() {
6283         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
6284                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6285     }
6286 
6287     ListenerInfo getListenerInfo() {
6288         if (mListenerInfo != null) {
6289             return mListenerInfo;
6290         }
6291         mListenerInfo = new ListenerInfo();
6292         return mListenerInfo;
6293     }
6294 
6295     /**
6296      * Register a callback to be invoked when the scroll X or Y positions of
6297      * this view change.
6298      * <p>
6299      * <b>Note:</b> Some views handle scrolling independently from View and may
6300      * have their own separate listeners for scroll-type events. For example,
6301      * {@link android.widget.ListView ListView} allows clients to register an
6302      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
6303      * to listen for changes in list scroll position.
6304      *
6305      * @param l The listener to notify when the scroll X or Y position changes.
6306      * @see android.view.View#getScrollX()
6307      * @see android.view.View#getScrollY()
6308      */
6309     public void setOnScrollChangeListener(OnScrollChangeListener l) {
6310         getListenerInfo().mOnScrollChangeListener = l;
6311     }
6312 
6313     /**
6314      * Register a callback to be invoked when focus of this view changed.
6315      *
6316      * @param l The callback that will run.
6317      */
6318     public void setOnFocusChangeListener(OnFocusChangeListener l) {
6319         getListenerInfo().mOnFocusChangeListener = l;
6320     }
6321 
6322     /**
6323      * Add a listener that will be called when the bounds of the view change due to
6324      * layout processing.
6325      *
6326      * @param listener The listener that will be called when layout bounds change.
6327      */
6328     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6329         ListenerInfo li = getListenerInfo();
6330         if (li.mOnLayoutChangeListeners == null) {
6331             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6332         }
6333         if (!li.mOnLayoutChangeListeners.contains(listener)) {
6334             li.mOnLayoutChangeListeners.add(listener);
6335         }
6336     }
6337 
6338     /**
6339      * Remove a listener for layout changes.
6340      *
6341      * @param listener The listener for layout bounds change.
6342      */
6343     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6344         ListenerInfo li = mListenerInfo;
6345         if (li == null || li.mOnLayoutChangeListeners == null) {
6346             return;
6347         }
6348         li.mOnLayoutChangeListeners.remove(listener);
6349     }
6350 
6351     /**
6352      * Add a listener for attach state changes.
6353      *
6354      * This listener will be called whenever this view is attached or detached
6355      * from a window. Remove the listener using
6356      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6357      *
6358      * @param listener Listener to attach
6359      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6360      */
6361     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6362         ListenerInfo li = getListenerInfo();
6363         if (li.mOnAttachStateChangeListeners == null) {
6364             li.mOnAttachStateChangeListeners
6365                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6366         }
6367         li.mOnAttachStateChangeListeners.add(listener);
6368     }
6369 
6370     /**
6371      * Remove a listener for attach state changes. The listener will receive no further
6372      * notification of window attach/detach events.
6373      *
6374      * @param listener Listener to remove
6375      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6376      */
6377     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6378         ListenerInfo li = mListenerInfo;
6379         if (li == null || li.mOnAttachStateChangeListeners == null) {
6380             return;
6381         }
6382         li.mOnAttachStateChangeListeners.remove(listener);
6383     }
6384 
6385     /**
6386      * Returns the focus-change callback registered for this view.
6387      *
6388      * @return The callback, or null if one is not registered.
6389      */
6390     public OnFocusChangeListener getOnFocusChangeListener() {
6391         ListenerInfo li = mListenerInfo;
6392         return li != null ? li.mOnFocusChangeListener : null;
6393     }
6394 
6395     /**
6396      * Register a callback to be invoked when this view is clicked. If this view is not
6397      * clickable, it becomes clickable.
6398      *
6399      * @param l The callback that will run
6400      *
6401      * @see #setClickable(boolean)
6402      */
6403     public void setOnClickListener(@Nullable OnClickListener l) {
6404         if (!isClickable()) {
6405             setClickable(true);
6406         }
6407         getListenerInfo().mOnClickListener = l;
6408     }
6409 
6410     /**
6411      * Return whether this view has an attached OnClickListener.  Returns
6412      * true if there is a listener, false if there is none.
6413      */
6414     public boolean hasOnClickListeners() {
6415         ListenerInfo li = mListenerInfo;
6416         return (li != null && li.mOnClickListener != null);
6417     }
6418 
6419     /**
6420      * Register a callback to be invoked when this view is clicked and held. If this view is not
6421      * long clickable, it becomes long clickable.
6422      *
6423      * @param l The callback that will run
6424      *
6425      * @see #setLongClickable(boolean)
6426      */
6427     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6428         if (!isLongClickable()) {
6429             setLongClickable(true);
6430         }
6431         getListenerInfo().mOnLongClickListener = l;
6432     }
6433 
6434     /**
6435      * Register a callback to be invoked when this view is context clicked. If the view is not
6436      * context clickable, it becomes context clickable.
6437      *
6438      * @param l The callback that will run
6439      * @see #setContextClickable(boolean)
6440      */
6441     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6442         if (!isContextClickable()) {
6443             setContextClickable(true);
6444         }
6445         getListenerInfo().mOnContextClickListener = l;
6446     }
6447 
6448     /**
6449      * Register a callback to be invoked when the context menu for this view is
6450      * being built. If this view is not long clickable, it becomes long clickable.
6451      *
6452      * @param l The callback that will run
6453      *
6454      */
6455     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6456         if (!isLongClickable()) {
6457             setLongClickable(true);
6458         }
6459         getListenerInfo().mOnCreateContextMenuListener = l;
6460     }
6461 
6462     /**
6463      * Set an observer to collect stats for each frame rendered for this view.
6464      *
6465      * @hide
6466      */
6467     public void addFrameMetricsListener(Window window,
6468             Window.OnFrameMetricsAvailableListener listener,
6469             Handler handler) {
6470         if (mAttachInfo != null) {
6471             if (mAttachInfo.mThreadedRenderer != null) {
6472                 if (mFrameMetricsObservers == null) {
6473                     mFrameMetricsObservers = new ArrayList<>();
6474                 }
6475 
6476                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6477                         handler.getLooper(), listener);
6478                 mFrameMetricsObservers.add(fmo);
6479                 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6480             } else {
6481                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6482             }
6483         } else {
6484             if (mFrameMetricsObservers == null) {
6485                 mFrameMetricsObservers = new ArrayList<>();
6486             }
6487 
6488             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6489                     handler.getLooper(), listener);
6490             mFrameMetricsObservers.add(fmo);
6491         }
6492     }
6493 
6494     /**
6495      * Remove observer configured to collect frame stats for this view.
6496      *
6497      * @hide
6498      */
6499     public void removeFrameMetricsListener(
6500             Window.OnFrameMetricsAvailableListener listener) {
6501         ThreadedRenderer renderer = getThreadedRenderer();
6502         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6503         if (fmo == null) {
6504             throw new IllegalArgumentException(
6505                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
6506         }
6507 
6508         if (mFrameMetricsObservers != null) {
6509             mFrameMetricsObservers.remove(fmo);
6510             if (renderer != null) {
6511                 renderer.removeFrameMetricsObserver(fmo);
6512             }
6513         }
6514     }
6515 
6516     private void registerPendingFrameMetricsObservers() {
6517         if (mFrameMetricsObservers != null) {
6518             ThreadedRenderer renderer = getThreadedRenderer();
6519             if (renderer != null) {
6520                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6521                     renderer.addFrameMetricsObserver(fmo);
6522                 }
6523             } else {
6524                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6525             }
6526         }
6527     }
6528 
6529     private FrameMetricsObserver findFrameMetricsObserver(
6530             Window.OnFrameMetricsAvailableListener listener) {
6531         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6532             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6533             if (observer.mListener == listener) {
6534                 return observer;
6535             }
6536         }
6537 
6538         return null;
6539     }
6540 
6541     /** @hide */
6542     public void setNotifyAutofillManagerOnClick(boolean notify) {
6543         if (notify) {
6544             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
6545         } else {
6546             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
6547         }
6548     }
6549 
6550     private void notifyAutofillManagerOnClick() {
6551         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
6552             try {
6553                 getAutofillManager().notifyViewClicked(this);
6554             } finally {
6555                 // Set it to already called so it's not called twice when called by
6556                 // performClickInternal()
6557                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
6558             }
6559         }
6560     }
6561 
6562     /**
6563      * Entry point for {@link #performClick()} - other methods on View should call it instead of
6564      * {@code performClick()} directly to make sure the autofill manager is notified when
6565      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
6566      * method).
6567      */
6568     private boolean performClickInternal() {
6569         // Must notify autofill manager before performing the click actions to avoid scenarios where
6570         // the app has a click listener that changes the state of views the autofill service might
6571         // be interested on.
6572         notifyAutofillManagerOnClick();
6573 
6574         return performClick();
6575     }
6576 
6577     /**
6578      * Call this view's OnClickListener, if it is defined.  Performs all normal
6579      * actions associated with clicking: reporting accessibility event, playing
6580      * a sound, etc.
6581      *
6582      * @return True there was an assigned OnClickListener that was called, false
6583      *         otherwise is returned.
6584      */
6585     // NOTE: other methods on View should not call this method directly, but performClickInternal()
6586     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
6587     // could extend this method without calling super.performClick()).
6588     public boolean performClick() {
6589         // We still need to call this method to handle the cases where performClick() was called
6590         // externally, instead of through performClickInternal()
6591         notifyAutofillManagerOnClick();
6592 
6593         final boolean result;
6594         final ListenerInfo li = mListenerInfo;
6595         if (li != null && li.mOnClickListener != null) {
6596             playSoundEffect(SoundEffectConstants.CLICK);
6597             li.mOnClickListener.onClick(this);
6598             result = true;
6599         } else {
6600             result = false;
6601         }
6602 
6603         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6604 
6605         notifyEnterOrExitForAutoFillIfNeeded(true);
6606 
6607         return result;
6608     }
6609 
6610     /**
6611      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6612      * this only calls the listener, and does not do any associated clicking
6613      * actions like reporting an accessibility event.
6614      *
6615      * @return True there was an assigned OnClickListener that was called, false
6616      *         otherwise is returned.
6617      */
6618     public boolean callOnClick() {
6619         ListenerInfo li = mListenerInfo;
6620         if (li != null && li.mOnClickListener != null) {
6621             li.mOnClickListener.onClick(this);
6622             return true;
6623         }
6624         return false;
6625     }
6626 
6627     /**
6628      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6629      * context menu if the OnLongClickListener did not consume the event.
6630      *
6631      * @return {@code true} if one of the above receivers consumed the event,
6632      *         {@code false} otherwise
6633      */
6634     public boolean performLongClick() {
6635         return performLongClickInternal(mLongClickX, mLongClickY);
6636     }
6637 
6638     /**
6639      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6640      * context menu if the OnLongClickListener did not consume the event,
6641      * anchoring it to an (x,y) coordinate.
6642      *
6643      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6644      *          to disable anchoring
6645      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6646      *          to disable anchoring
6647      * @return {@code true} if one of the above receivers consumed the event,
6648      *         {@code false} otherwise
6649      */
6650     public boolean performLongClick(float x, float y) {
6651         mLongClickX = x;
6652         mLongClickY = y;
6653         final boolean handled = performLongClick();
6654         mLongClickX = Float.NaN;
6655         mLongClickY = Float.NaN;
6656         return handled;
6657     }
6658 
6659     /**
6660      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6661      * context menu if the OnLongClickListener did not consume the event,
6662      * optionally anchoring it to an (x,y) coordinate.
6663      *
6664      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6665      *          to disable anchoring
6666      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6667      *          to disable anchoring
6668      * @return {@code true} if one of the above receivers consumed the event,
6669      *         {@code false} otherwise
6670      */
6671     private boolean performLongClickInternal(float x, float y) {
6672         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6673 
6674         boolean handled = false;
6675         final ListenerInfo li = mListenerInfo;
6676         if (li != null && li.mOnLongClickListener != null) {
6677             handled = li.mOnLongClickListener.onLongClick(View.this);
6678         }
6679         if (!handled) {
6680             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6681             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6682         }
6683         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6684             if (!handled) {
6685                 handled = showLongClickTooltip((int) x, (int) y);
6686             }
6687         }
6688         if (handled) {
6689             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6690         }
6691         return handled;
6692     }
6693 
6694     /**
6695      * Call this view's OnContextClickListener, if it is defined.
6696      *
6697      * @param x the x coordinate of the context click
6698      * @param y the y coordinate of the context click
6699      * @return True if there was an assigned OnContextClickListener that consumed the event, false
6700      *         otherwise.
6701      */
6702     public boolean performContextClick(float x, float y) {
6703         return performContextClick();
6704     }
6705 
6706     /**
6707      * Call this view's OnContextClickListener, if it is defined.
6708      *
6709      * @return True if there was an assigned OnContextClickListener that consumed the event, false
6710      *         otherwise.
6711      */
6712     public boolean performContextClick() {
6713         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6714 
6715         boolean handled = false;
6716         ListenerInfo li = mListenerInfo;
6717         if (li != null && li.mOnContextClickListener != null) {
6718             handled = li.mOnContextClickListener.onContextClick(View.this);
6719         }
6720         if (handled) {
6721             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6722         }
6723         return handled;
6724     }
6725 
6726     /**
6727      * Performs button-related actions during a touch down event.
6728      *
6729      * @param event The event.
6730      * @return True if the down was consumed.
6731      *
6732      * @hide
6733      */
6734     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6735         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6736             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6737             showContextMenu(event.getX(), event.getY());
6738             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6739             return true;
6740         }
6741         return false;
6742     }
6743 
6744     /**
6745      * Shows the context menu for this view.
6746      *
6747      * @return {@code true} if the context menu was shown, {@code false}
6748      *         otherwise
6749      * @see #showContextMenu(float, float)
6750      */
6751     public boolean showContextMenu() {
6752         return getParent().showContextMenuForChild(this);
6753     }
6754 
6755     /**
6756      * Shows the context menu for this view anchored to the specified
6757      * view-relative coordinate.
6758      *
6759      * @param x the X coordinate in pixels relative to the view to which the
6760      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6761      * @param y the Y coordinate in pixels relative to the view to which the
6762      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6763      * @return {@code true} if the context menu was shown, {@code false}
6764      *         otherwise
6765      */
6766     public boolean showContextMenu(float x, float y) {
6767         return getParent().showContextMenuForChild(this, x, y);
6768     }
6769 
6770     /**
6771      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6772      *
6773      * @param callback Callback that will control the lifecycle of the action mode
6774      * @return The new action mode if it is started, null otherwise
6775      *
6776      * @see ActionMode
6777      * @see #startActionMode(android.view.ActionMode.Callback, int)
6778      */
6779     public ActionMode startActionMode(ActionMode.Callback callback) {
6780         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6781     }
6782 
6783     /**
6784      * Start an action mode with the given type.
6785      *
6786      * @param callback Callback that will control the lifecycle of the action mode
6787      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6788      * @return The new action mode if it is started, null otherwise
6789      *
6790      * @see ActionMode
6791      */
6792     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6793         ViewParent parent = getParent();
6794         if (parent == null) return null;
6795         try {
6796             return parent.startActionModeForChild(this, callback, type);
6797         } catch (AbstractMethodError ame) {
6798             // Older implementations of custom views might not implement this.
6799             return parent.startActionModeForChild(this, callback);
6800         }
6801     }
6802 
6803     /**
6804      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6805      * Context, creating a unique View identifier to retrieve the result.
6806      *
6807      * @param intent The Intent to be started.
6808      * @param requestCode The request code to use.
6809      * @hide
6810      */
6811     public void startActivityForResult(Intent intent, int requestCode) {
6812         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6813         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6814     }
6815 
6816     /**
6817      * If this View corresponds to the calling who, dispatches the activity result.
6818      * @param who The identifier for the targeted View to receive the result.
6819      * @param requestCode The integer request code originally supplied to
6820      *                    startActivityForResult(), allowing you to identify who this
6821      *                    result came from.
6822      * @param resultCode The integer result code returned by the child activity
6823      *                   through its setResult().
6824      * @param data An Intent, which can return result data to the caller
6825      *               (various data can be attached to Intent "extras").
6826      * @return {@code true} if the activity result was dispatched.
6827      * @hide
6828      */
6829     public boolean dispatchActivityResult(
6830             String who, int requestCode, int resultCode, Intent data) {
6831         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6832             onActivityResult(requestCode, resultCode, data);
6833             mStartActivityRequestWho = null;
6834             return true;
6835         }
6836         return false;
6837     }
6838 
6839     /**
6840      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6841      *
6842      * @param requestCode The integer request code originally supplied to
6843      *                    startActivityForResult(), allowing you to identify who this
6844      *                    result came from.
6845      * @param resultCode The integer result code returned by the child activity
6846      *                   through its setResult().
6847      * @param data An Intent, which can return result data to the caller
6848      *               (various data can be attached to Intent "extras").
6849      * @hide
6850      */
6851     public void onActivityResult(int requestCode, int resultCode, Intent data) {
6852         // Do nothing.
6853     }
6854 
6855     /**
6856      * Register a callback to be invoked when a hardware key is pressed in this view.
6857      * Key presses in software input methods will generally not trigger the methods of
6858      * this listener.
6859      * @param l the key listener to attach to this view
6860      */
6861     public void setOnKeyListener(OnKeyListener l) {
6862         getListenerInfo().mOnKeyListener = l;
6863     }
6864 
6865     /**
6866      * Register a callback to be invoked when a touch event is sent to this view.
6867      * @param l the touch listener to attach to this view
6868      */
6869     public void setOnTouchListener(OnTouchListener l) {
6870         getListenerInfo().mOnTouchListener = l;
6871     }
6872 
6873     /**
6874      * Register a callback to be invoked when a generic motion event is sent to this view.
6875      * @param l the generic motion listener to attach to this view
6876      */
6877     public void setOnGenericMotionListener(OnGenericMotionListener l) {
6878         getListenerInfo().mOnGenericMotionListener = l;
6879     }
6880 
6881     /**
6882      * Register a callback to be invoked when a hover event is sent to this view.
6883      * @param l the hover listener to attach to this view
6884      */
6885     public void setOnHoverListener(OnHoverListener l) {
6886         getListenerInfo().mOnHoverListener = l;
6887     }
6888 
6889     /**
6890      * Register a drag event listener callback object for this View. The parameter is
6891      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6892      * View, the system calls the
6893      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6894      * @param l An implementation of {@link android.view.View.OnDragListener}.
6895      */
6896     public void setOnDragListener(OnDragListener l) {
6897         getListenerInfo().mOnDragListener = l;
6898     }
6899 
6900     /**
6901      * Give this view focus. This will cause
6902      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6903      *
6904      * Note: this does not check whether this {@link View} should get focus, it just
6905      * gives it focus no matter what.  It should only be called internally by framework
6906      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6907      *
6908      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6909      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6910      *        focus moved when requestFocus() is called. It may not always
6911      *        apply, in which case use the default View.FOCUS_DOWN.
6912      * @param previouslyFocusedRect The rectangle of the view that had focus
6913      *        prior in this View's coordinate system.
6914      */
6915     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6916         if (DBG) {
6917             System.out.println(this + " requestFocus()");
6918         }
6919 
6920         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6921             mPrivateFlags |= PFLAG_FOCUSED;
6922 
6923             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6924 
6925             if (mParent != null) {
6926                 mParent.requestChildFocus(this, this);
6927                 updateFocusedInCluster(oldFocus, direction);
6928             }
6929 
6930             if (mAttachInfo != null) {
6931                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6932             }
6933 
6934             onFocusChanged(true, direction, previouslyFocusedRect);
6935             refreshDrawableState();
6936         }
6937     }
6938 
6939     /**
6940      * Sets this view's preference for reveal behavior when it gains focus.
6941      *
6942      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6943      * this view would prefer to be brought fully into view when it gains focus.
6944      * For example, a text field that a user is meant to type into. Other views such
6945      * as scrolling containers may prefer to opt-out of this behavior.</p>
6946      *
6947      * <p>The default value for views is true, though subclasses may change this
6948      * based on their preferred behavior.</p>
6949      *
6950      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6951      *
6952      * @see #getRevealOnFocusHint()
6953      */
6954     public final void setRevealOnFocusHint(boolean revealOnFocus) {
6955         if (revealOnFocus) {
6956             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6957         } else {
6958             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6959         }
6960     }
6961 
6962     /**
6963      * Returns this view's preference for reveal behavior when it gains focus.
6964      *
6965      * <p>When this method returns true for a child view requesting focus, ancestor
6966      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6967      * should make a best effort to make the newly focused child fully visible to the user.
6968      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6969      * other properties affecting visibility to the user as part of the focus change.</p>
6970      *
6971      * @return true if this view would prefer to become fully visible when it gains focus,
6972      *         false if it would prefer not to disrupt scroll positioning
6973      *
6974      * @see #setRevealOnFocusHint(boolean)
6975      */
6976     public final boolean getRevealOnFocusHint() {
6977         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6978     }
6979 
6980     /**
6981      * Populates <code>outRect</code> with the hotspot bounds. By default,
6982      * the hotspot bounds are identical to the screen bounds.
6983      *
6984      * @param outRect rect to populate with hotspot bounds
6985      * @hide Only for internal use by views and widgets.
6986      */
6987     public void getHotspotBounds(Rect outRect) {
6988         final Drawable background = getBackground();
6989         if (background != null) {
6990             background.getHotspotBounds(outRect);
6991         } else {
6992             getBoundsOnScreen(outRect);
6993         }
6994     }
6995 
6996     /**
6997      * Request that a rectangle of this view be visible on the screen,
6998      * scrolling if necessary just enough.
6999      *
7000      * <p>A View should call this if it maintains some notion of which part
7001      * of its content is interesting.  For example, a text editing view
7002      * should call this when its cursor moves.
7003      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7004      * It should not be affected by which part of the View is currently visible or its scroll
7005      * position.
7006      *
7007      * @param rectangle The rectangle in the View's content coordinate space
7008      * @return Whether any parent scrolled.
7009      */
7010     public boolean requestRectangleOnScreen(Rect rectangle) {
7011         return requestRectangleOnScreen(rectangle, false);
7012     }
7013 
7014     /**
7015      * Request that a rectangle of this view be visible on the screen,
7016      * scrolling if necessary just enough.
7017      *
7018      * <p>A View should call this if it maintains some notion of which part
7019      * of its content is interesting.  For example, a text editing view
7020      * should call this when its cursor moves.
7021      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7022      * It should not be affected by which part of the View is currently visible or its scroll
7023      * position.
7024      * <p>When <code>immediate</code> is set to true, scrolling will not be
7025      * animated.
7026      *
7027      * @param rectangle The rectangle in the View's content coordinate space
7028      * @param immediate True to forbid animated scrolling, false otherwise
7029      * @return Whether any parent scrolled.
7030      */
7031     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
7032         if (mParent == null) {
7033             return false;
7034         }
7035 
7036         View child = this;
7037 
7038         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
7039         position.set(rectangle);
7040 
7041         ViewParent parent = mParent;
7042         boolean scrolled = false;
7043         while (parent != null) {
7044             rectangle.set((int) position.left, (int) position.top,
7045                     (int) position.right, (int) position.bottom);
7046 
7047             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
7048 
7049             if (!(parent instanceof View)) {
7050                 break;
7051             }
7052 
7053             // move it from child's content coordinate space to parent's content coordinate space
7054             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
7055 
7056             child = (View) parent;
7057             parent = child.getParent();
7058         }
7059 
7060         return scrolled;
7061     }
7062 
7063     /**
7064      * Called when this view wants to give up focus. If focus is cleared
7065      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
7066      * <p>
7067      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
7068      * to the first focusable View from the top after focus is cleared. Hence, if this
7069      * View is the first from the top that can take focus, then all callbacks
7070      * related to clearing focus will be invoked after which the framework will
7071      * give focus to this view.
7072      * </p>
7073      */
7074     public void clearFocus() {
7075         if (DBG) {
7076             System.out.println(this + " clearFocus()");
7077         }
7078 
7079         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
7080         clearFocusInternal(null, true, refocus);
7081     }
7082 
7083     /**
7084      * Clears focus from the view, optionally propagating the change up through
7085      * the parent hierarchy and requesting that the root view place new focus.
7086      *
7087      * @param propagate whether to propagate the change up through the parent
7088      *            hierarchy
7089      * @param refocus when propagate is true, specifies whether to request the
7090      *            root view place new focus
7091      */
7092     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
7093         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
7094             mPrivateFlags &= ~PFLAG_FOCUSED;
7095             clearParentsWantFocus();
7096 
7097             if (propagate && mParent != null) {
7098                 mParent.clearChildFocus(this);
7099             }
7100 
7101             onFocusChanged(false, 0, null);
7102             refreshDrawableState();
7103 
7104             if (propagate && (!refocus || !rootViewRequestFocus())) {
7105                 notifyGlobalFocusCleared(this);
7106             }
7107         }
7108     }
7109 
7110     void notifyGlobalFocusCleared(View oldFocus) {
7111         if (oldFocus != null && mAttachInfo != null) {
7112             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
7113         }
7114     }
7115 
7116     boolean rootViewRequestFocus() {
7117         final View root = getRootView();
7118         return root != null && root.requestFocus();
7119     }
7120 
7121     /**
7122      * Called internally by the view system when a new view is getting focus.
7123      * This is what clears the old focus.
7124      * <p>
7125      * <b>NOTE:</b> The parent view's focused child must be updated manually
7126      * after calling this method. Otherwise, the view hierarchy may be left in
7127      * an inconstent state.
7128      */
7129     void unFocus(View focused) {
7130         if (DBG) {
7131             System.out.println(this + " unFocus()");
7132         }
7133 
7134         clearFocusInternal(focused, false, false);
7135     }
7136 
7137     /**
7138      * Returns true if this view has focus itself, or is the ancestor of the
7139      * view that has focus.
7140      *
7141      * @return True if this view has or contains focus, false otherwise.
7142      */
7143     @ViewDebug.ExportedProperty(category = "focus")
7144     public boolean hasFocus() {
7145         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7146     }
7147 
7148     /**
7149      * Returns true if this view is focusable or if it contains a reachable View
7150      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
7151      * is a view whose parents do not block descendants focus.
7152      * Only {@link #VISIBLE} views are considered focusable.
7153      *
7154      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
7155      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
7156      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
7157      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
7158      * {@code false} for views not explicitly marked as focusable.
7159      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
7160      * behavior.</p>
7161      *
7162      * @return {@code true} if the view is focusable or if the view contains a focusable
7163      *         view, {@code false} otherwise
7164      *
7165      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
7166      * @see ViewGroup#getTouchscreenBlocksFocus()
7167      * @see #hasExplicitFocusable()
7168      */
7169     public boolean hasFocusable() {
7170         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
7171     }
7172 
7173     /**
7174      * Returns true if this view is focusable or if it contains a reachable View
7175      * for which {@link #hasExplicitFocusable()} returns {@code true}.
7176      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
7177      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
7178      * {@link #FOCUSABLE} are considered focusable.
7179      *
7180      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
7181      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
7182      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
7183      * to focusable will not.</p>
7184      *
7185      * @return {@code true} if the view is focusable or if the view contains a focusable
7186      *         view, {@code false} otherwise
7187      *
7188      * @see #hasFocusable()
7189      */
7190     public boolean hasExplicitFocusable() {
7191         return hasFocusable(false, true);
7192     }
7193 
7194     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
7195         if (!isFocusableInTouchMode()) {
7196             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
7197                 final ViewGroup g = (ViewGroup) p;
7198                 if (g.shouldBlockFocusForTouchscreen()) {
7199                     return false;
7200                 }
7201             }
7202         }
7203 
7204         // Invisible, gone, or disabled views are never focusable.
7205         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
7206                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
7207             return false;
7208         }
7209 
7210         // Only use effective focusable value when allowed.
7211         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
7212             return true;
7213         }
7214 
7215         return false;
7216     }
7217 
7218     /**
7219      * Called by the view system when the focus state of this view changes.
7220      * When the focus change event is caused by directional navigation, direction
7221      * and previouslyFocusedRect provide insight into where the focus is coming from.
7222      * When overriding, be sure to call up through to the super class so that
7223      * the standard focus handling will occur.
7224      *
7225      * @param gainFocus True if the View has focus; false otherwise.
7226      * @param direction The direction focus has moved when requestFocus()
7227      *                  is called to give this view focus. Values are
7228      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
7229      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
7230      *                  It may not always apply, in which case use the default.
7231      * @param previouslyFocusedRect The rectangle, in this view's coordinate
7232      *        system, of the previously focused view.  If applicable, this will be
7233      *        passed in as finer grained information about where the focus is coming
7234      *        from (in addition to direction).  Will be <code>null</code> otherwise.
7235      */
7236     @CallSuper
7237     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
7238             @Nullable Rect previouslyFocusedRect) {
7239         if (gainFocus) {
7240             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
7241         } else {
7242             notifyViewAccessibilityStateChangedIfNeeded(
7243                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7244         }
7245 
7246         // Here we check whether we still need the default focus highlight, and switch it on/off.
7247         switchDefaultFocusHighlight();
7248 
7249         InputMethodManager imm = InputMethodManager.peekInstance();
7250         if (!gainFocus) {
7251             if (isPressed()) {
7252                 setPressed(false);
7253             }
7254             if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
7255                 imm.focusOut(this);
7256             }
7257             onFocusLost();
7258         } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
7259             imm.focusIn(this);
7260         }
7261 
7262         invalidate(true);
7263         ListenerInfo li = mListenerInfo;
7264         if (li != null && li.mOnFocusChangeListener != null) {
7265             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
7266         }
7267 
7268         if (mAttachInfo != null) {
7269             mAttachInfo.mKeyDispatchState.reset(this);
7270         }
7271 
7272         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
7273     }
7274 
7275     /** @hide */
7276     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
7277         if (canNotifyAutofillEnterExitEvent()) {
7278             AutofillManager afm = getAutofillManager();
7279             if (afm != null) {
7280                 if (enter && isFocused()) {
7281                     // We have not been laid out yet, hence cannot evaluate
7282                     // whether this view is visible to the user, we will do
7283                     // the evaluation once layout is complete.
7284                     if (!isLaidOut()) {
7285                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
7286                     } else if (isVisibleToUser()) {
7287                         // TODO This is a potential problem that View gets focus before it's visible
7288                         // to User. Ideally View should handle the event when isVisibleToUser()
7289                         // becomes true where it should issue notifyViewEntered().
7290                         afm.notifyViewEntered(this);
7291                     }
7292                 } else if (!enter && !isFocused()) {
7293                     afm.notifyViewExited(this);
7294                 }
7295             }
7296         }
7297     }
7298 
7299     /**
7300      * Visually distinct portion of a window with window-like semantics are considered panes for
7301      * accessibility purposes. One example is the content view of a fragment that is replaced.
7302      * In order for accessibility services to understand a pane's window-like behavior, panes
7303      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
7304      * when they appear, disappear, or change title.
7305      *
7306      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
7307      *                               View is not a pane.
7308      *
7309      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
7310      */
7311     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
7312         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
7313             mAccessibilityPaneTitle = accessibilityPaneTitle;
7314             notifyViewAccessibilityStateChangedIfNeeded(
7315                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
7316         }
7317     }
7318 
7319     /**
7320      * Get the title of the pane for purposes of accessibility.
7321      *
7322      * @return The current pane title.
7323      *
7324      * {@see #setAccessibilityPaneTitle}.
7325      */
7326     @Nullable public CharSequence getAccessibilityPaneTitle() {
7327         return mAccessibilityPaneTitle;
7328     }
7329 
7330     private boolean isAccessibilityPane() {
7331         return mAccessibilityPaneTitle != null;
7332     }
7333 
7334     /**
7335      * Sends an accessibility event of the given type. If accessibility is
7336      * not enabled this method has no effect. The default implementation calls
7337      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
7338      * to populate information about the event source (this View), then calls
7339      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
7340      * populate the text content of the event source including its descendants,
7341      * and last calls
7342      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
7343      * on its parent to request sending of the event to interested parties.
7344      * <p>
7345      * If an {@link AccessibilityDelegate} has been specified via calling
7346      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7347      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
7348      * responsible for handling this call.
7349      * </p>
7350      *
7351      * @param eventType The type of the event to send, as defined by several types from
7352      * {@link android.view.accessibility.AccessibilityEvent}, such as
7353      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
7354      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
7355      *
7356      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7357      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7358      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
7359      * @see AccessibilityDelegate
7360      */
7361     public void sendAccessibilityEvent(int eventType) {
7362         if (mAccessibilityDelegate != null) {
7363             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
7364         } else {
7365             sendAccessibilityEventInternal(eventType);
7366         }
7367     }
7368 
7369     /**
7370      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
7371      * {@link AccessibilityEvent} to make an announcement which is related to some
7372      * sort of a context change for which none of the events representing UI transitions
7373      * is a good fit. For example, announcing a new page in a book. If accessibility
7374      * is not enabled this method does nothing.
7375      *
7376      * @param text The announcement text.
7377      */
7378     public void announceForAccessibility(CharSequence text) {
7379         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
7380             AccessibilityEvent event = AccessibilityEvent.obtain(
7381                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
7382             onInitializeAccessibilityEvent(event);
7383             event.getText().add(text);
7384             event.setContentDescription(null);
7385             mParent.requestSendAccessibilityEvent(this, event);
7386         }
7387     }
7388 
7389     /**
7390      * @see #sendAccessibilityEvent(int)
7391      *
7392      * Note: Called from the default {@link AccessibilityDelegate}.
7393      *
7394      * @hide
7395      */
7396     public void sendAccessibilityEventInternal(int eventType) {
7397         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7398             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
7399         }
7400     }
7401 
7402     /**
7403      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
7404      * takes as an argument an empty {@link AccessibilityEvent} and does not
7405      * perform a check whether accessibility is enabled.
7406      * <p>
7407      * If an {@link AccessibilityDelegate} has been specified via calling
7408      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7409      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
7410      * is responsible for handling this call.
7411      * </p>
7412      *
7413      * @param event The event to send.
7414      *
7415      * @see #sendAccessibilityEvent(int)
7416      */
7417     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
7418         if (mAccessibilityDelegate != null) {
7419             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7420         } else {
7421             sendAccessibilityEventUncheckedInternal(event);
7422         }
7423     }
7424 
7425     /**
7426      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7427      *
7428      * Note: Called from the default {@link AccessibilityDelegate}.
7429      *
7430      * @hide
7431      */
7432     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
7433         // Panes disappearing are relevant even if though the view is no longer visible.
7434         boolean isWindowStateChanged =
7435                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
7436         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
7437                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
7438         if (!isShown() && !isWindowDisappearedEvent) {
7439             return;
7440         }
7441         onInitializeAccessibilityEvent(event);
7442         // Only a subset of accessibility events populates text content.
7443         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
7444             dispatchPopulateAccessibilityEvent(event);
7445         }
7446         // In the beginning we called #isShown(), so we know that getParent() is not null.
7447         ViewParent parent = getParent();
7448         if (parent != null) {
7449             getParent().requestSendAccessibilityEvent(this, event);
7450         }
7451     }
7452 
7453     /**
7454      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
7455      * to its children for adding their text content to the event. Note that the
7456      * event text is populated in a separate dispatch path since we add to the
7457      * event not only the text of the source but also the text of all its descendants.
7458      * A typical implementation will call
7459      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
7460      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7461      * on each child. Override this method if custom population of the event text
7462      * content is required.
7463      * <p>
7464      * If an {@link AccessibilityDelegate} has been specified via calling
7465      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7466      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
7467      * is responsible for handling this call.
7468      * </p>
7469      * <p>
7470      * <em>Note:</em> Accessibility events of certain types are not dispatched for
7471      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
7472      * </p>
7473      *
7474      * @param event The event.
7475      *
7476      * @return True if the event population was completed.
7477      */
7478     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7479         if (mAccessibilityDelegate != null) {
7480             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
7481         } else {
7482             return dispatchPopulateAccessibilityEventInternal(event);
7483         }
7484     }
7485 
7486     /**
7487      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7488      *
7489      * Note: Called from the default {@link AccessibilityDelegate}.
7490      *
7491      * @hide
7492      */
7493     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7494         onPopulateAccessibilityEvent(event);
7495         return false;
7496     }
7497 
7498     /**
7499      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7500      * giving a chance to this View to populate the accessibility event with its
7501      * text content. While this method is free to modify event
7502      * attributes other than text content, doing so should normally be performed in
7503      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7504      * <p>
7505      * Example: Adding formatted date string to an accessibility event in addition
7506      *          to the text added by the super implementation:
7507      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7508      *     super.onPopulateAccessibilityEvent(event);
7509      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7510      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7511      *         mCurrentDate.getTimeInMillis(), flags);
7512      *     event.getText().add(selectedDateUtterance);
7513      * }</pre>
7514      * <p>
7515      * If an {@link AccessibilityDelegate} has been specified via calling
7516      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7517      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7518      * is responsible for handling this call.
7519      * </p>
7520      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7521      * information to the event, in case the default implementation has basic information to add.
7522      * </p>
7523      *
7524      * @param event The accessibility event which to populate.
7525      *
7526      * @see #sendAccessibilityEvent(int)
7527      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7528      */
7529     @CallSuper
7530     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7531         if (mAccessibilityDelegate != null) {
7532             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7533         } else {
7534             onPopulateAccessibilityEventInternal(event);
7535         }
7536     }
7537 
7538     /**
7539      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7540      *
7541      * Note: Called from the default {@link AccessibilityDelegate}.
7542      *
7543      * @hide
7544      */
7545     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7546         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
7547                 && !TextUtils.isEmpty(getAccessibilityPaneTitle())) {
7548             event.getText().add(getAccessibilityPaneTitle());
7549         }
7550     }
7551 
7552     /**
7553      * Initializes an {@link AccessibilityEvent} with information about
7554      * this View which is the event source. In other words, the source of
7555      * an accessibility event is the view whose state change triggered firing
7556      * the event.
7557      * <p>
7558      * Example: Setting the password property of an event in addition
7559      *          to properties set by the super implementation:
7560      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7561      *     super.onInitializeAccessibilityEvent(event);
7562      *     event.setPassword(true);
7563      * }</pre>
7564      * <p>
7565      * If an {@link AccessibilityDelegate} has been specified via calling
7566      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7567      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7568      * is responsible for handling this call.
7569      * </p>
7570      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7571      * information to the event, in case the default implementation has basic information to add.
7572      * </p>
7573      * @param event The event to initialize.
7574      *
7575      * @see #sendAccessibilityEvent(int)
7576      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7577      */
7578     @CallSuper
7579     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7580         if (mAccessibilityDelegate != null) {
7581             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7582         } else {
7583             onInitializeAccessibilityEventInternal(event);
7584         }
7585     }
7586 
7587     /**
7588      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7589      *
7590      * Note: Called from the default {@link AccessibilityDelegate}.
7591      *
7592      * @hide
7593      */
7594     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7595         event.setSource(this);
7596         event.setClassName(getAccessibilityClassName());
7597         event.setPackageName(getContext().getPackageName());
7598         event.setEnabled(isEnabled());
7599         event.setContentDescription(mContentDescription);
7600 
7601         switch (event.getEventType()) {
7602             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7603                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
7604                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7605                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7606                 event.setItemCount(focusablesTempList.size());
7607                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7608                 if (mAttachInfo != null) {
7609                     focusablesTempList.clear();
7610                 }
7611             } break;
7612             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7613                 CharSequence text = getIterableTextForAccessibility();
7614                 if (text != null && text.length() > 0) {
7615                     event.setFromIndex(getAccessibilitySelectionStart());
7616                     event.setToIndex(getAccessibilitySelectionEnd());
7617                     event.setItemCount(text.length());
7618                 }
7619             } break;
7620         }
7621     }
7622 
7623     /**
7624      * Returns an {@link AccessibilityNodeInfo} representing this view from the
7625      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7626      * This method is responsible for obtaining an accessibility node info from a
7627      * pool of reusable instances and calling
7628      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7629      * initialize the former.
7630      * <p>
7631      * Note: The client is responsible for recycling the obtained instance by calling
7632      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7633      * </p>
7634      *
7635      * @return A populated {@link AccessibilityNodeInfo}.
7636      *
7637      * @see AccessibilityNodeInfo
7638      */
7639     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7640         if (mAccessibilityDelegate != null) {
7641             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7642         } else {
7643             return createAccessibilityNodeInfoInternal();
7644         }
7645     }
7646 
7647     /**
7648      * @see #createAccessibilityNodeInfo()
7649      *
7650      * @hide
7651      */
7652     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7653         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7654         if (provider != null) {
7655             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7656         } else {
7657             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7658             onInitializeAccessibilityNodeInfo(info);
7659             return info;
7660         }
7661     }
7662 
7663     /**
7664      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7665      * The base implementation sets:
7666      * <ul>
7667      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7668      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7669      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7670      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7671      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7672      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7673      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7674      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7675      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7676      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7677      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7678      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7679      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7680      * </ul>
7681      * <p>
7682      * Subclasses should override this method, call the super implementation,
7683      * and set additional attributes.
7684      * </p>
7685      * <p>
7686      * If an {@link AccessibilityDelegate} has been specified via calling
7687      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7688      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7689      * is responsible for handling this call.
7690      * </p>
7691      *
7692      * @param info The instance to initialize.
7693      */
7694     @CallSuper
7695     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7696         if (mAccessibilityDelegate != null) {
7697             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7698         } else {
7699             onInitializeAccessibilityNodeInfoInternal(info);
7700         }
7701     }
7702 
7703     /**
7704      * Gets the location of this view in screen coordinates.
7705      *
7706      * @param outRect The output location
7707      * @hide
7708      */
7709     public void getBoundsOnScreen(Rect outRect) {
7710         getBoundsOnScreen(outRect, false);
7711     }
7712 
7713     /**
7714      * Gets the location of this view in screen coordinates.
7715      *
7716      * @param outRect The output location
7717      * @param clipToParent Whether to clip child bounds to the parent ones.
7718      * @hide
7719      */
7720     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7721         if (mAttachInfo == null) {
7722             return;
7723         }
7724 
7725         RectF position = mAttachInfo.mTmpTransformRect;
7726         position.set(0, 0, mRight - mLeft, mBottom - mTop);
7727         mapRectFromViewToScreenCoords(position, clipToParent);
7728         outRect.set(Math.round(position.left), Math.round(position.top),
7729                 Math.round(position.right), Math.round(position.bottom));
7730     }
7731 
7732     /**
7733      * Map a rectangle from view-relative coordinates to screen-relative coordinates
7734      *
7735      * @param rect The rectangle to be mapped
7736      * @param clipToParent Whether to clip child bounds to the parent ones.
7737      * @hide
7738      */
7739     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7740         if (!hasIdentityMatrix()) {
7741             getMatrix().mapRect(rect);
7742         }
7743 
7744         rect.offset(mLeft, mTop);
7745 
7746         ViewParent parent = mParent;
7747         while (parent instanceof View) {
7748             View parentView = (View) parent;
7749 
7750             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7751 
7752             if (clipToParent) {
7753                 rect.left = Math.max(rect.left, 0);
7754                 rect.top = Math.max(rect.top, 0);
7755                 rect.right = Math.min(rect.right, parentView.getWidth());
7756                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7757             }
7758 
7759             if (!parentView.hasIdentityMatrix()) {
7760                 parentView.getMatrix().mapRect(rect);
7761             }
7762 
7763             rect.offset(parentView.mLeft, parentView.mTop);
7764 
7765             parent = parentView.mParent;
7766         }
7767 
7768         if (parent instanceof ViewRootImpl) {
7769             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7770             rect.offset(0, -viewRootImpl.mCurScrollY);
7771         }
7772 
7773         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7774     }
7775 
7776     /**
7777      * Return the class name of this object to be used for accessibility purposes.
7778      * Subclasses should only override this if they are implementing something that
7779      * should be seen as a completely new class of view when used by accessibility,
7780      * unrelated to the class it is deriving from.  This is used to fill in
7781      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7782      */
7783     public CharSequence getAccessibilityClassName() {
7784         return View.class.getName();
7785     }
7786 
7787     /**
7788      * Called when assist structure is being retrieved from a view as part of
7789      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7790      * @param structure Fill in with structured view data.  The default implementation
7791      * fills in all data that can be inferred from the view itself.
7792      */
7793     public void onProvideStructure(ViewStructure structure) {
7794         onProvideStructureForAssistOrAutofill(structure, false, 0);
7795     }
7796 
7797     /**
7798      * Populates a {@link ViewStructure} to fullfil an autofill request.
7799      *
7800      * <p>The structure should contain at least the following properties:
7801      * <ul>
7802      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
7803      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
7804      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
7805      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
7806      * </ul>
7807      *
7808      * <p>It's also recommended to set the following properties - the more properties the structure
7809      * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
7810      * using the structure:
7811      *
7812      * <ul>
7813      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
7814      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
7815      *       view can only be filled with predefined values (typically used when the autofill type
7816      *       is {@link #AUTOFILL_TYPE_LIST}).
7817      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
7818      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
7819      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
7820      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
7821      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
7822      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
7823      *   <li>For views representing text fields, text properties such as the text itself
7824      *       ({@link ViewStructure#setText(CharSequence)}), text hints
7825      *       ({@link ViewStructure#setHint(CharSequence)}, input type
7826      *       ({@link ViewStructure#setInputType(int)}),
7827      *   <li>For views representing HTML nodes, its web domain
7828      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
7829      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
7830      * </ul>
7831      *
7832      * <p>The default implementation of this method already sets most of these properties based on
7833      * related {@link View} methods (for example, the autofill id is set using
7834      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
7835      * and views in the standard Android widgets library also override it to set their
7836      * relevant properties (for example, {@link android.widget.TextView} already sets the text
7837      * properties), so it's recommended to only override this method
7838      * (and call {@code super.onProvideAutofillStructure()}) when:
7839      *
7840      * <ul>
7841      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7842      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7843      *   <li>The view can only be autofilled with predefined options, so it can call
7844      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
7845      * </ul>
7846      *
7847      * <p><b>Note:</b> The {@code left} and {@code top} values set in
7848      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
7849      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
7850      *
7851      * <p>Views support the Autofill Framework mainly by:
7852      * <ul>
7853      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7854      *   <li>Notifying the Android System when the view value changed by calling
7855      *       {@link AutofillManager#notifyValueChanged(View)}.
7856      *   <li>Implementing the methods that autofill the view.
7857      * </ul>
7858      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
7859      * for the latter.
7860      *
7861      * @param structure fill in with structured view data for autofill purposes.
7862      * @param flags optional flags.
7863      *
7864      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7865      */
7866     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
7867         onProvideStructureForAssistOrAutofill(structure, true, flags);
7868     }
7869 
7870     private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7871             boolean forAutofill, @AutofillFlags int flags) {
7872         final int id = mID;
7873         if (id != NO_ID && !isViewIdGenerated(id)) {
7874             String pkg, type, entry;
7875             try {
7876                 final Resources res = getResources();
7877                 entry = res.getResourceEntryName(id);
7878                 type = res.getResourceTypeName(id);
7879                 pkg = res.getResourcePackageName(id);
7880             } catch (Resources.NotFoundException e) {
7881                 entry = type = pkg = null;
7882             }
7883             structure.setId(id, pkg, type, entry);
7884         } else {
7885             structure.setId(id, null, null, null);
7886         }
7887 
7888         if (forAutofill) {
7889             final @AutofillType int autofillType = getAutofillType();
7890             // Don't need to fill autofill info if view does not support it.
7891             // For example, only TextViews that are editable support autofill
7892             if (autofillType != AUTOFILL_TYPE_NONE) {
7893                 structure.setAutofillType(autofillType);
7894                 structure.setAutofillHints(getAutofillHints());
7895                 structure.setAutofillValue(getAutofillValue());
7896             }
7897             structure.setImportantForAutofill(getImportantForAutofill());
7898         }
7899 
7900         int ignoredParentLeft = 0;
7901         int ignoredParentTop = 0;
7902         if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
7903             View parentGroup = null;
7904 
7905             ViewParent viewParent = getParent();
7906             if (viewParent instanceof View) {
7907                 parentGroup = (View) viewParent;
7908             }
7909 
7910             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
7911                 ignoredParentLeft += parentGroup.mLeft;
7912                 ignoredParentTop += parentGroup.mTop;
7913 
7914                 viewParent = parentGroup.getParent();
7915                 if (viewParent instanceof View) {
7916                     parentGroup = (View) viewParent;
7917                 } else {
7918                     break;
7919                 }
7920             }
7921         }
7922 
7923         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
7924                 mRight - mLeft, mBottom - mTop);
7925         if (!forAutofill) {
7926             if (!hasIdentityMatrix()) {
7927                 structure.setTransformation(getMatrix());
7928             }
7929             structure.setElevation(getZ());
7930         }
7931         structure.setVisibility(getVisibility());
7932         structure.setEnabled(isEnabled());
7933         if (isClickable()) {
7934             structure.setClickable(true);
7935         }
7936         if (isFocusable()) {
7937             structure.setFocusable(true);
7938         }
7939         if (isFocused()) {
7940             structure.setFocused(true);
7941         }
7942         if (isAccessibilityFocused()) {
7943             structure.setAccessibilityFocused(true);
7944         }
7945         if (isSelected()) {
7946             structure.setSelected(true);
7947         }
7948         if (isActivated()) {
7949             structure.setActivated(true);
7950         }
7951         if (isLongClickable()) {
7952             structure.setLongClickable(true);
7953         }
7954         if (this instanceof Checkable) {
7955             structure.setCheckable(true);
7956             if (((Checkable)this).isChecked()) {
7957                 structure.setChecked(true);
7958             }
7959         }
7960         if (isOpaque()) {
7961             structure.setOpaque(true);
7962         }
7963         if (isContextClickable()) {
7964             structure.setContextClickable(true);
7965         }
7966         structure.setClassName(getAccessibilityClassName().toString());
7967         structure.setContentDescription(getContentDescription());
7968     }
7969 
7970     /**
7971      * Called when assist structure is being retrieved from a view as part of
7972      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7973      * generate additional virtual structure under this view.  The defaullt implementation
7974      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7975      * view's virtual accessibility nodes, if any.  You can override this for a more
7976      * optimal implementation providing this data.
7977      */
7978     public void onProvideVirtualStructure(ViewStructure structure) {
7979         onProvideVirtualStructureCompat(structure, false);
7980     }
7981 
7982     /**
7983      * Fallback implementation to populate a ViewStructure from accessibility state.
7984      *
7985      * @param structure The structure to populate.
7986      * @param forAutofill Whether the structure is needed for autofill.
7987      */
7988     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
7989         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7990         if (provider != null) {
7991             if (android.view.autofill.Helper.sVerbose && forAutofill) {
7992                 Log.v(VIEW_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
7993             }
7994 
7995             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7996             structure.setChildCount(1);
7997             final ViewStructure root = structure.newChild(0);
7998             populateVirtualStructure(root, provider, info, forAutofill);
7999             info.recycle();
8000         }
8001     }
8002 
8003     /**
8004      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
8005      * request.
8006      *
8007      * <p>This method should be used when the view manages a virtual structure under this view. For
8008      * example, a view that draws input fields using {@link #draw(Canvas)}.
8009      *
8010      * <p>When implementing this method, subclasses must follow the rules below:
8011      *
8012      * <ul>
8013      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
8014      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
8015      *       identifying the children in the virtual structure.
8016      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
8017      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
8018      *       autofill performance.
8019      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
8020      *       children.
8021      *   <li>Set the autofill properties of the child structure as defined by
8022      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
8023      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
8024      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
8025      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
8026      *       when the focused virtual child changed.
8027      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
8028      *       whether a given virtual view is visible to the user in order to support triggering
8029      *       save when all views of interest go away.
8030      *   <li>Call
8031      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
8032      *       when the value of a virtual child changed.
8033      *   <li>Call {@link
8034      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
8035      *       when the visibility of a virtual child changed.
8036      *   <li>Call
8037      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
8038      *       child is clicked.
8039      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
8040      *       changed and the current context should be committed (for example, when the user tapped
8041      *       a {@code SUBMIT} button in an HTML page).
8042      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
8043      *       changed and the current context should be canceled (for example, when the user tapped
8044      *       a {@code CANCEL} button in an HTML page).
8045      *   <li>Provide ways for users to manually request autofill by calling
8046      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
8047      *   <li>The {@code left} and {@code top} values set in
8048      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
8049      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
8050      *       structure.
8051      * </ul>
8052      *
8053      * <p>Views with virtual children support the Autofill Framework mainly by:
8054      * <ul>
8055      *   <li>Providing the metadata defining what the virtual children mean and how they can be
8056      *       autofilled.
8057      *   <li>Implementing the methods that autofill the virtual children.
8058      * </ul>
8059      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
8060      * for the latter.
8061      *
8062      * @param structure fill in with virtual children data for autofill purposes.
8063      * @param flags optional flags.
8064      *
8065      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8066      */
8067     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
8068         if (mContext.isAutofillCompatibilityEnabled()) {
8069             onProvideVirtualStructureCompat(structure, true);
8070         }
8071     }
8072 
8073     /**
8074      * Automatically fills the content of this view with the {@code value}.
8075      *
8076      * <p>Views support the Autofill Framework mainly by:
8077      * <ul>
8078      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8079      *   <li>Implementing the methods that autofill the view.
8080      * </ul>
8081      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
8082      * this method is responsible for latter.
8083      *
8084      * <p>This method does nothing by default, but when overridden it typically:
8085      * <ol>
8086      *   <li>Checks if the provided value matches the expected type (which is defined by
8087      *       {@link #getAutofillType()}).
8088      *   <li>Checks if the view is editable - if it isn't, it should return right away.
8089      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
8090      *   <li>Pass the actual value to the equivalent setter in the view.
8091      * </ol>
8092      *
8093      * <p>For example, a text-field view could implement the method this way:
8094      *
8095      * <pre class="prettyprint">
8096      * &#64;Override
8097      * public void autofill(AutofillValue value) {
8098      *   if (!value.isText() || !this.isEditable()) {
8099      *      return;
8100      *   }
8101      *   CharSequence text = value.getTextValue();
8102      *   if (text != null) {
8103      *     this.setText(text);
8104      *   }
8105      * }
8106      * </pre>
8107      *
8108      * <p>If the value is updated asynchronously, the next call to
8109      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
8110      * changed to the autofilled value. If not, the view will not be considered autofilled.
8111      *
8112      * <p><b>Note:</b> After this method is called, the value returned by
8113      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
8114      * view will not be highlighted as autofilled.
8115      *
8116      * @param value value to be autofilled.
8117      */
8118     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
8119     }
8120 
8121     /**
8122      * Automatically fills the content of the virtual children within this view.
8123      *
8124      * <p>Views with virtual children support the Autofill Framework mainly by:
8125      * <ul>
8126      *   <li>Providing the metadata defining what the virtual children mean and how they can be
8127      *       autofilled.
8128      *   <li>Implementing the methods that autofill the virtual children.
8129      * </ul>
8130      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
8131      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
8132      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
8133      *
8134      * <p>If a child value is updated asynchronously, the next call to
8135      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
8136      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
8137      * considered autofilled.
8138      *
8139      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
8140      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
8141      * changes.
8142      *
8143      * @param values map of values to be autofilled, keyed by virtual child id.
8144      *
8145      * @attr ref android.R.styleable#Theme_autofilledHighlight
8146      */
8147     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
8148         if (!mContext.isAutofillCompatibilityEnabled()) {
8149             return;
8150         }
8151         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8152         if (provider == null) {
8153             return;
8154         }
8155         final int valueCount = values.size();
8156         for (int i = 0; i < valueCount; i++) {
8157             final AutofillValue value = values.valueAt(i);
8158             if (value.isText()) {
8159                 final int virtualId = values.keyAt(i);
8160                 final CharSequence text = value.getTextValue();
8161                 final Bundle arguments = new Bundle();
8162                 arguments.putCharSequence(
8163                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
8164                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
8165             }
8166         }
8167     }
8168 
8169     /**
8170      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
8171      *
8172      * <p>The autofill id is created on demand, unless it is explicitly set by
8173      * {@link #setAutofillId(AutofillId)}.
8174      *
8175      * <p>See {@link #setAutofillId(AutofillId)} for more info.
8176      *
8177      * @return The View's autofill id.
8178      */
8179     public final AutofillId getAutofillId() {
8180         if (mAutofillId == null) {
8181             // The autofill id needs to be unique, but its value doesn't matter,
8182             // so it's better to reuse the accessibility id to save space.
8183             mAutofillId = new AutofillId(getAutofillViewId());
8184         }
8185         return mAutofillId;
8186     }
8187 
8188     /**
8189      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
8190      *
8191      * <p>The autofill id is created on demand, and this method should only be called when a view is
8192      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
8193      * that method creates a snapshot of the view that is passed along to the autofill service.
8194      *
8195      * <p>This method is typically used when view subtrees are recycled to represent different
8196      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
8197      * out, and restored later when it's swapped back in. For example:
8198      *
8199      * <pre>
8200      * EditText reusableView = ...;
8201      * ViewGroup parentView = ...;
8202      * AutofillManager afm = ...;
8203      *
8204      * // Swap out the view and change its contents
8205      * AutofillId oldId = reusableView.getAutofillId();
8206      * CharSequence oldText = reusableView.getText();
8207      * parentView.removeView(reusableView);
8208      * AutofillId newId = afm.getNextAutofillId();
8209      * reusableView.setText("New I am");
8210      * reusableView.setAutofillId(newId);
8211      * parentView.addView(reusableView);
8212      *
8213      * // Later, swap the old content back in
8214      * parentView.removeView(reusableView);
8215      * reusableView.setAutofillId(oldId);
8216      * reusableView.setText(oldText);
8217      * parentView.addView(reusableView);
8218      * </pre>
8219      *
8220      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
8221      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
8222      * obtained through {@link #getAutofillId()}), or a new value obtained through
8223      * {@link AutofillManager#getNextAutofillId()}.
8224      *
8225      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
8226      * a window}.
8227      *
8228      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
8229      */
8230     public void setAutofillId(@Nullable AutofillId id) {
8231         // TODO(b/37566627): add unit / CTS test for all possible combinations below
8232         if (android.view.autofill.Helper.sVerbose) {
8233             Log.v(VIEW_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
8234         }
8235         if (isAttachedToWindow()) {
8236             throw new IllegalStateException("Cannot set autofill id when view is attached");
8237         }
8238         if (id != null && id.isVirtual()) {
8239             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
8240         }
8241         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
8242             // Ignore reset because it was never explicitly set before.
8243             return;
8244         }
8245         mAutofillId = id;
8246         if (id != null) {
8247             mAutofillViewId = id.getViewId();
8248             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
8249         } else {
8250             mAutofillViewId = NO_ID;
8251             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
8252         }
8253     }
8254 
8255     /**
8256      * Describes the autofill type of this view, so an
8257      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
8258      * when autofilling the view.
8259      *
8260      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
8261      * support the Autofill Framework.
8262      *
8263      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
8264      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
8265      *
8266      * @see #onProvideAutofillStructure(ViewStructure, int)
8267      * @see #autofill(AutofillValue)
8268      */
8269     public @AutofillType int getAutofillType() {
8270         return AUTOFILL_TYPE_NONE;
8271     }
8272 
8273     /**
8274      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
8275      * to autofill the view with the user's data.
8276      *
8277      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
8278      *
8279      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
8280      * {@code null} if no hints were set.
8281      *
8282      * @attr ref android.R.styleable#View_autofillHints
8283      */
8284     @ViewDebug.ExportedProperty()
8285     @Nullable public String[] getAutofillHints() {
8286         return mAutofillHints;
8287     }
8288 
8289     /**
8290      * @hide
8291      */
8292     public boolean isAutofilled() {
8293         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
8294     }
8295 
8296     /**
8297      * Gets the {@link View}'s current autofill value.
8298      *
8299      * <p>By default returns {@code null}, but subclasses should override it and return an
8300      * appropriate value to properly support the Autofill Framework.
8301      *
8302      * @see #onProvideAutofillStructure(ViewStructure, int)
8303      * @see #autofill(AutofillValue)
8304      */
8305     @Nullable
8306     public AutofillValue getAutofillValue() {
8307         return null;
8308     }
8309 
8310     /**
8311      * Gets the mode for determining whether this view is important for autofill.
8312      *
8313      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
8314      * info about this mode.
8315      *
8316      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
8317      * {@link #setImportantForAutofill(int)}.
8318      *
8319      * @attr ref android.R.styleable#View_importantForAutofill
8320      */
8321     @ViewDebug.ExportedProperty(mapping = {
8322             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
8323             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
8324             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
8325             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
8326                 to = "yesExcludeDescendants"),
8327             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
8328                 to = "noExcludeDescendants")})
8329     public @AutofillImportance int getImportantForAutofill() {
8330         return (mPrivateFlags3
8331                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
8332     }
8333 
8334     /**
8335      * Sets the mode for determining whether this view is considered important for autofill.
8336      *
8337      * <p>The platform determines the importance for autofill automatically but you
8338      * can use this method to customize the behavior. For example:
8339      *
8340      * <ol>
8341      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
8342      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
8343      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
8344      *       view of an activity containing a spreadhseet editor), it should be
8345      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
8346      *   <li>When the view content is relevant for autofill but its children aren't (for example,
8347      *       a credit card expiration date represented by a custom view that overrides the proper
8348      *       autofill methods and has 2 children representing the month and year), it should
8349      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
8350      * </ol>
8351      *
8352      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
8353      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
8354      * children) will be always be considered not important; for example, when the user explicitly
8355      * makes an autofill request, all views are considered important. See
8356      * {@link #isImportantForAutofill()} for more details about how the View's importance for
8357      * autofill is used.
8358      *
8359      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
8360      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
8361      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
8362      *
8363      * @attr ref android.R.styleable#View_importantForAutofill
8364      */
8365     public void setImportantForAutofill(@AutofillImportance int mode) {
8366         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
8367         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
8368                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
8369     }
8370 
8371     /**
8372      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
8373      * associated with this view is considered important for autofill purposes.
8374      *
8375      * <p>Generally speaking, a view is important for autofill if:
8376      * <ol>
8377      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
8378      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
8379      *     determine how other views can be autofilled.
8380      * <ol>
8381      *
8382      * <p>For example, view containers should typically return {@code false} for performance reasons
8383      * (since the important info is provided by their children), but if its properties have relevant
8384      * information (for example, a resource id called {@code credentials}, it should return
8385      * {@code true}. On the other hand, views representing labels or editable fields should
8386      * typically return {@code true}, but in some cases they could return {@code false}
8387      * (for example, if they're part of a "Captcha" mechanism).
8388      *
8389      * <p>The value returned by this method depends on the value returned by
8390      * {@link #getImportantForAutofill()}:
8391      *
8392      * <ol>
8393      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
8394      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
8395      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
8396      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
8397      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
8398      *       that can return {@code true} in some cases (like a container with a resource id),
8399      *       but {@code false} in most.
8400      *   <li>otherwise, it returns {@code false}.
8401      * </ol>
8402      *
8403      * <p>When a view is considered important for autofill:
8404      * <ul>
8405      *   <li>The view might automatically trigger an autofill request when focused on.
8406      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
8407      *       request.
8408      * </ul>
8409      *
8410      * <p>On the other hand, when a view is considered not important for autofill:
8411      * <ul>
8412      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
8413      *       request through {@link AutofillManager#requestAutofill(View)}.
8414      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
8415      *       autofill request, unless the request has the
8416      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
8417      * </ul>
8418      *
8419      * @return whether the view is considered important for autofill.
8420      *
8421      * @see #setImportantForAutofill(int)
8422      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
8423      * @see #IMPORTANT_FOR_AUTOFILL_YES
8424      * @see #IMPORTANT_FOR_AUTOFILL_NO
8425      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
8426      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
8427      * @see AutofillManager#requestAutofill(View)
8428      */
8429     public final boolean isImportantForAutofill() {
8430         // Check parent mode to ensure we're not hidden.
8431         ViewParent parent = mParent;
8432         while (parent instanceof View) {
8433             final int parentImportance = ((View) parent).getImportantForAutofill();
8434             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
8435                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
8436                 return false;
8437             }
8438             parent = parent.getParent();
8439         }
8440 
8441         final int importance = getImportantForAutofill();
8442 
8443         // First, check the explicit states.
8444         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
8445                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
8446             return true;
8447         }
8448         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
8449                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
8450             return false;
8451         }
8452 
8453         // Then use some heuristics to handle AUTO.
8454 
8455         // Always include views that have an explicit resource id.
8456         final int id = mID;
8457         if (id != NO_ID && !isViewIdGenerated(id)) {
8458             final Resources res = getResources();
8459             String entry = null;
8460             String pkg = null;
8461             try {
8462                 entry = res.getResourceEntryName(id);
8463                 pkg = res.getResourcePackageName(id);
8464             } catch (Resources.NotFoundException e) {
8465                 // ignore
8466             }
8467             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
8468                 return true;
8469             }
8470         }
8471 
8472         // If the app developer explicitly set hints for it, it's important.
8473         if (getAutofillHints() != null) {
8474             return true;
8475         }
8476 
8477         // Otherwise, assume it's not important...
8478         return false;
8479     }
8480 
8481     @Nullable
8482     private AutofillManager getAutofillManager() {
8483         return mContext.getSystemService(AutofillManager.class);
8484     }
8485 
8486     private boolean isAutofillable() {
8487         return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
8488                 && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
8489     }
8490 
8491     /** @hide */
8492     public boolean canNotifyAutofillEnterExitEvent() {
8493         return isAutofillable() && isAttachedToWindow();
8494     }
8495 
8496     private void populateVirtualStructure(ViewStructure structure,
8497             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
8498             boolean forAutofill) {
8499         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
8500                 null, null, info.getViewIdResourceName());
8501         Rect rect = structure.getTempRect();
8502         info.getBoundsInParent(rect);
8503         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
8504         structure.setVisibility(VISIBLE);
8505         structure.setEnabled(info.isEnabled());
8506         if (info.isClickable()) {
8507             structure.setClickable(true);
8508         }
8509         if (info.isFocusable()) {
8510             structure.setFocusable(true);
8511         }
8512         if (info.isFocused()) {
8513             structure.setFocused(true);
8514         }
8515         if (info.isAccessibilityFocused()) {
8516             structure.setAccessibilityFocused(true);
8517         }
8518         if (info.isSelected()) {
8519             structure.setSelected(true);
8520         }
8521         if (info.isLongClickable()) {
8522             structure.setLongClickable(true);
8523         }
8524         if (info.isCheckable()) {
8525             structure.setCheckable(true);
8526             if (info.isChecked()) {
8527                 structure.setChecked(true);
8528             }
8529         }
8530         if (info.isContextClickable()) {
8531             structure.setContextClickable(true);
8532         }
8533         if (forAutofill) {
8534             structure.setAutofillId(new AutofillId(getAutofillId(),
8535                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
8536         }
8537         CharSequence cname = info.getClassName();
8538         structure.setClassName(cname != null ? cname.toString() : null);
8539         structure.setContentDescription(info.getContentDescription());
8540         if (forAutofill) {
8541             final int maxTextLength = info.getMaxTextLength();
8542             if (maxTextLength != -1) {
8543                 structure.setMaxTextLength(maxTextLength);
8544             }
8545             structure.setHint(info.getHintText());
8546         }
8547         CharSequence text = info.getText();
8548         boolean hasText = text != null || info.getError() != null;
8549         if (hasText) {
8550             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
8551         }
8552         if (forAutofill) {
8553             if (info.isEditable()) {
8554                 structure.setDataIsSensitive(true);
8555                 if (hasText) {
8556                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
8557                     structure.setAutofillValue(AutofillValue.forText(text));
8558                 }
8559                 int inputType = info.getInputType();
8560                 if (inputType == 0 && info.isPassword()) {
8561                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
8562                 }
8563                 structure.setInputType(inputType);
8564             } else {
8565                 structure.setDataIsSensitive(false);
8566             }
8567         }
8568         final int NCHILDREN = info.getChildCount();
8569         if (NCHILDREN > 0) {
8570             structure.setChildCount(NCHILDREN);
8571             for (int i=0; i<NCHILDREN; i++) {
8572                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
8573                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
8574                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
8575                     continue;
8576                 }
8577                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
8578                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
8579                 ViewStructure child = structure.newChild(i);
8580                 populateVirtualStructure(child, provider, cinfo, forAutofill);
8581                 cinfo.recycle();
8582             }
8583         }
8584     }
8585 
8586     /**
8587      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
8588      * implementation calls {@link #onProvideStructure} and
8589      * {@link #onProvideVirtualStructure}.
8590      */
8591     public void dispatchProvideStructure(ViewStructure structure) {
8592         dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
8593     }
8594 
8595     /**
8596      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
8597      * when an Assist structure is being created as part of an autofill request.
8598      *
8599      * <p>The default implementation does the following:
8600      * <ul>
8601      *   <li>Sets the {@link AutofillId} in the structure.
8602      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
8603      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
8604      * </ul>
8605      *
8606      * <p>Typically, this method should only be overridden by subclasses that provide a view
8607      * hierarchy (such as {@link ViewGroup}) - other classes should override
8608      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
8609      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
8610      *
8611      * <p>When overridden, it must:
8612      *
8613      * <ul>
8614      *   <li>Either call
8615      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
8616      *       set the {@link AutofillId} in the structure (for example, by calling
8617      *       {@code structure.setAutofillId(getAutofillId())}).
8618      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
8619      *       set, all views in the structure should be considered important for autofill,
8620      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
8621      *       respect this flag to provide a better user experience - this flag is typically used
8622      *       when an user explicitly requested autofill. If the flag is not set,
8623      *       then only views marked as important for autofill should be included in the
8624      *       structure - skipping non-important views optimizes the overall autofill performance.
8625      * </ul>
8626      *
8627      * @param structure fill in with structured view data for autofill purposes.
8628      * @param flags optional flags.
8629      *
8630      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8631      */
8632     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
8633             @AutofillFlags int flags) {
8634         dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
8635     }
8636 
8637     private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
8638             boolean forAutofill, @AutofillFlags int flags) {
8639         if (forAutofill) {
8640             structure.setAutofillId(getAutofillId());
8641             onProvideAutofillStructure(structure, flags);
8642             onProvideAutofillVirtualStructure(structure, flags);
8643         } else if (!isAssistBlocked()) {
8644             onProvideStructure(structure);
8645             onProvideVirtualStructure(structure);
8646         } else {
8647             structure.setClassName(getAccessibilityClassName().toString());
8648             structure.setAssistBlocked(true);
8649         }
8650     }
8651 
8652     /**
8653      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
8654      *
8655      * Note: Called from the default {@link AccessibilityDelegate}.
8656      *
8657      * @hide
8658      */
8659     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
8660         if (mAttachInfo == null) {
8661             return;
8662         }
8663 
8664         Rect bounds = mAttachInfo.mTmpInvalRect;
8665 
8666         getDrawingRect(bounds);
8667         info.setBoundsInParent(bounds);
8668 
8669         getBoundsOnScreen(bounds, true);
8670         info.setBoundsInScreen(bounds);
8671 
8672         ViewParent parent = getParentForAccessibility();
8673         if (parent instanceof View) {
8674             info.setParent((View) parent);
8675         }
8676 
8677         if (mID != View.NO_ID) {
8678             View rootView = getRootView();
8679             if (rootView == null) {
8680                 rootView = this;
8681             }
8682 
8683             View label = rootView.findLabelForView(this, mID);
8684             if (label != null) {
8685                 info.setLabeledBy(label);
8686             }
8687 
8688             if ((mAttachInfo.mAccessibilityFetchFlags
8689                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
8690                     && Resources.resourceHasPackage(mID)) {
8691                 try {
8692                     String viewId = getResources().getResourceName(mID);
8693                     info.setViewIdResourceName(viewId);
8694                 } catch (Resources.NotFoundException nfe) {
8695                     /* ignore */
8696                 }
8697             }
8698         }
8699 
8700         if (mLabelForId != View.NO_ID) {
8701             View rootView = getRootView();
8702             if (rootView == null) {
8703                 rootView = this;
8704             }
8705             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
8706             if (labeled != null) {
8707                 info.setLabelFor(labeled);
8708             }
8709         }
8710 
8711         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
8712             View rootView = getRootView();
8713             if (rootView == null) {
8714                 rootView = this;
8715             }
8716             View next = rootView.findViewInsideOutShouldExist(this,
8717                     mAccessibilityTraversalBeforeId);
8718             if (next != null && next.includeForAccessibility()) {
8719                 info.setTraversalBefore(next);
8720             }
8721         }
8722 
8723         if (mAccessibilityTraversalAfterId != View.NO_ID) {
8724             View rootView = getRootView();
8725             if (rootView == null) {
8726                 rootView = this;
8727             }
8728             View next = rootView.findViewInsideOutShouldExist(this,
8729                     mAccessibilityTraversalAfterId);
8730             if (next != null && next.includeForAccessibility()) {
8731                 info.setTraversalAfter(next);
8732             }
8733         }
8734 
8735         info.setVisibleToUser(isVisibleToUser());
8736 
8737         info.setImportantForAccessibility(isImportantForAccessibility());
8738         info.setPackageName(mContext.getPackageName());
8739         info.setClassName(getAccessibilityClassName());
8740         info.setContentDescription(getContentDescription());
8741 
8742         info.setEnabled(isEnabled());
8743         info.setClickable(isClickable());
8744         info.setFocusable(isFocusable());
8745         info.setScreenReaderFocusable(isScreenReaderFocusable());
8746         info.setFocused(isFocused());
8747         info.setAccessibilityFocused(isAccessibilityFocused());
8748         info.setSelected(isSelected());
8749         info.setLongClickable(isLongClickable());
8750         info.setContextClickable(isContextClickable());
8751         info.setLiveRegion(getAccessibilityLiveRegion());
8752         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
8753             info.setTooltipText(mTooltipInfo.mTooltipText);
8754             info.addAction((mTooltipInfo.mTooltipPopup == null)
8755                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
8756                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
8757         }
8758 
8759         // TODO: These make sense only if we are in an AdapterView but all
8760         // views can be selected. Maybe from accessibility perspective
8761         // we should report as selectable view in an AdapterView.
8762         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
8763         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
8764 
8765         if (isFocusable()) {
8766             if (isFocused()) {
8767                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
8768             } else {
8769                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
8770             }
8771         }
8772 
8773         if (!isAccessibilityFocused()) {
8774             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
8775         } else {
8776             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
8777         }
8778 
8779         if (isClickable() && isEnabled()) {
8780             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
8781         }
8782 
8783         if (isLongClickable() && isEnabled()) {
8784             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
8785         }
8786 
8787         if (isContextClickable() && isEnabled()) {
8788             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
8789         }
8790 
8791         CharSequence text = getIterableTextForAccessibility();
8792         if (text != null && text.length() > 0) {
8793             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
8794 
8795             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
8796             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
8797             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
8798             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
8799                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
8800                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
8801         }
8802 
8803         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
8804         populateAccessibilityNodeInfoDrawingOrderInParent(info);
8805         info.setPaneTitle(mAccessibilityPaneTitle);
8806         info.setHeading(isAccessibilityHeading());
8807     }
8808 
8809     /**
8810      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
8811      * additional data.
8812      * <p>
8813      * This method only needs overloading if the node is marked as having extra data available.
8814      * </p>
8815      *
8816      * @param info The info to which to add the extra data. Never {@code null}.
8817      * @param extraDataKey A key specifying the type of extra data to add to the info. The
8818      *                     extra data should be added to the {@link Bundle} returned by
8819      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
8820      *                     {@code null}.
8821      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
8822      *                  {@code null} if the service provided no arguments.
8823      *
8824      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
8825      */
8826     public void addExtraDataToAccessibilityNodeInfo(
8827             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
8828             @Nullable Bundle arguments) {
8829     }
8830 
8831     /**
8832      * Determine the order in which this view will be drawn relative to its siblings for a11y
8833      *
8834      * @param info The info whose drawing order should be populated
8835      */
8836     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8837         /*
8838          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8839          * drawing order may not be well-defined, and some Views with custom drawing order may
8840          * not be initialized sufficiently to respond properly getChildDrawingOrder.
8841          */
8842         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8843             info.setDrawingOrder(0);
8844             return;
8845         }
8846         int drawingOrderInParent = 1;
8847         // Iterate up the hierarchy if parents are not important for a11y
8848         View viewAtDrawingLevel = this;
8849         final ViewParent parent = getParentForAccessibility();
8850         while (viewAtDrawingLevel != parent) {
8851             final ViewParent currentParent = viewAtDrawingLevel.getParent();
8852             if (!(currentParent instanceof ViewGroup)) {
8853                 // Should only happen for the Decor
8854                 drawingOrderInParent = 0;
8855                 break;
8856             } else {
8857                 final ViewGroup parentGroup = (ViewGroup) currentParent;
8858                 final int childCount = parentGroup.getChildCount();
8859                 if (childCount > 1) {
8860                     List<View> preorderedList = parentGroup.buildOrderedChildList();
8861                     if (preorderedList != null) {
8862                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8863                         for (int i = 0; i < childDrawIndex; i++) {
8864                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8865                         }
8866                     } else {
8867                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8868                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8869                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8870                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
8871                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8872                         if (childDrawIndex != 0) {
8873                             for (int i = 0; i < numChildrenToIterate; i++) {
8874                                 final int otherDrawIndex = (customOrder ?
8875                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
8876                                 if (otherDrawIndex < childDrawIndex) {
8877                                     drawingOrderInParent +=
8878                                             numViewsForAccessibility(parentGroup.getChildAt(i));
8879                                 }
8880                             }
8881                         }
8882                     }
8883                 }
8884             }
8885             viewAtDrawingLevel = (View) currentParent;
8886         }
8887         info.setDrawingOrder(drawingOrderInParent);
8888     }
8889 
8890     private static int numViewsForAccessibility(View view) {
8891         if (view != null) {
8892             if (view.includeForAccessibility()) {
8893                 return 1;
8894             } else if (view instanceof ViewGroup) {
8895                 return ((ViewGroup) view).getNumChildrenForAccessibility();
8896             }
8897         }
8898         return 0;
8899     }
8900 
8901     private View findLabelForView(View view, int labeledId) {
8902         if (mMatchLabelForPredicate == null) {
8903             mMatchLabelForPredicate = new MatchLabelForPredicate();
8904         }
8905         mMatchLabelForPredicate.mLabeledId = labeledId;
8906         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8907     }
8908 
8909     /**
8910      * Computes whether this virtual autofill view is visible to the user.
8911      *
8912      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
8913      * view must override it.
8914      *
8915      * @return Whether the view is visible on the screen.
8916      */
8917     public boolean isVisibleToUserForAutofill(int virtualId) {
8918         if (mContext.isAutofillCompatibilityEnabled()) {
8919             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8920             if (provider != null) {
8921                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
8922                 if (node != null) {
8923                     return node.isVisibleToUser();
8924                 }
8925                 // if node is null, assume it's not visible anymore
8926             } else {
8927                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
8928             }
8929             return false;
8930         }
8931         return true;
8932     }
8933 
8934     /**
8935      * Computes whether this view is visible to the user. Such a view is
8936      * attached, visible, all its predecessors are visible, it is not clipped
8937      * entirely by its predecessors, and has an alpha greater than zero.
8938      *
8939      * @return Whether the view is visible on the screen.
8940      *
8941      * @hide
8942      */
8943     public boolean isVisibleToUser() {
8944         return isVisibleToUser(null);
8945     }
8946 
8947     /**
8948      * Computes whether the given portion of this view is visible to the user.
8949      * Such a view is attached, visible, all its predecessors are visible,
8950      * has an alpha greater than zero, and the specified portion is not
8951      * clipped entirely by its predecessors.
8952      *
8953      * @param boundInView the portion of the view to test; coordinates should be relative; may be
8954      *                    <code>null</code>, and the entire view will be tested in this case.
8955      *                    When <code>true</code> is returned by the function, the actual visible
8956      *                    region will be stored in this parameter; that is, if boundInView is fully
8957      *                    contained within the view, no modification will be made, otherwise regions
8958      *                    outside of the visible area of the view will be clipped.
8959      *
8960      * @return Whether the specified portion of the view is visible on the screen.
8961      *
8962      * @hide
8963      */
8964     protected boolean isVisibleToUser(Rect boundInView) {
8965         if (mAttachInfo != null) {
8966             // Attached to invisible window means this view is not visible.
8967             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8968                 return false;
8969             }
8970             // An invisible predecessor or one with alpha zero means
8971             // that this view is not visible to the user.
8972             Object current = this;
8973             while (current instanceof View) {
8974                 View view = (View) current;
8975                 // We have attach info so this view is attached and there is no
8976                 // need to check whether we reach to ViewRootImpl on the way up.
8977                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8978                         view.getVisibility() != VISIBLE) {
8979                     return false;
8980                 }
8981                 current = view.mParent;
8982             }
8983             // Check if the view is entirely covered by its predecessors.
8984             Rect visibleRect = mAttachInfo.mTmpInvalRect;
8985             Point offset = mAttachInfo.mPoint;
8986             if (!getGlobalVisibleRect(visibleRect, offset)) {
8987                 return false;
8988             }
8989             // Check if the visible portion intersects the rectangle of interest.
8990             if (boundInView != null) {
8991                 visibleRect.offset(-offset.x, -offset.y);
8992                 return boundInView.intersect(visibleRect);
8993             }
8994             return true;
8995         }
8996         return false;
8997     }
8998 
8999     /**
9000      * Returns the delegate for implementing accessibility support via
9001      * composition. For more details see {@link AccessibilityDelegate}.
9002      *
9003      * @return The delegate, or null if none set.
9004      *
9005      * @hide
9006      */
9007     public AccessibilityDelegate getAccessibilityDelegate() {
9008         return mAccessibilityDelegate;
9009     }
9010 
9011     /**
9012      * Sets a delegate for implementing accessibility support via composition
9013      * (as opposed to inheritance). For more details, see
9014      * {@link AccessibilityDelegate}.
9015      * <p>
9016      * <strong>Note:</strong> On platform versions prior to
9017      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
9018      * views in the {@code android.widget.*} package are called <i>before</i>
9019      * host methods. This prevents certain properties such as class name from
9020      * being modified by overriding
9021      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
9022      * as any changes will be overwritten by the host class.
9023      * <p>
9024      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
9025      * methods are called <i>after</i> host methods, which all properties to be
9026      * modified without being overwritten by the host class.
9027      *
9028      * @param delegate the object to which accessibility method calls should be
9029      *                 delegated
9030      * @see AccessibilityDelegate
9031      */
9032     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
9033         mAccessibilityDelegate = delegate;
9034     }
9035 
9036     /**
9037      * Gets the provider for managing a virtual view hierarchy rooted at this View
9038      * and reported to {@link android.accessibilityservice.AccessibilityService}s
9039      * that explore the window content.
9040      * <p>
9041      * If this method returns an instance, this instance is responsible for managing
9042      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
9043      * View including the one representing the View itself. Similarly the returned
9044      * instance is responsible for performing accessibility actions on any virtual
9045      * view or the root view itself.
9046      * </p>
9047      * <p>
9048      * If an {@link AccessibilityDelegate} has been specified via calling
9049      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9050      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
9051      * is responsible for handling this call.
9052      * </p>
9053      *
9054      * @return The provider.
9055      *
9056      * @see AccessibilityNodeProvider
9057      */
9058     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
9059         if (mAccessibilityDelegate != null) {
9060             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
9061         } else {
9062             return null;
9063         }
9064     }
9065 
9066     /**
9067      * Gets the unique identifier of this view on the screen for accessibility purposes.
9068      *
9069      * @return The view accessibility id.
9070      *
9071      * @hide
9072      */
9073     public int getAccessibilityViewId() {
9074         if (mAccessibilityViewId == NO_ID) {
9075             mAccessibilityViewId = sNextAccessibilityViewId++;
9076         }
9077         return mAccessibilityViewId;
9078     }
9079 
9080     /**
9081      * Gets the unique identifier of this view on the screen for autofill purposes.
9082      *
9083      * @return The view autofill id.
9084      *
9085      * @hide
9086      */
9087     public int getAutofillViewId() {
9088         if (mAutofillViewId == NO_ID) {
9089             mAutofillViewId = mContext.getNextAutofillId();
9090         }
9091         return mAutofillViewId;
9092     }
9093 
9094     /**
9095      * Gets the unique identifier of the window in which this View reseides.
9096      *
9097      * @return The window accessibility id.
9098      *
9099      * @hide
9100      */
9101     public int getAccessibilityWindowId() {
9102         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
9103                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
9104     }
9105 
9106     /**
9107      * Returns the {@link View}'s content description.
9108      * <p>
9109      * <strong>Note:</strong> Do not override this method, as it will have no
9110      * effect on the content description presented to accessibility services.
9111      * You must call {@link #setContentDescription(CharSequence)} to modify the
9112      * content description.
9113      *
9114      * @return the content description
9115      * @see #setContentDescription(CharSequence)
9116      * @attr ref android.R.styleable#View_contentDescription
9117      */
9118     @ViewDebug.ExportedProperty(category = "accessibility")
9119     public CharSequence getContentDescription() {
9120         return mContentDescription;
9121     }
9122 
9123     /**
9124      * Sets the {@link View}'s content description.
9125      * <p>
9126      * A content description briefly describes the view and is primarily used
9127      * for accessibility support to determine how a view should be presented to
9128      * the user. In the case of a view with no textual representation, such as
9129      * {@link android.widget.ImageButton}, a useful content description
9130      * explains what the view does. For example, an image button with a phone
9131      * icon that is used to place a call may use "Call" as its content
9132      * description. An image of a floppy disk that is used to save a file may
9133      * use "Save".
9134      *
9135      * @param contentDescription The content description.
9136      * @see #getContentDescription()
9137      * @attr ref android.R.styleable#View_contentDescription
9138      */
9139     @RemotableViewMethod
9140     public void setContentDescription(CharSequence contentDescription) {
9141         if (mContentDescription == null) {
9142             if (contentDescription == null) {
9143                 return;
9144             }
9145         } else if (mContentDescription.equals(contentDescription)) {
9146             return;
9147         }
9148         mContentDescription = contentDescription;
9149         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
9150         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
9151             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
9152             notifySubtreeAccessibilityStateChangedIfNeeded();
9153         } else {
9154             notifyViewAccessibilityStateChangedIfNeeded(
9155                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
9156         }
9157     }
9158 
9159     /**
9160      * Sets the id of a view before which this one is visited in accessibility traversal.
9161      * A screen-reader must visit the content of this view before the content of the one
9162      * it precedes. For example, if view B is set to be before view A, then a screen-reader
9163      * will traverse the entire content of B before traversing the entire content of A,
9164      * regardles of what traversal strategy it is using.
9165      * <p>
9166      * Views that do not have specified before/after relationships are traversed in order
9167      * determined by the screen-reader.
9168      * </p>
9169      * <p>
9170      * Setting that this view is before a view that is not important for accessibility
9171      * or if this view is not important for accessibility will have no effect as the
9172      * screen-reader is not aware of unimportant views.
9173      * </p>
9174      *
9175      * @param beforeId The id of a view this one precedes in accessibility traversal.
9176      *
9177      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
9178      *
9179      * @see #setImportantForAccessibility(int)
9180      */
9181     @RemotableViewMethod
9182     public void setAccessibilityTraversalBefore(int beforeId) {
9183         if (mAccessibilityTraversalBeforeId == beforeId) {
9184             return;
9185         }
9186         mAccessibilityTraversalBeforeId = beforeId;
9187         notifyViewAccessibilityStateChangedIfNeeded(
9188                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9189     }
9190 
9191     /**
9192      * Gets the id of a view before which this one is visited in accessibility traversal.
9193      *
9194      * @return The id of a view this one precedes in accessibility traversal if
9195      *         specified, otherwise {@link #NO_ID}.
9196      *
9197      * @see #setAccessibilityTraversalBefore(int)
9198      */
9199     public int getAccessibilityTraversalBefore() {
9200         return mAccessibilityTraversalBeforeId;
9201     }
9202 
9203     /**
9204      * Sets the id of a view after which this one is visited in accessibility traversal.
9205      * A screen-reader must visit the content of the other view before the content of this
9206      * one. For example, if view B is set to be after view A, then a screen-reader
9207      * will traverse the entire content of A before traversing the entire content of B,
9208      * regardles of what traversal strategy it is using.
9209      * <p>
9210      * Views that do not have specified before/after relationships are traversed in order
9211      * determined by the screen-reader.
9212      * </p>
9213      * <p>
9214      * Setting that this view is after a view that is not important for accessibility
9215      * or if this view is not important for accessibility will have no effect as the
9216      * screen-reader is not aware of unimportant views.
9217      * </p>
9218      *
9219      * @param afterId The id of a view this one succedees in accessibility traversal.
9220      *
9221      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
9222      *
9223      * @see #setImportantForAccessibility(int)
9224      */
9225     @RemotableViewMethod
9226     public void setAccessibilityTraversalAfter(int afterId) {
9227         if (mAccessibilityTraversalAfterId == afterId) {
9228             return;
9229         }
9230         mAccessibilityTraversalAfterId = afterId;
9231         notifyViewAccessibilityStateChangedIfNeeded(
9232                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9233     }
9234 
9235     /**
9236      * Gets the id of a view after which this one is visited in accessibility traversal.
9237      *
9238      * @return The id of a view this one succeedes in accessibility traversal if
9239      *         specified, otherwise {@link #NO_ID}.
9240      *
9241      * @see #setAccessibilityTraversalAfter(int)
9242      */
9243     public int getAccessibilityTraversalAfter() {
9244         return mAccessibilityTraversalAfterId;
9245     }
9246 
9247     /**
9248      * Gets the id of a view for which this view serves as a label for
9249      * accessibility purposes.
9250      *
9251      * @return The labeled view id.
9252      */
9253     @ViewDebug.ExportedProperty(category = "accessibility")
9254     public int getLabelFor() {
9255         return mLabelForId;
9256     }
9257 
9258     /**
9259      * Sets the id of a view for which this view serves as a label for
9260      * accessibility purposes.
9261      *
9262      * @param id The labeled view id.
9263      */
9264     @RemotableViewMethod
9265     public void setLabelFor(@IdRes int id) {
9266         if (mLabelForId == id) {
9267             return;
9268         }
9269         mLabelForId = id;
9270         if (mLabelForId != View.NO_ID
9271                 && mID == View.NO_ID) {
9272             mID = generateViewId();
9273         }
9274         notifyViewAccessibilityStateChangedIfNeeded(
9275                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9276     }
9277 
9278     /**
9279      * Invoked whenever this view loses focus, either by losing window focus or by losing
9280      * focus within its window. This method can be used to clear any state tied to the
9281      * focus. For instance, if a button is held pressed with the trackball and the window
9282      * loses focus, this method can be used to cancel the press.
9283      *
9284      * Subclasses of View overriding this method should always call super.onFocusLost().
9285      *
9286      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
9287      * @see #onWindowFocusChanged(boolean)
9288      *
9289      * @hide pending API council approval
9290      */
9291     @CallSuper
9292     protected void onFocusLost() {
9293         resetPressedState();
9294     }
9295 
9296     private void resetPressedState() {
9297         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9298             return;
9299         }
9300 
9301         if (isPressed()) {
9302             setPressed(false);
9303 
9304             if (!mHasPerformedLongPress) {
9305                 removeLongPressCallback();
9306             }
9307         }
9308     }
9309 
9310     /**
9311      * Returns true if this view has focus
9312      *
9313      * @return True if this view has focus, false otherwise.
9314      */
9315     @ViewDebug.ExportedProperty(category = "focus")
9316     public boolean isFocused() {
9317         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
9318     }
9319 
9320     /**
9321      * Find the view in the hierarchy rooted at this view that currently has
9322      * focus.
9323      *
9324      * @return The view that currently has focus, or null if no focused view can
9325      *         be found.
9326      */
9327     public View findFocus() {
9328         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
9329     }
9330 
9331     /**
9332      * Indicates whether this view is one of the set of scrollable containers in
9333      * its window.
9334      *
9335      * @return whether this view is one of the set of scrollable containers in
9336      * its window
9337      *
9338      * @attr ref android.R.styleable#View_isScrollContainer
9339      */
9340     public boolean isScrollContainer() {
9341         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
9342     }
9343 
9344     /**
9345      * Change whether this view is one of the set of scrollable containers in
9346      * its window.  This will be used to determine whether the window can
9347      * resize or must pan when a soft input area is open -- scrollable
9348      * containers allow the window to use resize mode since the container
9349      * will appropriately shrink.
9350      *
9351      * @attr ref android.R.styleable#View_isScrollContainer
9352      */
9353     public void setScrollContainer(boolean isScrollContainer) {
9354         if (isScrollContainer) {
9355             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
9356                 mAttachInfo.mScrollContainers.add(this);
9357                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
9358             }
9359             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
9360         } else {
9361             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
9362                 mAttachInfo.mScrollContainers.remove(this);
9363             }
9364             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
9365         }
9366     }
9367 
9368     /**
9369      * Returns the quality of the drawing cache.
9370      *
9371      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
9372      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
9373      *
9374      * @see #setDrawingCacheQuality(int)
9375      * @see #setDrawingCacheEnabled(boolean)
9376      * @see #isDrawingCacheEnabled()
9377      *
9378      * @attr ref android.R.styleable#View_drawingCacheQuality
9379      *
9380      * @deprecated The view drawing cache was largely made obsolete with the introduction of
9381      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
9382      * layers are largely unnecessary and can easily result in a net loss in performance due to the
9383      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
9384      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
9385      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
9386      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
9387      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
9388      * software-rendered usages are discouraged and have compatibility issues with hardware-only
9389      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
9390      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
9391      * reports or unit testing the {@link PixelCopy} API is recommended.
9392      */
9393     @Deprecated
9394     @DrawingCacheQuality
9395     public int getDrawingCacheQuality() {
9396         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
9397     }
9398 
9399     /**
9400      * Set the drawing cache quality of this view. This value is used only when the
9401      * drawing cache is enabled
9402      *
9403      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
9404      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
9405      *
9406      * @see #getDrawingCacheQuality()
9407      * @see #setDrawingCacheEnabled(boolean)
9408      * @see #isDrawingCacheEnabled()
9409      *
9410      * @attr ref android.R.styleable#View_drawingCacheQuality
9411      *
9412      * @deprecated The view drawing cache was largely made obsolete with the introduction of
9413      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
9414      * layers are largely unnecessary and can easily result in a net loss in performance due to the
9415      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
9416      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
9417      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
9418      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
9419      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
9420      * software-rendered usages are discouraged and have compatibility issues with hardware-only
9421      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
9422      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
9423      * reports or unit testing the {@link PixelCopy} API is recommended.
9424      */
9425     @Deprecated
9426     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
9427         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
9428     }
9429 
9430     /**
9431      * Returns whether the screen should remain on, corresponding to the current
9432      * value of {@link #KEEP_SCREEN_ON}.
9433      *
9434      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
9435      *
9436      * @see #setKeepScreenOn(boolean)
9437      *
9438      * @attr ref android.R.styleable#View_keepScreenOn
9439      */
9440     public boolean getKeepScreenOn() {
9441         return (mViewFlags & KEEP_SCREEN_ON) != 0;
9442     }
9443 
9444     /**
9445      * Controls whether the screen should remain on, modifying the
9446      * value of {@link #KEEP_SCREEN_ON}.
9447      *
9448      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
9449      *
9450      * @see #getKeepScreenOn()
9451      *
9452      * @attr ref android.R.styleable#View_keepScreenOn
9453      */
9454     public void setKeepScreenOn(boolean keepScreenOn) {
9455         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
9456     }
9457 
9458     /**
9459      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
9460      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
9461      *
9462      * @attr ref android.R.styleable#View_nextFocusLeft
9463      */
9464     public int getNextFocusLeftId() {
9465         return mNextFocusLeftId;
9466     }
9467 
9468     /**
9469      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
9470      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
9471      * decide automatically.
9472      *
9473      * @attr ref android.R.styleable#View_nextFocusLeft
9474      */
9475     public void setNextFocusLeftId(int nextFocusLeftId) {
9476         mNextFocusLeftId = nextFocusLeftId;
9477     }
9478 
9479     /**
9480      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
9481      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
9482      *
9483      * @attr ref android.R.styleable#View_nextFocusRight
9484      */
9485     public int getNextFocusRightId() {
9486         return mNextFocusRightId;
9487     }
9488 
9489     /**
9490      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
9491      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
9492      * decide automatically.
9493      *
9494      * @attr ref android.R.styleable#View_nextFocusRight
9495      */
9496     public void setNextFocusRightId(int nextFocusRightId) {
9497         mNextFocusRightId = nextFocusRightId;
9498     }
9499 
9500     /**
9501      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
9502      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
9503      *
9504      * @attr ref android.R.styleable#View_nextFocusUp
9505      */
9506     public int getNextFocusUpId() {
9507         return mNextFocusUpId;
9508     }
9509 
9510     /**
9511      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
9512      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
9513      * decide automatically.
9514      *
9515      * @attr ref android.R.styleable#View_nextFocusUp
9516      */
9517     public void setNextFocusUpId(int nextFocusUpId) {
9518         mNextFocusUpId = nextFocusUpId;
9519     }
9520 
9521     /**
9522      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
9523      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
9524      *
9525      * @attr ref android.R.styleable#View_nextFocusDown
9526      */
9527     public int getNextFocusDownId() {
9528         return mNextFocusDownId;
9529     }
9530 
9531     /**
9532      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
9533      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
9534      * decide automatically.
9535      *
9536      * @attr ref android.R.styleable#View_nextFocusDown
9537      */
9538     public void setNextFocusDownId(int nextFocusDownId) {
9539         mNextFocusDownId = nextFocusDownId;
9540     }
9541 
9542     /**
9543      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
9544      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
9545      *
9546      * @attr ref android.R.styleable#View_nextFocusForward
9547      */
9548     public int getNextFocusForwardId() {
9549         return mNextFocusForwardId;
9550     }
9551 
9552     /**
9553      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
9554      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
9555      * decide automatically.
9556      *
9557      * @attr ref android.R.styleable#View_nextFocusForward
9558      */
9559     public void setNextFocusForwardId(int nextFocusForwardId) {
9560         mNextFocusForwardId = nextFocusForwardId;
9561     }
9562 
9563     /**
9564      * Gets the id of the root of the next keyboard navigation cluster.
9565      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
9566      * decide automatically.
9567      *
9568      * @attr ref android.R.styleable#View_nextClusterForward
9569      */
9570     public int getNextClusterForwardId() {
9571         return mNextClusterForwardId;
9572     }
9573 
9574     /**
9575      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
9576      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
9577      * decide automatically.
9578      *
9579      * @attr ref android.R.styleable#View_nextClusterForward
9580      */
9581     public void setNextClusterForwardId(int nextClusterForwardId) {
9582         mNextClusterForwardId = nextClusterForwardId;
9583     }
9584 
9585     /**
9586      * Returns the visibility of this view and all of its ancestors
9587      *
9588      * @return True if this view and all of its ancestors are {@link #VISIBLE}
9589      */
9590     public boolean isShown() {
9591         View current = this;
9592         //noinspection ConstantConditions
9593         do {
9594             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9595                 return false;
9596             }
9597             ViewParent parent = current.mParent;
9598             if (parent == null) {
9599                 return false; // We are not attached to the view root
9600             }
9601             if (!(parent instanceof View)) {
9602                 return true;
9603             }
9604             current = (View) parent;
9605         } while (current != null);
9606 
9607         return false;
9608     }
9609 
9610     /**
9611      * Called by the view hierarchy when the content insets for a window have
9612      * changed, to allow it to adjust its content to fit within those windows.
9613      * The content insets tell you the space that the status bar, input method,
9614      * and other system windows infringe on the application's window.
9615      *
9616      * <p>You do not normally need to deal with this function, since the default
9617      * window decoration given to applications takes care of applying it to the
9618      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
9619      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
9620      * and your content can be placed under those system elements.  You can then
9621      * use this method within your view hierarchy if you have parts of your UI
9622      * which you would like to ensure are not being covered.
9623      *
9624      * <p>The default implementation of this method simply applies the content
9625      * insets to the view's padding, consuming that content (modifying the
9626      * insets to be 0), and returning true.  This behavior is off by default, but can
9627      * be enabled through {@link #setFitsSystemWindows(boolean)}.
9628      *
9629      * <p>This function's traversal down the hierarchy is depth-first.  The same content
9630      * insets object is propagated down the hierarchy, so any changes made to it will
9631      * be seen by all following views (including potentially ones above in
9632      * the hierarchy since this is a depth-first traversal).  The first view
9633      * that returns true will abort the entire traversal.
9634      *
9635      * <p>The default implementation works well for a situation where it is
9636      * used with a container that covers the entire window, allowing it to
9637      * apply the appropriate insets to its content on all edges.  If you need
9638      * a more complicated layout (such as two different views fitting system
9639      * windows, one on the top of the window, and one on the bottom),
9640      * you can override the method and handle the insets however you would like.
9641      * Note that the insets provided by the framework are always relative to the
9642      * far edges of the window, not accounting for the location of the called view
9643      * within that window.  (In fact when this method is called you do not yet know
9644      * where the layout will place the view, as it is done before layout happens.)
9645      *
9646      * <p>Note: unlike many View methods, there is no dispatch phase to this
9647      * call.  If you are overriding it in a ViewGroup and want to allow the
9648      * call to continue to your children, you must be sure to call the super
9649      * implementation.
9650      *
9651      * <p>Here is a sample layout that makes use of fitting system windows
9652      * to have controls for a video view placed inside of the window decorations
9653      * that it hides and shows.  This can be used with code like the second
9654      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
9655      *
9656      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
9657      *
9658      * @param insets Current content insets of the window.  Prior to
9659      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
9660      * the insets or else you and Android will be unhappy.
9661      *
9662      * @return {@code true} if this view applied the insets and it should not
9663      * continue propagating further down the hierarchy, {@code false} otherwise.
9664      * @see #getFitsSystemWindows()
9665      * @see #setFitsSystemWindows(boolean)
9666      * @see #setSystemUiVisibility(int)
9667      *
9668      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
9669      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
9670      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
9671      * to implement handling their own insets.
9672      */
9673     @Deprecated
9674     protected boolean fitSystemWindows(Rect insets) {
9675         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
9676             if (insets == null) {
9677                 // Null insets by definition have already been consumed.
9678                 // This call cannot apply insets since there are none to apply,
9679                 // so return false.
9680                 return false;
9681             }
9682             // If we're not in the process of dispatching the newer apply insets call,
9683             // that means we're not in the compatibility path. Dispatch into the newer
9684             // apply insets path and take things from there.
9685             try {
9686                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
9687                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
9688             } finally {
9689                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
9690             }
9691         } else {
9692             // We're being called from the newer apply insets path.
9693             // Perform the standard fallback behavior.
9694             return fitSystemWindowsInt(insets);
9695         }
9696     }
9697 
9698     private boolean fitSystemWindowsInt(Rect insets) {
9699         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
9700             mUserPaddingStart = UNDEFINED_PADDING;
9701             mUserPaddingEnd = UNDEFINED_PADDING;
9702             Rect localInsets = sThreadLocal.get();
9703             if (localInsets == null) {
9704                 localInsets = new Rect();
9705                 sThreadLocal.set(localInsets);
9706             }
9707             boolean res = computeFitSystemWindows(insets, localInsets);
9708             mUserPaddingLeftInitial = localInsets.left;
9709             mUserPaddingRightInitial = localInsets.right;
9710             internalSetPadding(localInsets.left, localInsets.top,
9711                     localInsets.right, localInsets.bottom);
9712             return res;
9713         }
9714         return false;
9715     }
9716 
9717     /**
9718      * Called when the view should apply {@link WindowInsets} according to its internal policy.
9719      *
9720      * <p>This method should be overridden by views that wish to apply a policy different from or
9721      * in addition to the default behavior. Clients that wish to force a view subtree
9722      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
9723      *
9724      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
9725      * it will be called during dispatch instead of this method. The listener may optionally
9726      * call this method from its own implementation if it wishes to apply the view's default
9727      * insets policy in addition to its own.</p>
9728      *
9729      * <p>Implementations of this method should either return the insets parameter unchanged
9730      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
9731      * that this view applied itself. This allows new inset types added in future platform
9732      * versions to pass through existing implementations unchanged without being erroneously
9733      * consumed.</p>
9734      *
9735      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
9736      * property is set then the view will consume the system window insets and apply them
9737      * as padding for the view.</p>
9738      *
9739      * @param insets Insets to apply
9740      * @return The supplied insets with any applied insets consumed
9741      */
9742     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
9743         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
9744             // We weren't called from within a direct call to fitSystemWindows,
9745             // call into it as a fallback in case we're in a class that overrides it
9746             // and has logic to perform.
9747             if (fitSystemWindows(insets.getSystemWindowInsets())) {
9748                 return insets.consumeSystemWindowInsets();
9749             }
9750         } else {
9751             // We were called from within a direct call to fitSystemWindows.
9752             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
9753                 return insets.consumeSystemWindowInsets();
9754             }
9755         }
9756         return insets;
9757     }
9758 
9759     /**
9760      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
9761      * window insets to this view. The listener's
9762      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
9763      * method will be called instead of the view's
9764      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
9765      *
9766      * @param listener Listener to set
9767      *
9768      * @see #onApplyWindowInsets(WindowInsets)
9769      */
9770     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
9771         getListenerInfo().mOnApplyWindowInsetsListener = listener;
9772     }
9773 
9774     /**
9775      * Request to apply the given window insets to this view or another view in its subtree.
9776      *
9777      * <p>This method should be called by clients wishing to apply insets corresponding to areas
9778      * obscured by window decorations or overlays. This can include the status and navigation bars,
9779      * action bars, input methods and more. New inset categories may be added in the future.
9780      * The method returns the insets provided minus any that were applied by this view or its
9781      * children.</p>
9782      *
9783      * <p>Clients wishing to provide custom behavior should override the
9784      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
9785      * {@link OnApplyWindowInsetsListener} via the
9786      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
9787      * method.</p>
9788      *
9789      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
9790      * </p>
9791      *
9792      * @param insets Insets to apply
9793      * @return The provided insets minus the insets that were consumed
9794      */
9795     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
9796         try {
9797             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
9798             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
9799                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
9800             } else {
9801                 return onApplyWindowInsets(insets);
9802             }
9803         } finally {
9804             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
9805         }
9806     }
9807 
9808     /**
9809      * Compute the view's coordinate within the surface.
9810      *
9811      * <p>Computes the coordinates of this view in its surface. The argument
9812      * must be an array of two integers. After the method returns, the array
9813      * contains the x and y location in that order.</p>
9814      * @hide
9815      * @param location an array of two integers in which to hold the coordinates
9816      */
9817     public void getLocationInSurface(@Size(2) int[] location) {
9818         getLocationInWindow(location);
9819         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
9820             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
9821             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
9822         }
9823     }
9824 
9825     /**
9826      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
9827      * only available if the view is attached.
9828      *
9829      * @return WindowInsets from the top of the view hierarchy or null if View is detached
9830      */
9831     public WindowInsets getRootWindowInsets() {
9832         if (mAttachInfo != null) {
9833             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
9834         }
9835         return null;
9836     }
9837 
9838     /**
9839      * @hide Compute the insets that should be consumed by this view and the ones
9840      * that should propagate to those under it.
9841      *
9842      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
9843      *
9844      * @param inoutInsets the insets given to this view
9845      * @param outLocalInsets the insets that should be applied to this view
9846      * @deprecated use {@link #computeSystemWindowInsets}
9847      * @return
9848      */
9849     @Deprecated
9850     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
9851         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
9852                 outLocalInsets);
9853         inoutInsets.set(innerInsets.getSystemWindowInsets());
9854         return innerInsets.isSystemWindowInsetsConsumed();
9855     }
9856 
9857     /**
9858      * Compute insets that should be consumed by this view and the ones that should propagate
9859      * to those under it.
9860      *
9861      * @param in Insets currently being processed by this View, likely received as a parameter
9862      *           to {@link #onApplyWindowInsets(WindowInsets)}.
9863      * @param outLocalInsets A Rect that will receive the insets that should be consumed
9864      *                       by this view
9865      * @return Insets that should be passed along to views under this one
9866      */
9867     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
9868         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9869                 || mAttachInfo == null
9870                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
9871                 && !mAttachInfo.mOverscanRequested)) {
9872             outLocalInsets.set(in.getSystemWindowInsets());
9873             return in.consumeSystemWindowInsets().inset(outLocalInsets);
9874         } else {
9875             // The application wants to take care of fitting system window for
9876             // the content...  however we still need to take care of any overscan here.
9877             final Rect overscan = mAttachInfo.mOverscanInsets;
9878             outLocalInsets.set(overscan);
9879             return in.inset(outLocalInsets);
9880         }
9881     }
9882 
9883     /**
9884      * Sets whether or not this view should account for system screen decorations
9885      * such as the status bar and inset its content; that is, controlling whether
9886      * the default implementation of {@link #fitSystemWindows(Rect)} will be
9887      * executed.  See that method for more details.
9888      *
9889      * <p>Note that if you are providing your own implementation of
9890      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
9891      * flag to true -- your implementation will be overriding the default
9892      * implementation that checks this flag.
9893      *
9894      * @param fitSystemWindows If true, then the default implementation of
9895      * {@link #fitSystemWindows(Rect)} will be executed.
9896      *
9897      * @attr ref android.R.styleable#View_fitsSystemWindows
9898      * @see #getFitsSystemWindows()
9899      * @see #fitSystemWindows(Rect)
9900      * @see #setSystemUiVisibility(int)
9901      */
9902     public void setFitsSystemWindows(boolean fitSystemWindows) {
9903         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9904     }
9905 
9906     /**
9907      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9908      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9909      * will be executed.
9910      *
9911      * @return {@code true} if the default implementation of
9912      * {@link #fitSystemWindows(Rect)} will be executed.
9913      *
9914      * @attr ref android.R.styleable#View_fitsSystemWindows
9915      * @see #setFitsSystemWindows(boolean)
9916      * @see #fitSystemWindows(Rect)
9917      * @see #setSystemUiVisibility(int)
9918      */
9919     @ViewDebug.ExportedProperty
9920     public boolean getFitsSystemWindows() {
9921         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9922     }
9923 
9924     /** @hide */
9925     public boolean fitsSystemWindows() {
9926         return getFitsSystemWindows();
9927     }
9928 
9929     /**
9930      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9931      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9932      */
9933     @Deprecated
9934     public void requestFitSystemWindows() {
9935         if (mParent != null) {
9936             mParent.requestFitSystemWindows();
9937         }
9938     }
9939 
9940     /**
9941      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9942      */
9943     public void requestApplyInsets() {
9944         requestFitSystemWindows();
9945     }
9946 
9947     /**
9948      * For use by PhoneWindow to make its own system window fitting optional.
9949      * @hide
9950      */
9951     public void makeOptionalFitsSystemWindows() {
9952         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9953     }
9954 
9955     /**
9956      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9957      * treat them as such.
9958      * @hide
9959      */
9960     public void getOutsets(Rect outOutsetRect) {
9961         if (mAttachInfo != null) {
9962             outOutsetRect.set(mAttachInfo.mOutsets);
9963         } else {
9964             outOutsetRect.setEmpty();
9965         }
9966     }
9967 
9968     /**
9969      * Returns the visibility status for this view.
9970      *
9971      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9972      * @attr ref android.R.styleable#View_visibility
9973      */
9974     @ViewDebug.ExportedProperty(mapping = {
9975         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9976         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9977         @ViewDebug.IntToString(from = GONE,      to = "GONE")
9978     })
9979     @Visibility
9980     public int getVisibility() {
9981         return mViewFlags & VISIBILITY_MASK;
9982     }
9983 
9984     /**
9985      * Set the visibility state of this view.
9986      *
9987      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9988      * @attr ref android.R.styleable#View_visibility
9989      */
9990     @RemotableViewMethod
9991     public void setVisibility(@Visibility int visibility) {
9992         setFlags(visibility, VISIBILITY_MASK);
9993     }
9994 
9995     /**
9996      * Returns the enabled status for this view. The interpretation of the
9997      * enabled state varies by subclass.
9998      *
9999      * @return True if this view is enabled, false otherwise.
10000      */
10001     @ViewDebug.ExportedProperty
10002     public boolean isEnabled() {
10003         return (mViewFlags & ENABLED_MASK) == ENABLED;
10004     }
10005 
10006     /**
10007      * Set the enabled state of this view. The interpretation of the enabled
10008      * state varies by subclass.
10009      *
10010      * @param enabled True if this view is enabled, false otherwise.
10011      */
10012     @RemotableViewMethod
10013     public void setEnabled(boolean enabled) {
10014         if (enabled == isEnabled()) return;
10015 
10016         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
10017 
10018         /*
10019          * The View most likely has to change its appearance, so refresh
10020          * the drawable state.
10021          */
10022         refreshDrawableState();
10023 
10024         // Invalidate too, since the default behavior for views is to be
10025         // be drawn at 50% alpha rather than to change the drawable.
10026         invalidate(true);
10027 
10028         if (!enabled) {
10029             cancelPendingInputEvents();
10030         }
10031     }
10032 
10033     /**
10034      * Set whether this view can receive the focus.
10035      * <p>
10036      * Setting this to false will also ensure that this view is not focusable
10037      * in touch mode.
10038      *
10039      * @param focusable If true, this view can receive the focus.
10040      *
10041      * @see #setFocusableInTouchMode(boolean)
10042      * @see #setFocusable(int)
10043      * @attr ref android.R.styleable#View_focusable
10044      */
10045     public void setFocusable(boolean focusable) {
10046         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
10047     }
10048 
10049     /**
10050      * Sets whether this view can receive focus.
10051      * <p>
10052      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
10053      * automatically based on the view's interactivity. This is the default.
10054      * <p>
10055      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
10056      * in touch mode.
10057      *
10058      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
10059      *                  or {@link #FOCUSABLE_AUTO}.
10060      * @see #setFocusableInTouchMode(boolean)
10061      * @attr ref android.R.styleable#View_focusable
10062      */
10063     public void setFocusable(@Focusable int focusable) {
10064         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
10065             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
10066         }
10067         setFlags(focusable, FOCUSABLE_MASK);
10068     }
10069 
10070     /**
10071      * Set whether this view can receive focus while in touch mode.
10072      *
10073      * Setting this to true will also ensure that this view is focusable.
10074      *
10075      * @param focusableInTouchMode If true, this view can receive the focus while
10076      *   in touch mode.
10077      *
10078      * @see #setFocusable(boolean)
10079      * @attr ref android.R.styleable#View_focusableInTouchMode
10080      */
10081     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
10082         // Focusable in touch mode should always be set before the focusable flag
10083         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
10084         // which, in touch mode, will not successfully request focus on this view
10085         // because the focusable in touch mode flag is not set
10086         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
10087 
10088         // Clear FOCUSABLE_AUTO if set.
10089         if (focusableInTouchMode) {
10090             // Clears FOCUSABLE_AUTO if set.
10091             setFlags(FOCUSABLE, FOCUSABLE_MASK);
10092         }
10093     }
10094 
10095     /**
10096      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
10097      * to autofill the view with the user's data.
10098      *
10099      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
10100      * For example, if the application accepts either an username or email address to identify
10101      * an user.
10102      *
10103      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
10104      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
10105      * constants such as:
10106      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
10107      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
10108      * {@link #AUTOFILL_HINT_NAME},
10109      * {@link #AUTOFILL_HINT_PHONE},
10110      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
10111      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
10112      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
10113      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
10114      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
10115      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
10116      *
10117      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
10118      * @attr ref android.R.styleable#View_autofillHints
10119      */
10120     public void setAutofillHints(@Nullable String... autofillHints) {
10121         if (autofillHints == null || autofillHints.length == 0) {
10122             mAutofillHints = null;
10123         } else {
10124             mAutofillHints = autofillHints;
10125         }
10126     }
10127 
10128     /**
10129      * @hide
10130      */
10131     @TestApi
10132     public void setAutofilled(boolean isAutofilled) {
10133         boolean wasChanged = isAutofilled != isAutofilled();
10134 
10135         if (wasChanged) {
10136             if (isAutofilled) {
10137                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
10138             } else {
10139                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
10140             }
10141 
10142             invalidate();
10143         }
10144     }
10145 
10146     /**
10147      * Set whether this view should have sound effects enabled for events such as
10148      * clicking and touching.
10149      *
10150      * <p>You may wish to disable sound effects for a view if you already play sounds,
10151      * for instance, a dial key that plays dtmf tones.
10152      *
10153      * @param soundEffectsEnabled whether sound effects are enabled for this view.
10154      * @see #isSoundEffectsEnabled()
10155      * @see #playSoundEffect(int)
10156      * @attr ref android.R.styleable#View_soundEffectsEnabled
10157      */
10158     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
10159         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
10160     }
10161 
10162     /**
10163      * @return whether this view should have sound effects enabled for events such as
10164      *     clicking and touching.
10165      *
10166      * @see #setSoundEffectsEnabled(boolean)
10167      * @see #playSoundEffect(int)
10168      * @attr ref android.R.styleable#View_soundEffectsEnabled
10169      */
10170     @ViewDebug.ExportedProperty
10171     public boolean isSoundEffectsEnabled() {
10172         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
10173     }
10174 
10175     /**
10176      * Set whether this view should have haptic feedback for events such as
10177      * long presses.
10178      *
10179      * <p>You may wish to disable haptic feedback if your view already controls
10180      * its own haptic feedback.
10181      *
10182      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
10183      * @see #isHapticFeedbackEnabled()
10184      * @see #performHapticFeedback(int)
10185      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
10186      */
10187     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
10188         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
10189     }
10190 
10191     /**
10192      * @return whether this view should have haptic feedback enabled for events
10193      * long presses.
10194      *
10195      * @see #setHapticFeedbackEnabled(boolean)
10196      * @see #performHapticFeedback(int)
10197      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
10198      */
10199     @ViewDebug.ExportedProperty
10200     public boolean isHapticFeedbackEnabled() {
10201         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
10202     }
10203 
10204     /**
10205      * Returns the layout direction for this view.
10206      *
10207      * @return One of {@link #LAYOUT_DIRECTION_LTR},
10208      *   {@link #LAYOUT_DIRECTION_RTL},
10209      *   {@link #LAYOUT_DIRECTION_INHERIT} or
10210      *   {@link #LAYOUT_DIRECTION_LOCALE}.
10211      *
10212      * @attr ref android.R.styleable#View_layoutDirection
10213      *
10214      * @hide
10215      */
10216     @ViewDebug.ExportedProperty(category = "layout", mapping = {
10217         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
10218         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
10219         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
10220         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
10221     })
10222     @LayoutDir
10223     public int getRawLayoutDirection() {
10224         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
10225     }
10226 
10227     /**
10228      * Set the layout direction for this view. This will propagate a reset of layout direction
10229      * resolution to the view's children and resolve layout direction for this view.
10230      *
10231      * @param layoutDirection the layout direction to set. Should be one of:
10232      *
10233      * {@link #LAYOUT_DIRECTION_LTR},
10234      * {@link #LAYOUT_DIRECTION_RTL},
10235      * {@link #LAYOUT_DIRECTION_INHERIT},
10236      * {@link #LAYOUT_DIRECTION_LOCALE}.
10237      *
10238      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
10239      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
10240      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
10241      *
10242      * @attr ref android.R.styleable#View_layoutDirection
10243      */
10244     @RemotableViewMethod
10245     public void setLayoutDirection(@LayoutDir int layoutDirection) {
10246         if (getRawLayoutDirection() != layoutDirection) {
10247             // Reset the current layout direction and the resolved one
10248             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
10249             resetRtlProperties();
10250             // Set the new layout direction (filtered)
10251             mPrivateFlags2 |=
10252                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
10253             // We need to resolve all RTL properties as they all depend on layout direction
10254             resolveRtlPropertiesIfNeeded();
10255             requestLayout();
10256             invalidate(true);
10257         }
10258     }
10259 
10260     /**
10261      * Returns the resolved layout direction for this view.
10262      *
10263      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
10264      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
10265      *
10266      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
10267      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
10268      *
10269      * @attr ref android.R.styleable#View_layoutDirection
10270      */
10271     @ViewDebug.ExportedProperty(category = "layout", mapping = {
10272         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
10273         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
10274     })
10275     @ResolvedLayoutDir
10276     public int getLayoutDirection() {
10277         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
10278         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
10279             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
10280             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
10281         }
10282         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
10283                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
10284     }
10285 
10286     /**
10287      * Indicates whether or not this view's layout is right-to-left. This is resolved from
10288      * layout attribute and/or the inherited value from the parent
10289      *
10290      * @return true if the layout is right-to-left.
10291      *
10292      * @hide
10293      */
10294     @ViewDebug.ExportedProperty(category = "layout")
10295     public boolean isLayoutRtl() {
10296         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
10297     }
10298 
10299     /**
10300      * Indicates whether the view is currently tracking transient state that the
10301      * app should not need to concern itself with saving and restoring, but that
10302      * the framework should take special note to preserve when possible.
10303      *
10304      * <p>A view with transient state cannot be trivially rebound from an external
10305      * data source, such as an adapter binding item views in a list. This may be
10306      * because the view is performing an animation, tracking user selection
10307      * of content, or similar.</p>
10308      *
10309      * @return true if the view has transient state
10310      */
10311     @ViewDebug.ExportedProperty(category = "layout")
10312     public boolean hasTransientState() {
10313         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
10314     }
10315 
10316     /**
10317      * Set whether this view is currently tracking transient state that the
10318      * framework should attempt to preserve when possible. This flag is reference counted,
10319      * so every call to setHasTransientState(true) should be paired with a later call
10320      * to setHasTransientState(false).
10321      *
10322      * <p>A view with transient state cannot be trivially rebound from an external
10323      * data source, such as an adapter binding item views in a list. This may be
10324      * because the view is performing an animation, tracking user selection
10325      * of content, or similar.</p>
10326      *
10327      * @param hasTransientState true if this view has transient state
10328      */
10329     public void setHasTransientState(boolean hasTransientState) {
10330         final boolean oldHasTransientState = hasTransientState();
10331         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
10332                 mTransientStateCount - 1;
10333         if (mTransientStateCount < 0) {
10334             mTransientStateCount = 0;
10335             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
10336                     "unmatched pair of setHasTransientState calls");
10337         } else if ((hasTransientState && mTransientStateCount == 1) ||
10338                 (!hasTransientState && mTransientStateCount == 0)) {
10339             // update flag if we've just incremented up from 0 or decremented down to 0
10340             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
10341                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
10342             final boolean newHasTransientState = hasTransientState();
10343             if (mParent != null && newHasTransientState != oldHasTransientState) {
10344                 try {
10345                     mParent.childHasTransientStateChanged(this, newHasTransientState);
10346                 } catch (AbstractMethodError e) {
10347                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10348                             " does not fully implement ViewParent", e);
10349                 }
10350             }
10351         }
10352     }
10353 
10354     /**
10355      * Returns true if this view is currently attached to a window.
10356      */
10357     public boolean isAttachedToWindow() {
10358         return mAttachInfo != null;
10359     }
10360 
10361     /**
10362      * Returns true if this view has been through at least one layout since it
10363      * was last attached to or detached from a window.
10364      */
10365     public boolean isLaidOut() {
10366         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
10367     }
10368 
10369     /**
10370      * @return {@code true} if laid-out and not about to do another layout.
10371      */
10372     boolean isLayoutValid() {
10373         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
10374     }
10375 
10376     /**
10377      * If this view doesn't do any drawing on its own, set this flag to
10378      * allow further optimizations. By default, this flag is not set on
10379      * View, but could be set on some View subclasses such as ViewGroup.
10380      *
10381      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
10382      * you should clear this flag.
10383      *
10384      * @param willNotDraw whether or not this View draw on its own
10385      */
10386     public void setWillNotDraw(boolean willNotDraw) {
10387         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
10388     }
10389 
10390     /**
10391      * Returns whether or not this View draws on its own.
10392      *
10393      * @return true if this view has nothing to draw, false otherwise
10394      */
10395     @ViewDebug.ExportedProperty(category = "drawing")
10396     public boolean willNotDraw() {
10397         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
10398     }
10399 
10400     /**
10401      * When a View's drawing cache is enabled, drawing is redirected to an
10402      * offscreen bitmap. Some views, like an ImageView, must be able to
10403      * bypass this mechanism if they already draw a single bitmap, to avoid
10404      * unnecessary usage of the memory.
10405      *
10406      * @param willNotCacheDrawing true if this view does not cache its
10407      *        drawing, false otherwise
10408      *
10409      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10410      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10411      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10412      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10413      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10414      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10415      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10416      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10417      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10418      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10419      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10420      * reports or unit testing the {@link PixelCopy} API is recommended.
10421      */
10422     @Deprecated
10423     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
10424         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
10425     }
10426 
10427     /**
10428      * Returns whether or not this View can cache its drawing or not.
10429      *
10430      * @return true if this view does not cache its drawing, false otherwise
10431      *
10432      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10433      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10434      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10435      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10436      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10437      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10438      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10439      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10440      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10441      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10442      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10443      * reports or unit testing the {@link PixelCopy} API is recommended.
10444      */
10445     @ViewDebug.ExportedProperty(category = "drawing")
10446     @Deprecated
10447     public boolean willNotCacheDrawing() {
10448         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
10449     }
10450 
10451     /**
10452      * Indicates whether this view reacts to click events or not.
10453      *
10454      * @return true if the view is clickable, false otherwise
10455      *
10456      * @see #setClickable(boolean)
10457      * @attr ref android.R.styleable#View_clickable
10458      */
10459     @ViewDebug.ExportedProperty
10460     public boolean isClickable() {
10461         return (mViewFlags & CLICKABLE) == CLICKABLE;
10462     }
10463 
10464     /**
10465      * Enables or disables click events for this view. When a view
10466      * is clickable it will change its state to "pressed" on every click.
10467      * Subclasses should set the view clickable to visually react to
10468      * user's clicks.
10469      *
10470      * @param clickable true to make the view clickable, false otherwise
10471      *
10472      * @see #isClickable()
10473      * @attr ref android.R.styleable#View_clickable
10474      */
10475     public void setClickable(boolean clickable) {
10476         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
10477     }
10478 
10479     /**
10480      * Indicates whether this view reacts to long click events or not.
10481      *
10482      * @return true if the view is long clickable, false otherwise
10483      *
10484      * @see #setLongClickable(boolean)
10485      * @attr ref android.R.styleable#View_longClickable
10486      */
10487     public boolean isLongClickable() {
10488         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
10489     }
10490 
10491     /**
10492      * Enables or disables long click events for this view. When a view is long
10493      * clickable it reacts to the user holding down the button for a longer
10494      * duration than a tap. This event can either launch the listener or a
10495      * context menu.
10496      *
10497      * @param longClickable true to make the view long clickable, false otherwise
10498      * @see #isLongClickable()
10499      * @attr ref android.R.styleable#View_longClickable
10500      */
10501     public void setLongClickable(boolean longClickable) {
10502         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
10503     }
10504 
10505     /**
10506      * Indicates whether this view reacts to context clicks or not.
10507      *
10508      * @return true if the view is context clickable, false otherwise
10509      * @see #setContextClickable(boolean)
10510      * @attr ref android.R.styleable#View_contextClickable
10511      */
10512     public boolean isContextClickable() {
10513         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10514     }
10515 
10516     /**
10517      * Enables or disables context clicking for this view. This event can launch the listener.
10518      *
10519      * @param contextClickable true to make the view react to a context click, false otherwise
10520      * @see #isContextClickable()
10521      * @attr ref android.R.styleable#View_contextClickable
10522      */
10523     public void setContextClickable(boolean contextClickable) {
10524         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
10525     }
10526 
10527     /**
10528      * Sets the pressed state for this view and provides a touch coordinate for
10529      * animation hinting.
10530      *
10531      * @param pressed Pass true to set the View's internal state to "pressed",
10532      *            or false to reverts the View's internal state from a
10533      *            previously set "pressed" state.
10534      * @param x The x coordinate of the touch that caused the press
10535      * @param y The y coordinate of the touch that caused the press
10536      */
10537     private void setPressed(boolean pressed, float x, float y) {
10538         if (pressed) {
10539             drawableHotspotChanged(x, y);
10540         }
10541 
10542         setPressed(pressed);
10543     }
10544 
10545     /**
10546      * Sets the pressed state for this view.
10547      *
10548      * @see #isClickable()
10549      * @see #setClickable(boolean)
10550      *
10551      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
10552      *        the View's internal state from a previously set "pressed" state.
10553      */
10554     public void setPressed(boolean pressed) {
10555         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
10556 
10557         if (pressed) {
10558             mPrivateFlags |= PFLAG_PRESSED;
10559         } else {
10560             mPrivateFlags &= ~PFLAG_PRESSED;
10561         }
10562 
10563         if (needsRefresh) {
10564             refreshDrawableState();
10565         }
10566         dispatchSetPressed(pressed);
10567     }
10568 
10569     /**
10570      * Dispatch setPressed to all of this View's children.
10571      *
10572      * @see #setPressed(boolean)
10573      *
10574      * @param pressed The new pressed state
10575      */
10576     protected void dispatchSetPressed(boolean pressed) {
10577     }
10578 
10579     /**
10580      * Indicates whether the view is currently in pressed state. Unless
10581      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
10582      * the pressed state.
10583      *
10584      * @see #setPressed(boolean)
10585      * @see #isClickable()
10586      * @see #setClickable(boolean)
10587      *
10588      * @return true if the view is currently pressed, false otherwise
10589      */
10590     @ViewDebug.ExportedProperty
10591     public boolean isPressed() {
10592         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
10593     }
10594 
10595     /**
10596      * @hide
10597      * Indicates whether this view will participate in data collection through
10598      * {@link ViewStructure}.  If true, it will not provide any data
10599      * for itself or its children.  If false, the normal data collection will be allowed.
10600      *
10601      * @return Returns false if assist data collection is not blocked, else true.
10602      *
10603      * @see #setAssistBlocked(boolean)
10604      * @attr ref android.R.styleable#View_assistBlocked
10605      */
10606     public boolean isAssistBlocked() {
10607         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
10608     }
10609 
10610     /**
10611      * @hide
10612      * Controls whether assist data collection from this view and its children is enabled
10613      * (that is, whether {@link #onProvideStructure} and
10614      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
10615      * allowing normal assist collection.  Setting this to false will disable assist collection.
10616      *
10617      * @param enabled Set to true to <em>disable</em> assist data collection, or false
10618      * (the default) to allow it.
10619      *
10620      * @see #isAssistBlocked()
10621      * @see #onProvideStructure
10622      * @see #onProvideVirtualStructure
10623      * @attr ref android.R.styleable#View_assistBlocked
10624      */
10625     public void setAssistBlocked(boolean enabled) {
10626         if (enabled) {
10627             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
10628         } else {
10629             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
10630         }
10631     }
10632 
10633     /**
10634      * Indicates whether this view will save its state (that is,
10635      * whether its {@link #onSaveInstanceState} method will be called).
10636      *
10637      * @return Returns true if the view state saving is enabled, else false.
10638      *
10639      * @see #setSaveEnabled(boolean)
10640      * @attr ref android.R.styleable#View_saveEnabled
10641      */
10642     public boolean isSaveEnabled() {
10643         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
10644     }
10645 
10646     /**
10647      * Controls whether the saving of this view's state is
10648      * enabled (that is, whether its {@link #onSaveInstanceState} method
10649      * will be called).  Note that even if freezing is enabled, the
10650      * view still must have an id assigned to it (via {@link #setId(int)})
10651      * for its state to be saved.  This flag can only disable the
10652      * saving of this view; any child views may still have their state saved.
10653      *
10654      * @param enabled Set to false to <em>disable</em> state saving, or true
10655      * (the default) to allow it.
10656      *
10657      * @see #isSaveEnabled()
10658      * @see #setId(int)
10659      * @see #onSaveInstanceState()
10660      * @attr ref android.R.styleable#View_saveEnabled
10661      */
10662     public void setSaveEnabled(boolean enabled) {
10663         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
10664     }
10665 
10666     /**
10667      * Gets whether the framework should discard touches when the view's
10668      * window is obscured by another visible window.
10669      * Refer to the {@link View} security documentation for more details.
10670      *
10671      * @return True if touch filtering is enabled.
10672      *
10673      * @see #setFilterTouchesWhenObscured(boolean)
10674      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10675      */
10676     @ViewDebug.ExportedProperty
10677     public boolean getFilterTouchesWhenObscured() {
10678         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
10679     }
10680 
10681     /**
10682      * Sets whether the framework should discard touches when the view's
10683      * window is obscured by another visible window.
10684      * Refer to the {@link View} security documentation for more details.
10685      *
10686      * @param enabled True if touch filtering should be enabled.
10687      *
10688      * @see #getFilterTouchesWhenObscured
10689      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10690      */
10691     public void setFilterTouchesWhenObscured(boolean enabled) {
10692         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
10693                 FILTER_TOUCHES_WHEN_OBSCURED);
10694     }
10695 
10696     /**
10697      * Indicates whether the entire hierarchy under this view will save its
10698      * state when a state saving traversal occurs from its parent.  The default
10699      * is true; if false, these views will not be saved unless
10700      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10701      *
10702      * @return Returns true if the view state saving from parent is enabled, else false.
10703      *
10704      * @see #setSaveFromParentEnabled(boolean)
10705      */
10706     public boolean isSaveFromParentEnabled() {
10707         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
10708     }
10709 
10710     /**
10711      * Controls whether the entire hierarchy under this view will save its
10712      * state when a state saving traversal occurs from its parent.  The default
10713      * is true; if false, these views will not be saved unless
10714      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10715      *
10716      * @param enabled Set to false to <em>disable</em> state saving, or true
10717      * (the default) to allow it.
10718      *
10719      * @see #isSaveFromParentEnabled()
10720      * @see #setId(int)
10721      * @see #onSaveInstanceState()
10722      */
10723     public void setSaveFromParentEnabled(boolean enabled) {
10724         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
10725     }
10726 
10727 
10728     /**
10729      * Returns whether this View is currently able to take focus.
10730      *
10731      * @return True if this view can take focus, or false otherwise.
10732      */
10733     @ViewDebug.ExportedProperty(category = "focus")
10734     public final boolean isFocusable() {
10735         return FOCUSABLE == (mViewFlags & FOCUSABLE);
10736     }
10737 
10738     /**
10739      * Returns the focusable setting for this view.
10740      *
10741      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
10742      * @attr ref android.R.styleable#View_focusable
10743      */
10744     @ViewDebug.ExportedProperty(mapping = {
10745             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
10746             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
10747             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
10748             }, category = "focus")
10749     @Focusable
10750     public int getFocusable() {
10751         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
10752     }
10753 
10754     /**
10755      * When a view is focusable, it may not want to take focus when in touch mode.
10756      * For example, a button would like focus when the user is navigating via a D-pad
10757      * so that the user can click on it, but once the user starts touching the screen,
10758      * the button shouldn't take focus
10759      * @return Whether the view is focusable in touch mode.
10760      * @attr ref android.R.styleable#View_focusableInTouchMode
10761      */
10762     @ViewDebug.ExportedProperty(category = "focus")
10763     public final boolean isFocusableInTouchMode() {
10764         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
10765     }
10766 
10767     /**
10768      * Returns whether the view should be treated as a focusable unit by screen reader
10769      * accessibility tools.
10770      * @see #setScreenReaderFocusable(boolean)
10771      *
10772      * @return Whether the view should be treated as a focusable unit by screen reader.
10773      */
10774     public boolean isScreenReaderFocusable() {
10775         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
10776     }
10777 
10778     /**
10779      * When screen readers (one type of accessibility tool) decide what should be read to the
10780      * user, they typically look for input focusable ({@link #isFocusable()}) parents of
10781      * non-focusable text items, and read those focusable parents and their non-focusable children
10782      * as a unit. In some situations, this behavior is desirable for views that should not take
10783      * input focus. Setting an item to be screen reader focusable requests that the view be
10784      * treated as a unit by screen readers without any effect on input focusability. The default
10785      * value of {@code false} lets screen readers use other signals, like focusable, to determine
10786      * how to group items.
10787      *
10788      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
10789      *                              accessibility tools.
10790      */
10791     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
10792         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
10793     }
10794 
10795     /**
10796      * Gets whether this view is a heading for accessibility purposes.
10797      *
10798      * @return {@code true} if the view is a heading, {@code false} otherwise.
10799      *
10800      * @attr ref android.R.styleable#View_accessibilityHeading
10801      */
10802     public boolean isAccessibilityHeading() {
10803         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
10804     }
10805 
10806     /**
10807      * Set if view is a heading for a section of content for accessibility purposes.
10808      *
10809      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
10810      *
10811      * @attr ref android.R.styleable#View_accessibilityHeading
10812      */
10813     public void setAccessibilityHeading(boolean isHeading) {
10814         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
10815     }
10816 
10817     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
10818         int pflags3 = mPrivateFlags3;
10819         if (newValue) {
10820             pflags3 |= mask;
10821         } else {
10822             pflags3 &= ~mask;
10823         }
10824 
10825         if (pflags3 != mPrivateFlags3) {
10826             mPrivateFlags3 = pflags3;
10827             notifyViewAccessibilityStateChangedIfNeeded(
10828                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10829         }
10830     }
10831 
10832     /**
10833      * Find the nearest view in the specified direction that can take focus.
10834      * This does not actually give focus to that view.
10835      *
10836      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10837      *
10838      * @return The nearest focusable in the specified direction, or null if none
10839      *         can be found.
10840      */
10841     public View focusSearch(@FocusRealDirection int direction) {
10842         if (mParent != null) {
10843             return mParent.focusSearch(this, direction);
10844         } else {
10845             return null;
10846         }
10847     }
10848 
10849     /**
10850      * Returns whether this View is a root of a keyboard navigation cluster.
10851      *
10852      * @return True if this view is a root of a cluster, or false otherwise.
10853      * @attr ref android.R.styleable#View_keyboardNavigationCluster
10854      */
10855     @ViewDebug.ExportedProperty(category = "focus")
10856     public final boolean isKeyboardNavigationCluster() {
10857         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
10858     }
10859 
10860     /**
10861      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
10862      * will be ignored.
10863      *
10864      * @return the keyboard navigation cluster that this view is in (can be this view)
10865      *         or {@code null} if not in one
10866      */
10867     View findKeyboardNavigationCluster() {
10868         if (mParent instanceof View) {
10869             View cluster = ((View) mParent).findKeyboardNavigationCluster();
10870             if (cluster != null) {
10871                 return cluster;
10872             } else if (isKeyboardNavigationCluster()) {
10873                 return this;
10874             }
10875         }
10876         return null;
10877     }
10878 
10879     /**
10880      * Set whether this view is a root of a keyboard navigation cluster.
10881      *
10882      * @param isCluster If true, this view is a root of a cluster.
10883      *
10884      * @attr ref android.R.styleable#View_keyboardNavigationCluster
10885      */
10886     public void setKeyboardNavigationCluster(boolean isCluster) {
10887         if (isCluster) {
10888             mPrivateFlags3 |= PFLAG3_CLUSTER;
10889         } else {
10890             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
10891         }
10892     }
10893 
10894     /**
10895      * Sets this View as the one which receives focus the next time cluster navigation jumps
10896      * to the cluster containing this View. This does NOT change focus even if the cluster
10897      * containing this view is current.
10898      *
10899      * @hide
10900      */
10901     @TestApi
10902     public final void setFocusedInCluster() {
10903         setFocusedInCluster(findKeyboardNavigationCluster());
10904     }
10905 
10906     private void setFocusedInCluster(View cluster) {
10907         if (this instanceof ViewGroup) {
10908             ((ViewGroup) this).mFocusedInCluster = null;
10909         }
10910         if (cluster == this) {
10911             return;
10912         }
10913         ViewParent parent = mParent;
10914         View child = this;
10915         while (parent instanceof ViewGroup) {
10916             ((ViewGroup) parent).mFocusedInCluster = child;
10917             if (parent == cluster) {
10918                 break;
10919             }
10920             child = (View) parent;
10921             parent = parent.getParent();
10922         }
10923     }
10924 
10925     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
10926         if (oldFocus != null) {
10927             View oldCluster = oldFocus.findKeyboardNavigationCluster();
10928             View cluster = findKeyboardNavigationCluster();
10929             if (oldCluster != cluster) {
10930                 // Going from one cluster to another, so save last-focused.
10931                 // This covers cluster jumps because they are always FOCUS_DOWN
10932                 oldFocus.setFocusedInCluster(oldCluster);
10933                 if (!(oldFocus.mParent instanceof ViewGroup)) {
10934                     return;
10935                 }
10936                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
10937                     // This is a result of ordered navigation so consider navigation through
10938                     // the previous cluster "complete" and clear its last-focused memory.
10939                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10940                 } else if (oldFocus instanceof ViewGroup
10941                         && ((ViewGroup) oldFocus).getDescendantFocusability()
10942                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
10943                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
10944                     // This means oldFocus is not focusable since it obviously has a focusable
10945                     // child (this). Don't restore focus to it in the future.
10946                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10947                 }
10948             }
10949         }
10950     }
10951 
10952     /**
10953      * Returns whether this View should receive focus when the focus is restored for the view
10954      * hierarchy containing this view.
10955      * <p>
10956      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10957      * window or serves as a target of cluster navigation.
10958      *
10959      * @see #restoreDefaultFocus()
10960      *
10961      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
10962      * @attr ref android.R.styleable#View_focusedByDefault
10963      */
10964     @ViewDebug.ExportedProperty(category = "focus")
10965     public final boolean isFocusedByDefault() {
10966         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
10967     }
10968 
10969     /**
10970      * Sets whether this View should receive focus when the focus is restored for the view
10971      * hierarchy containing this view.
10972      * <p>
10973      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10974      * window or serves as a target of cluster navigation.
10975      *
10976      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
10977      *                           {@code false} otherwise.
10978      *
10979      * @see #restoreDefaultFocus()
10980      *
10981      * @attr ref android.R.styleable#View_focusedByDefault
10982      */
10983     public void setFocusedByDefault(boolean isFocusedByDefault) {
10984         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
10985             return;
10986         }
10987 
10988         if (isFocusedByDefault) {
10989             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
10990         } else {
10991             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
10992         }
10993 
10994         if (mParent instanceof ViewGroup) {
10995             if (isFocusedByDefault) {
10996                 ((ViewGroup) mParent).setDefaultFocus(this);
10997             } else {
10998                 ((ViewGroup) mParent).clearDefaultFocus(this);
10999             }
11000         }
11001     }
11002 
11003     /**
11004      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
11005      *
11006      * @return {@code true} if this view has default focus, {@code false} otherwise
11007      */
11008     boolean hasDefaultFocus() {
11009         return isFocusedByDefault();
11010     }
11011 
11012     /**
11013      * Find the nearest keyboard navigation cluster in the specified direction.
11014      * This does not actually give focus to that cluster.
11015      *
11016      * @param currentCluster The starting point of the search. Null means the current cluster is not
11017      *                       found yet
11018      * @param direction Direction to look
11019      *
11020      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
11021      *         can be found
11022      */
11023     public View keyboardNavigationClusterSearch(View currentCluster,
11024             @FocusDirection int direction) {
11025         if (isKeyboardNavigationCluster()) {
11026             currentCluster = this;
11027         }
11028         if (isRootNamespace()) {
11029             // Root namespace means we should consider ourselves the top of the
11030             // tree for group searching; otherwise we could be group searching
11031             // into other tabs.  see LocalActivityManager and TabHost for more info.
11032             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
11033                     this, currentCluster, direction);
11034         } else if (mParent != null) {
11035             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
11036         }
11037         return null;
11038     }
11039 
11040     /**
11041      * This method is the last chance for the focused view and its ancestors to
11042      * respond to an arrow key. This is called when the focused view did not
11043      * consume the key internally, nor could the view system find a new view in
11044      * the requested direction to give focus to.
11045      *
11046      * @param focused The currently focused view.
11047      * @param direction The direction focus wants to move. One of FOCUS_UP,
11048      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
11049      * @return True if the this view consumed this unhandled move.
11050      */
11051     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
11052         return false;
11053     }
11054 
11055     /**
11056      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
11057      * have {@link android.R.attr#state_focused} defined in its background.
11058      *
11059      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
11060      *                                      highlight, {@code false} otherwise.
11061      *
11062      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
11063      */
11064     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
11065         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
11066     }
11067 
11068     /**
11069 
11070     /**
11071      * Returns whether this View should use a default focus highlight when it gets focused but
11072      * doesn't have {@link android.R.attr#state_focused} defined in its background.
11073      *
11074      * @return True if this View should use a default focus highlight.
11075      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
11076      */
11077     @ViewDebug.ExportedProperty(category = "focus")
11078     public final boolean getDefaultFocusHighlightEnabled() {
11079         return mDefaultFocusHighlightEnabled;
11080     }
11081 
11082     /**
11083      * If a user manually specified the next view id for a particular direction,
11084      * use the root to look up the view.
11085      * @param root The root view of the hierarchy containing this view.
11086      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
11087      * or FOCUS_BACKWARD.
11088      * @return The user specified next view, or null if there is none.
11089      */
11090     View findUserSetNextFocus(View root, @FocusDirection int direction) {
11091         switch (direction) {
11092             case FOCUS_LEFT:
11093                 if (mNextFocusLeftId == View.NO_ID) return null;
11094                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
11095             case FOCUS_RIGHT:
11096                 if (mNextFocusRightId == View.NO_ID) return null;
11097                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
11098             case FOCUS_UP:
11099                 if (mNextFocusUpId == View.NO_ID) return null;
11100                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
11101             case FOCUS_DOWN:
11102                 if (mNextFocusDownId == View.NO_ID) return null;
11103                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
11104             case FOCUS_FORWARD:
11105                 if (mNextFocusForwardId == View.NO_ID) return null;
11106                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
11107             case FOCUS_BACKWARD: {
11108                 if (mID == View.NO_ID) return null;
11109                 final int id = mID;
11110                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
11111                     @Override
11112                     public boolean test(View t) {
11113                         return t.mNextFocusForwardId == id;
11114                     }
11115                 });
11116             }
11117         }
11118         return null;
11119     }
11120 
11121     /**
11122      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
11123      * use the root to look up the view.
11124      *
11125      * @param root the root view of the hierarchy containing this view
11126      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
11127      * @return the user-specified next cluster, or {@code null} if there is none
11128      */
11129     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
11130         switch (direction) {
11131             case FOCUS_FORWARD:
11132                 if (mNextClusterForwardId == View.NO_ID) return null;
11133                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
11134             case FOCUS_BACKWARD: {
11135                 if (mID == View.NO_ID) return null;
11136                 final int id = mID;
11137                 return root.findViewByPredicateInsideOut(this,
11138                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
11139             }
11140         }
11141         return null;
11142     }
11143 
11144     private View findViewInsideOutShouldExist(View root, int id) {
11145         if (mMatchIdPredicate == null) {
11146             mMatchIdPredicate = new MatchIdPredicate();
11147         }
11148         mMatchIdPredicate.mId = id;
11149         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
11150         if (result == null) {
11151             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
11152         }
11153         return result;
11154     }
11155 
11156     /**
11157      * Find and return all focusable views that are descendants of this view,
11158      * possibly including this view if it is focusable itself.
11159      *
11160      * @param direction The direction of the focus
11161      * @return A list of focusable views
11162      */
11163     public ArrayList<View> getFocusables(@FocusDirection int direction) {
11164         ArrayList<View> result = new ArrayList<View>(24);
11165         addFocusables(result, direction);
11166         return result;
11167     }
11168 
11169     /**
11170      * Add any focusable views that are descendants of this view (possibly
11171      * including this view if it is focusable itself) to views.  If we are in touch mode,
11172      * only add views that are also focusable in touch mode.
11173      *
11174      * @param views Focusable views found so far
11175      * @param direction The direction of the focus
11176      */
11177     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
11178         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
11179     }
11180 
11181     /**
11182      * Adds any focusable views that are descendants of this view (possibly
11183      * including this view if it is focusable itself) to views. This method
11184      * adds all focusable views regardless if we are in touch mode or
11185      * only views focusable in touch mode if we are in touch mode or
11186      * only views that can take accessibility focus if accessibility is enabled
11187      * depending on the focusable mode parameter.
11188      *
11189      * @param views Focusable views found so far or null if all we are interested is
11190      *        the number of focusables.
11191      * @param direction The direction of the focus.
11192      * @param focusableMode The type of focusables to be added.
11193      *
11194      * @see #FOCUSABLES_ALL
11195      * @see #FOCUSABLES_TOUCH_MODE
11196      */
11197     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
11198             @FocusableMode int focusableMode) {
11199         if (views == null) {
11200             return;
11201         }
11202         if (!canTakeFocus()) {
11203             return;
11204         }
11205         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
11206                 && !isFocusableInTouchMode()) {
11207             return;
11208         }
11209         views.add(this);
11210     }
11211 
11212     /**
11213      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
11214      * including this view if it is a cluster root itself) to views.
11215      *
11216      * @param views Keyboard navigation cluster roots found so far
11217      * @param direction Direction to look
11218      */
11219     public void addKeyboardNavigationClusters(
11220             @NonNull Collection<View> views,
11221             int direction) {
11222         if (!isKeyboardNavigationCluster()) {
11223             return;
11224         }
11225         if (!hasFocusable()) {
11226             return;
11227         }
11228         views.add(this);
11229     }
11230 
11231     /**
11232      * Finds the Views that contain given text. The containment is case insensitive.
11233      * The search is performed by either the text that the View renders or the content
11234      * description that describes the view for accessibility purposes and the view does
11235      * not render or both. Clients can specify how the search is to be performed via
11236      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
11237      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
11238      *
11239      * @param outViews The output list of matching Views.
11240      * @param searched The text to match against.
11241      *
11242      * @see #FIND_VIEWS_WITH_TEXT
11243      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
11244      * @see #setContentDescription(CharSequence)
11245      */
11246     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
11247             @FindViewFlags int flags) {
11248         if (getAccessibilityNodeProvider() != null) {
11249             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
11250                 outViews.add(this);
11251             }
11252         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
11253                 && (searched != null && searched.length() > 0)
11254                 && (mContentDescription != null && mContentDescription.length() > 0)) {
11255             String searchedLowerCase = searched.toString().toLowerCase();
11256             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
11257             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
11258                 outViews.add(this);
11259             }
11260         }
11261     }
11262 
11263     /**
11264      * Find and return all touchable views that are descendants of this view,
11265      * possibly including this view if it is touchable itself.
11266      *
11267      * @return A list of touchable views
11268      */
11269     public ArrayList<View> getTouchables() {
11270         ArrayList<View> result = new ArrayList<View>();
11271         addTouchables(result);
11272         return result;
11273     }
11274 
11275     /**
11276      * Add any touchable views that are descendants of this view (possibly
11277      * including this view if it is touchable itself) to views.
11278      *
11279      * @param views Touchable views found so far
11280      */
11281     public void addTouchables(ArrayList<View> views) {
11282         final int viewFlags = mViewFlags;
11283 
11284         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
11285                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
11286                 && (viewFlags & ENABLED_MASK) == ENABLED) {
11287             views.add(this);
11288         }
11289     }
11290 
11291     /**
11292      * Returns whether this View is accessibility focused.
11293      *
11294      * @return True if this View is accessibility focused.
11295      */
11296     public boolean isAccessibilityFocused() {
11297         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
11298     }
11299 
11300     /**
11301      * Call this to try to give accessibility focus to this view.
11302      *
11303      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
11304      * returns false or the view is no visible or the view already has accessibility
11305      * focus.
11306      *
11307      * See also {@link #focusSearch(int)}, which is what you call to say that you
11308      * have focus, and you want your parent to look for the next one.
11309      *
11310      * @return Whether this view actually took accessibility focus.
11311      *
11312      * @hide
11313      */
11314     public boolean requestAccessibilityFocus() {
11315         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
11316         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
11317             return false;
11318         }
11319         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
11320             return false;
11321         }
11322         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
11323             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
11324             ViewRootImpl viewRootImpl = getViewRootImpl();
11325             if (viewRootImpl != null) {
11326                 viewRootImpl.setAccessibilityFocus(this, null);
11327             }
11328             invalidate();
11329             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
11330             return true;
11331         }
11332         return false;
11333     }
11334 
11335     /**
11336      * Call this to try to clear accessibility focus of this view.
11337      *
11338      * See also {@link #focusSearch(int)}, which is what you call to say that you
11339      * have focus, and you want your parent to look for the next one.
11340      *
11341      * @hide
11342      */
11343     public void clearAccessibilityFocus() {
11344         clearAccessibilityFocusNoCallbacks(0);
11345 
11346         // Clear the global reference of accessibility focus if this view or
11347         // any of its descendants had accessibility focus. This will NOT send
11348         // an event or update internal state if focus is cleared from a
11349         // descendant view, which may leave views in inconsistent states.
11350         final ViewRootImpl viewRootImpl = getViewRootImpl();
11351         if (viewRootImpl != null) {
11352             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
11353             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
11354                 viewRootImpl.setAccessibilityFocus(null, null);
11355             }
11356         }
11357     }
11358 
11359     private void sendAccessibilityHoverEvent(int eventType) {
11360         // Since we are not delivering to a client accessibility events from not
11361         // important views (unless the clinet request that) we need to fire the
11362         // event from the deepest view exposed to the client. As a consequence if
11363         // the user crosses a not exposed view the client will see enter and exit
11364         // of the exposed predecessor followed by and enter and exit of that same
11365         // predecessor when entering and exiting the not exposed descendant. This
11366         // is fine since the client has a clear idea which view is hovered at the
11367         // price of a couple more events being sent. This is a simple and
11368         // working solution.
11369         View source = this;
11370         while (true) {
11371             if (source.includeForAccessibility()) {
11372                 source.sendAccessibilityEvent(eventType);
11373                 return;
11374             }
11375             ViewParent parent = source.getParent();
11376             if (parent instanceof View) {
11377                 source = (View) parent;
11378             } else {
11379                 return;
11380             }
11381         }
11382     }
11383 
11384     /**
11385      * Clears accessibility focus without calling any callback methods
11386      * normally invoked in {@link #clearAccessibilityFocus()}. This method
11387      * is used separately from that one for clearing accessibility focus when
11388      * giving this focus to another view.
11389      *
11390      * @param action The action, if any, that led to focus being cleared. Set to
11391      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
11392      * the window.
11393      */
11394     void clearAccessibilityFocusNoCallbacks(int action) {
11395         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
11396             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
11397             invalidate();
11398             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11399                 AccessibilityEvent event = AccessibilityEvent.obtain(
11400                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
11401                 event.setAction(action);
11402                 if (mAccessibilityDelegate != null) {
11403                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
11404                 } else {
11405                     sendAccessibilityEventUnchecked(event);
11406                 }
11407             }
11408         }
11409     }
11410 
11411     /**
11412      * Call this to try to give focus to a specific view or to one of its
11413      * descendants.
11414      *
11415      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
11416      * false), or if it can't be focused due to other conditions (not focusable in touch mode
11417      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
11418      * enabled, or has no size).
11419      *
11420      * See also {@link #focusSearch(int)}, which is what you call to say that you
11421      * have focus, and you want your parent to look for the next one.
11422      *
11423      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
11424      * {@link #FOCUS_DOWN} and <code>null</code>.
11425      *
11426      * @return Whether this view or one of its descendants actually took focus.
11427      */
11428     public final boolean requestFocus() {
11429         return requestFocus(View.FOCUS_DOWN);
11430     }
11431 
11432     /**
11433      * This will request focus for whichever View was last focused within this
11434      * cluster before a focus-jump out of it.
11435      *
11436      * @hide
11437      */
11438     @TestApi
11439     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
11440         // Prioritize focusableByDefault over algorithmic focus selection.
11441         if (restoreDefaultFocus()) {
11442             return true;
11443         }
11444         return requestFocus(direction);
11445     }
11446 
11447     /**
11448      * This will request focus for whichever View not in a cluster was last focused before a
11449      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
11450      * the "first" focusable view it finds.
11451      *
11452      * @hide
11453      */
11454     @TestApi
11455     public boolean restoreFocusNotInCluster() {
11456         return requestFocus(View.FOCUS_DOWN);
11457     }
11458 
11459     /**
11460      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
11461      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
11462      *
11463      * @return Whether this view or one of its descendants actually took focus
11464      */
11465     public boolean restoreDefaultFocus() {
11466         return requestFocus(View.FOCUS_DOWN);
11467     }
11468 
11469     /**
11470      * Call this to try to give focus to a specific view or to one of its
11471      * descendants and give it a hint about what direction focus is heading.
11472      *
11473      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
11474      * false), or if it is focusable and it is not focusable in touch mode
11475      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
11476      *
11477      * See also {@link #focusSearch(int)}, which is what you call to say that you
11478      * have focus, and you want your parent to look for the next one.
11479      *
11480      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
11481      * <code>null</code> set for the previously focused rectangle.
11482      *
11483      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
11484      * @return Whether this view or one of its descendants actually took focus.
11485      */
11486     public final boolean requestFocus(int direction) {
11487         return requestFocus(direction, null);
11488     }
11489 
11490     /**
11491      * Call this to try to give focus to a specific view or to one of its descendants
11492      * and give it hints about the direction and a specific rectangle that the focus
11493      * is coming from.  The rectangle can help give larger views a finer grained hint
11494      * about where focus is coming from, and therefore, where to show selection, or
11495      * forward focus change internally.
11496      *
11497      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
11498      * false), or if it is focusable and it is not focusable in touch mode
11499      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
11500      *
11501      * A View will not take focus if it is not visible.
11502      *
11503      * A View will not take focus if one of its parents has
11504      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
11505      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
11506      *
11507      * See also {@link #focusSearch(int)}, which is what you call to say that you
11508      * have focus, and you want your parent to look for the next one.
11509      *
11510      * You may wish to override this method if your custom {@link View} has an internal
11511      * {@link View} that it wishes to forward the request to.
11512      *
11513      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
11514      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
11515      *        to give a finer grained hint about where focus is coming from.  May be null
11516      *        if there is no hint.
11517      * @return Whether this view or one of its descendants actually took focus.
11518      */
11519     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
11520         return requestFocusNoSearch(direction, previouslyFocusedRect);
11521     }
11522 
11523     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
11524         // need to be focusable
11525         if (!canTakeFocus()) {
11526             return false;
11527         }
11528 
11529         // need to be focusable in touch mode if in touch mode
11530         if (isInTouchMode() &&
11531             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
11532                return false;
11533         }
11534 
11535         // need to not have any parents blocking us
11536         if (hasAncestorThatBlocksDescendantFocus()) {
11537             return false;
11538         }
11539 
11540         if (!isLayoutValid()) {
11541             mPrivateFlags |= PFLAG_WANTS_FOCUS;
11542         } else {
11543             clearParentsWantFocus();
11544         }
11545 
11546         handleFocusGainInternal(direction, previouslyFocusedRect);
11547         return true;
11548     }
11549 
11550     void clearParentsWantFocus() {
11551         if (mParent instanceof View) {
11552             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
11553             ((View) mParent).clearParentsWantFocus();
11554         }
11555     }
11556 
11557     /**
11558      * Call this to try to give focus to a specific view or to one of its descendants. This is a
11559      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
11560      * touch mode to request focus when they are touched.
11561      *
11562      * @return Whether this view or one of its descendants actually took focus.
11563      *
11564      * @see #isInTouchMode()
11565      *
11566      */
11567     public final boolean requestFocusFromTouch() {
11568         // Leave touch mode if we need to
11569         if (isInTouchMode()) {
11570             ViewRootImpl viewRoot = getViewRootImpl();
11571             if (viewRoot != null) {
11572                 viewRoot.ensureTouchMode(false);
11573             }
11574         }
11575         return requestFocus(View.FOCUS_DOWN);
11576     }
11577 
11578     /**
11579      * @return Whether any ancestor of this view blocks descendant focus.
11580      */
11581     private boolean hasAncestorThatBlocksDescendantFocus() {
11582         final boolean focusableInTouchMode = isFocusableInTouchMode();
11583         ViewParent ancestor = mParent;
11584         while (ancestor instanceof ViewGroup) {
11585             final ViewGroup vgAncestor = (ViewGroup) ancestor;
11586             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
11587                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
11588                 return true;
11589             } else {
11590                 ancestor = vgAncestor.getParent();
11591             }
11592         }
11593         return false;
11594     }
11595 
11596     /**
11597      * Gets the mode for determining whether this View is important for accessibility.
11598      * A view is important for accessibility if it fires accessibility events and if it
11599      * is reported to accessibility services that query the screen.
11600      *
11601      * @return The mode for determining whether a view is important for accessibility, one
11602      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
11603      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
11604      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
11605      *
11606      * @attr ref android.R.styleable#View_importantForAccessibility
11607      *
11608      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
11609      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
11610      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
11611      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
11612      */
11613     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
11614             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
11615             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
11616             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
11617             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
11618                     to = "noHideDescendants")
11619         })
11620     public int getImportantForAccessibility() {
11621         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
11622                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
11623     }
11624 
11625     /**
11626      * Sets the live region mode for this view. This indicates to accessibility
11627      * services whether they should automatically notify the user about changes
11628      * to the view's content description or text, or to the content descriptions
11629      * or text of the view's children (where applicable).
11630      * <p>
11631      * For example, in a login screen with a TextView that displays an "incorrect
11632      * password" notification, that view should be marked as a live region with
11633      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
11634      * <p>
11635      * To disable change notifications for this view, use
11636      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
11637      * mode for most views.
11638      * <p>
11639      * To indicate that the user should be notified of changes, use
11640      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
11641      * <p>
11642      * If the view's changes should interrupt ongoing speech and notify the user
11643      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
11644      *
11645      * @param mode The live region mode for this view, one of:
11646      *        <ul>
11647      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
11648      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
11649      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
11650      *        </ul>
11651      * @attr ref android.R.styleable#View_accessibilityLiveRegion
11652      */
11653     public void setAccessibilityLiveRegion(int mode) {
11654         if (mode != getAccessibilityLiveRegion()) {
11655             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
11656             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
11657                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
11658             notifyViewAccessibilityStateChangedIfNeeded(
11659                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11660         }
11661     }
11662 
11663     /**
11664      * Gets the live region mode for this View.
11665      *
11666      * @return The live region mode for the view.
11667      *
11668      * @attr ref android.R.styleable#View_accessibilityLiveRegion
11669      *
11670      * @see #setAccessibilityLiveRegion(int)
11671      */
11672     public int getAccessibilityLiveRegion() {
11673         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
11674                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
11675     }
11676 
11677     /**
11678      * Sets how to determine whether this view is important for accessibility
11679      * which is if it fires accessibility events and if it is reported to
11680      * accessibility services that query the screen.
11681      *
11682      * @param mode How to determine whether this view is important for accessibility.
11683      *
11684      * @attr ref android.R.styleable#View_importantForAccessibility
11685      *
11686      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
11687      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
11688      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
11689      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
11690      */
11691     public void setImportantForAccessibility(int mode) {
11692         final int oldMode = getImportantForAccessibility();
11693         if (mode != oldMode) {
11694             final boolean hideDescendants =
11695                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
11696 
11697             // If this node or its descendants are no longer important, try to
11698             // clear accessibility focus.
11699             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
11700                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
11701                 if (focusHost != null) {
11702                     focusHost.clearAccessibilityFocus();
11703                 }
11704             }
11705 
11706             // If we're moving between AUTO and another state, we might not need
11707             // to send a subtree changed notification. We'll store the computed
11708             // importance, since we'll need to check it later to make sure.
11709             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
11710                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
11711             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
11712             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
11713             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
11714                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
11715             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
11716                 notifySubtreeAccessibilityStateChangedIfNeeded();
11717             } else {
11718                 notifyViewAccessibilityStateChangedIfNeeded(
11719                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11720             }
11721         }
11722     }
11723 
11724     /**
11725      * Returns the view within this view's hierarchy that is hosting
11726      * accessibility focus.
11727      *
11728      * @param searchDescendants whether to search for focus in descendant views
11729      * @return the view hosting accessibility focus, or {@code null}
11730      */
11731     private View findAccessibilityFocusHost(boolean searchDescendants) {
11732         if (isAccessibilityFocusedViewOrHost()) {
11733             return this;
11734         }
11735 
11736         if (searchDescendants) {
11737             final ViewRootImpl viewRoot = getViewRootImpl();
11738             if (viewRoot != null) {
11739                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
11740                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
11741                     return focusHost;
11742                 }
11743             }
11744         }
11745 
11746         return null;
11747     }
11748 
11749     /**
11750      * Computes whether this view should be exposed for accessibility. In
11751      * general, views that are interactive or provide information are exposed
11752      * while views that serve only as containers are hidden.
11753      * <p>
11754      * If an ancestor of this view has importance
11755      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
11756      * returns <code>false</code>.
11757      * <p>
11758      * Otherwise, the value is computed according to the view's
11759      * {@link #getImportantForAccessibility()} value:
11760      * <ol>
11761      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
11762      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
11763      * </code>
11764      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
11765      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
11766      * view satisfies any of the following:
11767      * <ul>
11768      * <li>Is actionable, e.g. {@link #isClickable()},
11769      * {@link #isLongClickable()}, or {@link #isFocusable()}
11770      * <li>Has an {@link AccessibilityDelegate}
11771      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
11772      * {@link OnKeyListener}, etc.
11773      * <li>Is an accessibility live region, e.g.
11774      * {@link #getAccessibilityLiveRegion()} is not
11775      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
11776      * </ul>
11777      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
11778      * </ol>
11779      *
11780      * @return Whether the view is exposed for accessibility.
11781      * @see #setImportantForAccessibility(int)
11782      * @see #getImportantForAccessibility()
11783      */
11784     public boolean isImportantForAccessibility() {
11785         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
11786                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
11787         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
11788                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11789             return false;
11790         }
11791 
11792         // Check parent mode to ensure we're not hidden.
11793         ViewParent parent = mParent;
11794         while (parent instanceof View) {
11795             if (((View) parent).getImportantForAccessibility()
11796                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11797                 return false;
11798             }
11799             parent = parent.getParent();
11800         }
11801 
11802         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
11803                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
11804                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
11805                 || isAccessibilityPane();
11806     }
11807 
11808     /**
11809      * Gets the parent for accessibility purposes. Note that the parent for
11810      * accessibility is not necessary the immediate parent. It is the first
11811      * predecessor that is important for accessibility.
11812      *
11813      * @return The parent for accessibility purposes.
11814      */
11815     public ViewParent getParentForAccessibility() {
11816         if (mParent instanceof View) {
11817             View parentView = (View) mParent;
11818             if (parentView.includeForAccessibility()) {
11819                 return mParent;
11820             } else {
11821                 return mParent.getParentForAccessibility();
11822             }
11823         }
11824         return null;
11825     }
11826 
11827     /** @hide */
11828     View getSelfOrParentImportantForA11y() {
11829         if (isImportantForAccessibility()) return this;
11830         ViewParent parent = getParentForAccessibility();
11831         if (parent instanceof View) return (View) parent;
11832         return null;
11833     }
11834 
11835     /**
11836      * Adds the children of this View relevant for accessibility to the given list
11837      * as output. Since some Views are not important for accessibility the added
11838      * child views are not necessarily direct children of this view, rather they are
11839      * the first level of descendants important for accessibility.
11840      *
11841      * @param outChildren The output list that will receive children for accessibility.
11842      */
11843     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
11844 
11845     }
11846 
11847     /**
11848      * Whether to regard this view for accessibility. A view is regarded for
11849      * accessibility if it is important for accessibility or the querying
11850      * accessibility service has explicitly requested that view not
11851      * important for accessibility are regarded.
11852      *
11853      * @return Whether to regard the view for accessibility.
11854      *
11855      * @hide
11856      */
11857     public boolean includeForAccessibility() {
11858         if (mAttachInfo != null) {
11859             return (mAttachInfo.mAccessibilityFetchFlags
11860                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
11861                     || isImportantForAccessibility();
11862         }
11863         return false;
11864     }
11865 
11866     /**
11867      * Returns whether the View is considered actionable from
11868      * accessibility perspective. Such view are important for
11869      * accessibility.
11870      *
11871      * @return True if the view is actionable for accessibility.
11872      *
11873      * @hide
11874      */
11875     public boolean isActionableForAccessibility() {
11876         return (isClickable() || isLongClickable() || isFocusable());
11877     }
11878 
11879     /**
11880      * Returns whether the View has registered callbacks which makes it
11881      * important for accessibility.
11882      *
11883      * @return True if the view is actionable for accessibility.
11884      */
11885     private boolean hasListenersForAccessibility() {
11886         ListenerInfo info = getListenerInfo();
11887         return mTouchDelegate != null || info.mOnKeyListener != null
11888                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
11889                 || info.mOnHoverListener != null || info.mOnDragListener != null;
11890     }
11891 
11892     /**
11893      * Notifies that the accessibility state of this view changed. The change
11894      * is local to this view and does not represent structural changes such
11895      * as children and parent. For example, the view became focusable. The
11896      * notification is at at most once every
11897      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11898      * to avoid unnecessary load to the system. Also once a view has a pending
11899      * notification this method is a NOP until the notification has been sent.
11900      *
11901      * @hide
11902      */
11903     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
11904         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11905             return;
11906         }
11907 
11908         // Changes to views with a pane title count as window state changes, as the pane title
11909         // marks them as significant parts of the UI.
11910         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
11911                 && isAccessibilityPane()) {
11912             // If the pane isn't visible, content changed events are sufficient unless we're
11913             // reporting that the view just disappeared
11914             if ((getVisibility() == VISIBLE)
11915                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
11916                 final AccessibilityEvent event = AccessibilityEvent.obtain();
11917                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
11918                 event.setContentChangeTypes(changeType);
11919                 event.setSource(this);
11920                 onPopulateAccessibilityEvent(event);
11921                 if (mParent != null) {
11922                     try {
11923                         mParent.requestSendAccessibilityEvent(this, event);
11924                     } catch (AbstractMethodError e) {
11925                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
11926                                 + " does not fully implement ViewParent", e);
11927                     }
11928                 }
11929                 return;
11930             }
11931         }
11932 
11933         // If this is a live region, we should send a subtree change event
11934         // from this view immediately. Otherwise, we can let it propagate up.
11935         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
11936             final AccessibilityEvent event = AccessibilityEvent.obtain();
11937             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
11938             event.setContentChangeTypes(changeType);
11939             sendAccessibilityEventUnchecked(event);
11940         } else if (mParent != null) {
11941             try {
11942                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
11943             } catch (AbstractMethodError e) {
11944                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11945                         " does not fully implement ViewParent", e);
11946             }
11947         }
11948     }
11949 
11950     /**
11951      * Notifies that the accessibility state of this view changed. The change
11952      * is *not* local to this view and does represent structural changes such
11953      * as children and parent. For example, the view size changed. The
11954      * notification is at at most once every
11955      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11956      * to avoid unnecessary load to the system. Also once a view has a pending
11957      * notification this method is a NOP until the notification has been sent.
11958      *
11959      * @hide
11960      */
11961     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
11962         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11963             return;
11964         }
11965 
11966         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
11967             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11968             if (mParent != null) {
11969                 try {
11970                     mParent.notifySubtreeAccessibilityStateChanged(
11971                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
11972                 } catch (AbstractMethodError e) {
11973                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11974                             " does not fully implement ViewParent", e);
11975                 }
11976             }
11977         }
11978     }
11979 
11980     /**
11981      * Change the visibility of the View without triggering any other changes. This is
11982      * important for transitions, where visibility changes should not adjust focus or
11983      * trigger a new layout. This is only used when the visibility has already been changed
11984      * and we need a transient value during an animation. When the animation completes,
11985      * the original visibility value is always restored.
11986      *
11987      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11988      * @hide
11989      */
11990     public void setTransitionVisibility(@Visibility int visibility) {
11991         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
11992     }
11993 
11994     /**
11995      * Reset the flag indicating the accessibility state of the subtree rooted
11996      * at this view changed.
11997      */
11998     void resetSubtreeAccessibilityStateChanged() {
11999         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
12000     }
12001 
12002     /**
12003      * Report an accessibility action to this view's parents for delegated processing.
12004      *
12005      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
12006      * call this method to delegate an accessibility action to a supporting parent. If the parent
12007      * returns true from its
12008      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
12009      * method this method will return true to signify that the action was consumed.</p>
12010      *
12011      * <p>This method is useful for implementing nested scrolling child views. If
12012      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
12013      * a custom view implementation may invoke this method to allow a parent to consume the
12014      * scroll first. If this method returns true the custom view should skip its own scrolling
12015      * behavior.</p>
12016      *
12017      * @param action Accessibility action to delegate
12018      * @param arguments Optional action arguments
12019      * @return true if the action was consumed by a parent
12020      */
12021     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
12022         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
12023             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
12024                 return true;
12025             }
12026         }
12027         return false;
12028     }
12029 
12030     /**
12031      * Performs the specified accessibility action on the view. For
12032      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
12033      * <p>
12034      * If an {@link AccessibilityDelegate} has been specified via calling
12035      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
12036      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
12037      * is responsible for handling this call.
12038      * </p>
12039      *
12040      * <p>The default implementation will delegate
12041      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
12042      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
12043      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
12044      *
12045      * @param action The action to perform.
12046      * @param arguments Optional action arguments.
12047      * @return Whether the action was performed.
12048      */
12049     public boolean performAccessibilityAction(int action, Bundle arguments) {
12050       if (mAccessibilityDelegate != null) {
12051           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
12052       } else {
12053           return performAccessibilityActionInternal(action, arguments);
12054       }
12055     }
12056 
12057    /**
12058     * @see #performAccessibilityAction(int, Bundle)
12059     *
12060     * Note: Called from the default {@link AccessibilityDelegate}.
12061     *
12062     * @hide
12063     */
12064     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
12065         if (isNestedScrollingEnabled()
12066                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
12067                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
12068                 || action == R.id.accessibilityActionScrollUp
12069                 || action == R.id.accessibilityActionScrollLeft
12070                 || action == R.id.accessibilityActionScrollDown
12071                 || action == R.id.accessibilityActionScrollRight)) {
12072             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
12073                 return true;
12074             }
12075         }
12076 
12077         switch (action) {
12078             case AccessibilityNodeInfo.ACTION_CLICK: {
12079                 if (isClickable()) {
12080                     performClickInternal();
12081                     return true;
12082                 }
12083             } break;
12084             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
12085                 if (isLongClickable()) {
12086                     performLongClick();
12087                     return true;
12088                 }
12089             } break;
12090             case AccessibilityNodeInfo.ACTION_FOCUS: {
12091                 if (!hasFocus()) {
12092                     // Get out of touch mode since accessibility
12093                     // wants to move focus around.
12094                     getViewRootImpl().ensureTouchMode(false);
12095                     return requestFocus();
12096                 }
12097             } break;
12098             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
12099                 if (hasFocus()) {
12100                     clearFocus();
12101                     return !isFocused();
12102                 }
12103             } break;
12104             case AccessibilityNodeInfo.ACTION_SELECT: {
12105                 if (!isSelected()) {
12106                     setSelected(true);
12107                     return isSelected();
12108                 }
12109             } break;
12110             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
12111                 if (isSelected()) {
12112                     setSelected(false);
12113                     return !isSelected();
12114                 }
12115             } break;
12116             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
12117                 if (!isAccessibilityFocused()) {
12118                     return requestAccessibilityFocus();
12119                 }
12120             } break;
12121             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
12122                 if (isAccessibilityFocused()) {
12123                     clearAccessibilityFocus();
12124                     return true;
12125                 }
12126             } break;
12127             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
12128                 if (arguments != null) {
12129                     final int granularity = arguments.getInt(
12130                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
12131                     final boolean extendSelection = arguments.getBoolean(
12132                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
12133                     return traverseAtGranularity(granularity, true, extendSelection);
12134                 }
12135             } break;
12136             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
12137                 if (arguments != null) {
12138                     final int granularity = arguments.getInt(
12139                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
12140                     final boolean extendSelection = arguments.getBoolean(
12141                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
12142                     return traverseAtGranularity(granularity, false, extendSelection);
12143                 }
12144             } break;
12145             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
12146                 CharSequence text = getIterableTextForAccessibility();
12147                 if (text == null) {
12148                     return false;
12149                 }
12150                 final int start = (arguments != null) ? arguments.getInt(
12151                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
12152                 final int end = (arguments != null) ? arguments.getInt(
12153                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
12154                 // Only cursor position can be specified (selection length == 0)
12155                 if ((getAccessibilitySelectionStart() != start
12156                         || getAccessibilitySelectionEnd() != end)
12157                         && (start == end)) {
12158                     setAccessibilitySelection(start, end);
12159                     notifyViewAccessibilityStateChangedIfNeeded(
12160                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12161                     return true;
12162                 }
12163             } break;
12164             case R.id.accessibilityActionShowOnScreen: {
12165                 if (mAttachInfo != null) {
12166                     final Rect r = mAttachInfo.mTmpInvalRect;
12167                     getDrawingRect(r);
12168                     return requestRectangleOnScreen(r, true);
12169                 }
12170             } break;
12171             case R.id.accessibilityActionContextClick: {
12172                 if (isContextClickable()) {
12173                     performContextClick();
12174                     return true;
12175                 }
12176             } break;
12177             case R.id.accessibilityActionShowTooltip: {
12178                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
12179                     // Tooltip already showing
12180                     return false;
12181                 }
12182                 return showLongClickTooltip(0, 0);
12183             }
12184             case R.id.accessibilityActionHideTooltip: {
12185                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
12186                     // No tooltip showing
12187                     return false;
12188                 }
12189                 hideTooltip();
12190                 return true;
12191             }
12192         }
12193         return false;
12194     }
12195 
12196     private boolean traverseAtGranularity(int granularity, boolean forward,
12197             boolean extendSelection) {
12198         CharSequence text = getIterableTextForAccessibility();
12199         if (text == null || text.length() == 0) {
12200             return false;
12201         }
12202         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
12203         if (iterator == null) {
12204             return false;
12205         }
12206         int current = getAccessibilitySelectionEnd();
12207         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
12208             current = forward ? 0 : text.length();
12209         }
12210         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
12211         if (range == null) {
12212             return false;
12213         }
12214         final int segmentStart = range[0];
12215         final int segmentEnd = range[1];
12216         int selectionStart;
12217         int selectionEnd;
12218         if (extendSelection && isAccessibilitySelectionExtendable()) {
12219             selectionStart = getAccessibilitySelectionStart();
12220             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
12221                 selectionStart = forward ? segmentStart : segmentEnd;
12222             }
12223             selectionEnd = forward ? segmentEnd : segmentStart;
12224         } else {
12225             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
12226         }
12227         setAccessibilitySelection(selectionStart, selectionEnd);
12228         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
12229                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
12230         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
12231         return true;
12232     }
12233 
12234     /**
12235      * Gets the text reported for accessibility purposes.
12236      *
12237      * @return The accessibility text.
12238      *
12239      * @hide
12240      */
12241     public CharSequence getIterableTextForAccessibility() {
12242         return getContentDescription();
12243     }
12244 
12245     /**
12246      * Gets whether accessibility selection can be extended.
12247      *
12248      * @return If selection is extensible.
12249      *
12250      * @hide
12251      */
12252     public boolean isAccessibilitySelectionExtendable() {
12253         return false;
12254     }
12255 
12256     /**
12257      * @hide
12258      */
12259     public int getAccessibilitySelectionStart() {
12260         return mAccessibilityCursorPosition;
12261     }
12262 
12263     /**
12264      * @hide
12265      */
12266     public int getAccessibilitySelectionEnd() {
12267         return getAccessibilitySelectionStart();
12268     }
12269 
12270     /**
12271      * @hide
12272      */
12273     public void setAccessibilitySelection(int start, int end) {
12274         if (start ==  end && end == mAccessibilityCursorPosition) {
12275             return;
12276         }
12277         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
12278             mAccessibilityCursorPosition = start;
12279         } else {
12280             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
12281         }
12282         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
12283     }
12284 
12285     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
12286             int fromIndex, int toIndex) {
12287         if (mParent == null) {
12288             return;
12289         }
12290         AccessibilityEvent event = AccessibilityEvent.obtain(
12291                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
12292         onInitializeAccessibilityEvent(event);
12293         onPopulateAccessibilityEvent(event);
12294         event.setFromIndex(fromIndex);
12295         event.setToIndex(toIndex);
12296         event.setAction(action);
12297         event.setMovementGranularity(granularity);
12298         mParent.requestSendAccessibilityEvent(this, event);
12299     }
12300 
12301     /**
12302      * @hide
12303      */
12304     public TextSegmentIterator getIteratorForGranularity(int granularity) {
12305         switch (granularity) {
12306             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
12307                 CharSequence text = getIterableTextForAccessibility();
12308                 if (text != null && text.length() > 0) {
12309                     CharacterTextSegmentIterator iterator =
12310                         CharacterTextSegmentIterator.getInstance(
12311                                 mContext.getResources().getConfiguration().locale);
12312                     iterator.initialize(text.toString());
12313                     return iterator;
12314                 }
12315             } break;
12316             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
12317                 CharSequence text = getIterableTextForAccessibility();
12318                 if (text != null && text.length() > 0) {
12319                     WordTextSegmentIterator iterator =
12320                         WordTextSegmentIterator.getInstance(
12321                                 mContext.getResources().getConfiguration().locale);
12322                     iterator.initialize(text.toString());
12323                     return iterator;
12324                 }
12325             } break;
12326             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
12327                 CharSequence text = getIterableTextForAccessibility();
12328                 if (text != null && text.length() > 0) {
12329                     ParagraphTextSegmentIterator iterator =
12330                         ParagraphTextSegmentIterator.getInstance();
12331                     iterator.initialize(text.toString());
12332                     return iterator;
12333                 }
12334             } break;
12335         }
12336         return null;
12337     }
12338 
12339     /**
12340      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
12341      * and {@link #onFinishTemporaryDetach()}.
12342      *
12343      * <p>This method always returns {@code true} when called directly or indirectly from
12344      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
12345      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
12346      * <ul>
12347      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
12348      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
12349      * </ul>
12350      * </p>
12351      *
12352      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
12353      * and {@link #onFinishTemporaryDetach()}.
12354      */
isTemporarilyDetached()12355     public final boolean isTemporarilyDetached() {
12356         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
12357     }
12358 
12359     /**
12360      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
12361      * a container View.
12362      */
12363     @CallSuper
dispatchStartTemporaryDetach()12364     public void dispatchStartTemporaryDetach() {
12365         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
12366         notifyEnterOrExitForAutoFillIfNeeded(false);
12367         onStartTemporaryDetach();
12368     }
12369 
12370     /**
12371      * This is called when a container is going to temporarily detach a child, with
12372      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
12373      * It will either be followed by {@link #onFinishTemporaryDetach()} or
12374      * {@link #onDetachedFromWindow()} when the container is done.
12375      */
onStartTemporaryDetach()12376     public void onStartTemporaryDetach() {
12377         removeUnsetPressCallback();
12378         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
12379     }
12380 
12381     /**
12382      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
12383      * a container View.
12384      */
12385     @CallSuper
dispatchFinishTemporaryDetach()12386     public void dispatchFinishTemporaryDetach() {
12387         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
12388         onFinishTemporaryDetach();
12389         if (hasWindowFocus() && hasFocus()) {
12390             InputMethodManager.getInstance().focusIn(this);
12391         }
12392         notifyEnterOrExitForAutoFillIfNeeded(true);
12393     }
12394 
12395     /**
12396      * Called after {@link #onStartTemporaryDetach} when the container is done
12397      * changing the view.
12398      */
onFinishTemporaryDetach()12399     public void onFinishTemporaryDetach() {
12400     }
12401 
12402     /**
12403      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
12404      * for this view's window.  Returns null if the view is not currently attached
12405      * to the window.  Normally you will not need to use this directly, but
12406      * just use the standard high-level event callbacks like
12407      * {@link #onKeyDown(int, KeyEvent)}.
12408      */
getKeyDispatcherState()12409     public KeyEvent.DispatcherState getKeyDispatcherState() {
12410         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
12411     }
12412 
12413     /**
12414      * Dispatch a key event before it is processed by any input method
12415      * associated with the view hierarchy.  This can be used to intercept
12416      * key events in special situations before the IME consumes them; a
12417      * typical example would be handling the BACK key to update the application's
12418      * UI instead of allowing the IME to see it and close itself.
12419      *
12420      * @param event The key event to be dispatched.
12421      * @return True if the event was handled, false otherwise.
12422      */
dispatchKeyEventPreIme(KeyEvent event)12423     public boolean dispatchKeyEventPreIme(KeyEvent event) {
12424         return onKeyPreIme(event.getKeyCode(), event);
12425     }
12426 
12427     /**
12428      * Dispatch a key event to the next view on the focus path. This path runs
12429      * from the top of the view tree down to the currently focused view. If this
12430      * view has focus, it will dispatch to itself. Otherwise it will dispatch
12431      * the next node down the focus path. This method also fires any key
12432      * listeners.
12433      *
12434      * @param event The key event to be dispatched.
12435      * @return True if the event was handled, false otherwise.
12436      */
dispatchKeyEvent(KeyEvent event)12437     public boolean dispatchKeyEvent(KeyEvent event) {
12438         if (mInputEventConsistencyVerifier != null) {
12439             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
12440         }
12441 
12442         // Give any attached key listener a first crack at the event.
12443         //noinspection SimplifiableIfStatement
12444         ListenerInfo li = mListenerInfo;
12445         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
12446                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
12447             return true;
12448         }
12449 
12450         if (event.dispatch(this, mAttachInfo != null
12451                 ? mAttachInfo.mKeyDispatchState : null, this)) {
12452             return true;
12453         }
12454 
12455         if (mInputEventConsistencyVerifier != null) {
12456             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
12457         }
12458         return false;
12459     }
12460 
12461     /**
12462      * Dispatches a key shortcut event.
12463      *
12464      * @param event The key event to be dispatched.
12465      * @return True if the event was handled by the view, false otherwise.
12466      */
dispatchKeyShortcutEvent(KeyEvent event)12467     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
12468         return onKeyShortcut(event.getKeyCode(), event);
12469     }
12470 
12471     /**
12472      * Pass the touch screen motion event down to the target view, or this
12473      * view if it is the target.
12474      *
12475      * @param event The motion event to be dispatched.
12476      * @return True if the event was handled by the view, false otherwise.
12477      */
dispatchTouchEvent(MotionEvent event)12478     public boolean dispatchTouchEvent(MotionEvent event) {
12479         // If the event should be handled by accessibility focus first.
12480         if (event.isTargetAccessibilityFocus()) {
12481             // We don't have focus or no virtual descendant has it, do not handle the event.
12482             if (!isAccessibilityFocusedViewOrHost()) {
12483                 return false;
12484             }
12485             // We have focus and got the event, then use normal event dispatch.
12486             event.setTargetAccessibilityFocus(false);
12487         }
12488 
12489         boolean result = false;
12490 
12491         if (mInputEventConsistencyVerifier != null) {
12492             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
12493         }
12494 
12495         final int actionMasked = event.getActionMasked();
12496         if (actionMasked == MotionEvent.ACTION_DOWN) {
12497             // Defensive cleanup for new gesture
12498             stopNestedScroll();
12499         }
12500 
12501         if (onFilterTouchEventForSecurity(event)) {
12502             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
12503                 result = true;
12504             }
12505             //noinspection SimplifiableIfStatement
12506             ListenerInfo li = mListenerInfo;
12507             if (li != null && li.mOnTouchListener != null
12508                     && (mViewFlags & ENABLED_MASK) == ENABLED
12509                     && li.mOnTouchListener.onTouch(this, event)) {
12510                 result = true;
12511             }
12512 
12513             if (!result && onTouchEvent(event)) {
12514                 result = true;
12515             }
12516         }
12517 
12518         if (!result && mInputEventConsistencyVerifier != null) {
12519             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
12520         }
12521 
12522         // Clean up after nested scrolls if this is the end of a gesture;
12523         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
12524         // of the gesture.
12525         if (actionMasked == MotionEvent.ACTION_UP ||
12526                 actionMasked == MotionEvent.ACTION_CANCEL ||
12527                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
12528             stopNestedScroll();
12529         }
12530 
12531         return result;
12532     }
12533 
isAccessibilityFocusedViewOrHost()12534     boolean isAccessibilityFocusedViewOrHost() {
12535         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
12536                 .getAccessibilityFocusedHost() == this);
12537     }
12538 
12539     /**
12540      * Filter the touch event to apply security policies.
12541      *
12542      * @param event The motion event to be filtered.
12543      * @return True if the event should be dispatched, false if the event should be dropped.
12544      *
12545      * @see #getFilterTouchesWhenObscured
12546      */
onFilterTouchEventForSecurity(MotionEvent event)12547     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
12548         //noinspection RedundantIfStatement
12549         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
12550                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
12551             // Window is obscured, drop this touch.
12552             return false;
12553         }
12554         return true;
12555     }
12556 
12557     /**
12558      * Pass a trackball motion event down to the focused view.
12559      *
12560      * @param event The motion event to be dispatched.
12561      * @return True if the event was handled by the view, false otherwise.
12562      */
dispatchTrackballEvent(MotionEvent event)12563     public boolean dispatchTrackballEvent(MotionEvent event) {
12564         if (mInputEventConsistencyVerifier != null) {
12565             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
12566         }
12567 
12568         return onTrackballEvent(event);
12569     }
12570 
12571     /**
12572      * Pass a captured pointer event down to the focused view.
12573      *
12574      * @param event The motion event to be dispatched.
12575      * @return True if the event was handled by the view, false otherwise.
12576      */
dispatchCapturedPointerEvent(MotionEvent event)12577     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
12578         if (!hasPointerCapture()) {
12579             return false;
12580         }
12581         //noinspection SimplifiableIfStatement
12582         ListenerInfo li = mListenerInfo;
12583         if (li != null && li.mOnCapturedPointerListener != null
12584                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
12585             return true;
12586         }
12587         return onCapturedPointerEvent(event);
12588     }
12589 
12590     /**
12591      * Dispatch a generic motion event.
12592      * <p>
12593      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12594      * are delivered to the view under the pointer.  All other generic motion events are
12595      * delivered to the focused view.  Hover events are handled specially and are delivered
12596      * to {@link #onHoverEvent(MotionEvent)}.
12597      * </p>
12598      *
12599      * @param event The motion event to be dispatched.
12600      * @return True if the event was handled by the view, false otherwise.
12601      */
dispatchGenericMotionEvent(MotionEvent event)12602     public boolean dispatchGenericMotionEvent(MotionEvent event) {
12603         if (mInputEventConsistencyVerifier != null) {
12604             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
12605         }
12606 
12607         final int source = event.getSource();
12608         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
12609             final int action = event.getAction();
12610             if (action == MotionEvent.ACTION_HOVER_ENTER
12611                     || action == MotionEvent.ACTION_HOVER_MOVE
12612                     || action == MotionEvent.ACTION_HOVER_EXIT) {
12613                 if (dispatchHoverEvent(event)) {
12614                     return true;
12615                 }
12616             } else if (dispatchGenericPointerEvent(event)) {
12617                 return true;
12618             }
12619         } else if (dispatchGenericFocusedEvent(event)) {
12620             return true;
12621         }
12622 
12623         if (dispatchGenericMotionEventInternal(event)) {
12624             return true;
12625         }
12626 
12627         if (mInputEventConsistencyVerifier != null) {
12628             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
12629         }
12630         return false;
12631     }
12632 
dispatchGenericMotionEventInternal(MotionEvent event)12633     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
12634         //noinspection SimplifiableIfStatement
12635         ListenerInfo li = mListenerInfo;
12636         if (li != null && li.mOnGenericMotionListener != null
12637                 && (mViewFlags & ENABLED_MASK) == ENABLED
12638                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
12639             return true;
12640         }
12641 
12642         if (onGenericMotionEvent(event)) {
12643             return true;
12644         }
12645 
12646         final int actionButton = event.getActionButton();
12647         switch (event.getActionMasked()) {
12648             case MotionEvent.ACTION_BUTTON_PRESS:
12649                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
12650                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
12651                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
12652                     if (performContextClick(event.getX(), event.getY())) {
12653                         mInContextButtonPress = true;
12654                         setPressed(true, event.getX(), event.getY());
12655                         removeTapCallback();
12656                         removeLongPressCallback();
12657                         return true;
12658                     }
12659                 }
12660                 break;
12661 
12662             case MotionEvent.ACTION_BUTTON_RELEASE:
12663                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
12664                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
12665                     mInContextButtonPress = false;
12666                     mIgnoreNextUpEvent = true;
12667                 }
12668                 break;
12669         }
12670 
12671         if (mInputEventConsistencyVerifier != null) {
12672             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
12673         }
12674         return false;
12675     }
12676 
12677     /**
12678      * Dispatch a hover event.
12679      * <p>
12680      * Do not call this method directly.
12681      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
12682      * </p>
12683      *
12684      * @param event The motion event to be dispatched.
12685      * @return True if the event was handled by the view, false otherwise.
12686      */
dispatchHoverEvent(MotionEvent event)12687     protected boolean dispatchHoverEvent(MotionEvent event) {
12688         ListenerInfo li = mListenerInfo;
12689         //noinspection SimplifiableIfStatement
12690         if (li != null && li.mOnHoverListener != null
12691                 && (mViewFlags & ENABLED_MASK) == ENABLED
12692                 && li.mOnHoverListener.onHover(this, event)) {
12693             return true;
12694         }
12695 
12696         return onHoverEvent(event);
12697     }
12698 
12699     /**
12700      * Returns true if the view has a child to which it has recently sent
12701      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
12702      * it does not have a hovered child, then it must be the innermost hovered view.
12703      * @hide
12704      */
hasHoveredChild()12705     protected boolean hasHoveredChild() {
12706         return false;
12707     }
12708 
12709     /**
12710      * Dispatch a generic motion event to the view under the first pointer.
12711      * <p>
12712      * Do not call this method directly.
12713      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
12714      * </p>
12715      *
12716      * @param event The motion event to be dispatched.
12717      * @return True if the event was handled by the view, false otherwise.
12718      */
dispatchGenericPointerEvent(MotionEvent event)12719     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
12720         return false;
12721     }
12722 
12723     /**
12724      * Dispatch a generic motion event to the currently focused view.
12725      * <p>
12726      * Do not call this method directly.
12727      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
12728      * </p>
12729      *
12730      * @param event The motion event to be dispatched.
12731      * @return True if the event was handled by the view, false otherwise.
12732      */
dispatchGenericFocusedEvent(MotionEvent event)12733     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
12734         return false;
12735     }
12736 
12737     /**
12738      * Dispatch a pointer event.
12739      * <p>
12740      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
12741      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
12742      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
12743      * and should not be expected to handle other pointing device features.
12744      * </p>
12745      *
12746      * @param event The motion event to be dispatched.
12747      * @return True if the event was handled by the view, false otherwise.
12748      * @hide
12749      */
dispatchPointerEvent(MotionEvent event)12750     public final boolean dispatchPointerEvent(MotionEvent event) {
12751         if (event.isTouchEvent()) {
12752             return dispatchTouchEvent(event);
12753         } else {
12754             return dispatchGenericMotionEvent(event);
12755         }
12756     }
12757 
12758     /**
12759      * Called when the window containing this view gains or loses window focus.
12760      * ViewGroups should override to route to their children.
12761      *
12762      * @param hasFocus True if the window containing this view now has focus,
12763      *        false otherwise.
12764      */
dispatchWindowFocusChanged(boolean hasFocus)12765     public void dispatchWindowFocusChanged(boolean hasFocus) {
12766         onWindowFocusChanged(hasFocus);
12767     }
12768 
12769     /**
12770      * Called when the window containing this view gains or loses focus.  Note
12771      * that this is separate from view focus: to receive key events, both
12772      * your view and its window must have focus.  If a window is displayed
12773      * on top of yours that takes input focus, then your own window will lose
12774      * focus but the view focus will remain unchanged.
12775      *
12776      * @param hasWindowFocus True if the window containing this view now has
12777      *        focus, false otherwise.
12778      */
onWindowFocusChanged(boolean hasWindowFocus)12779     public void onWindowFocusChanged(boolean hasWindowFocus) {
12780         InputMethodManager imm = InputMethodManager.peekInstance();
12781         if (!hasWindowFocus) {
12782             if (isPressed()) {
12783                 setPressed(false);
12784             }
12785             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12786             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12787                 imm.focusOut(this);
12788             }
12789             removeLongPressCallback();
12790             removeTapCallback();
12791             onFocusLost();
12792         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12793             imm.focusIn(this);
12794         }
12795 
12796         refreshDrawableState();
12797     }
12798 
12799     /**
12800      * Returns true if this view is in a window that currently has window focus.
12801      * Note that this is not the same as the view itself having focus.
12802      *
12803      * @return True if this view is in a window that currently has window focus.
12804      */
hasWindowFocus()12805     public boolean hasWindowFocus() {
12806         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
12807     }
12808 
12809     /**
12810      * Dispatch a view visibility change down the view hierarchy.
12811      * ViewGroups should override to route to their children.
12812      * @param changedView The view whose visibility changed. Could be 'this' or
12813      * an ancestor view.
12814      * @param visibility The new visibility of changedView: {@link #VISIBLE},
12815      * {@link #INVISIBLE} or {@link #GONE}.
12816      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)12817     protected void dispatchVisibilityChanged(@NonNull View changedView,
12818             @Visibility int visibility) {
12819         onVisibilityChanged(changedView, visibility);
12820     }
12821 
12822     /**
12823      * Called when the visibility of the view or an ancestor of the view has
12824      * changed.
12825      *
12826      * @param changedView The view whose visibility changed. May be
12827      *                    {@code this} or an ancestor view.
12828      * @param visibility The new visibility, one of {@link #VISIBLE},
12829      *                   {@link #INVISIBLE} or {@link #GONE}.
12830      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)12831     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
12832     }
12833 
12834     /**
12835      * Dispatch a hint about whether this view is displayed. For instance, when
12836      * a View moves out of the screen, it might receives a display hint indicating
12837      * the view is not displayed. Applications should not <em>rely</em> on this hint
12838      * as there is no guarantee that they will receive one.
12839      *
12840      * @param hint A hint about whether or not this view is displayed:
12841      * {@link #VISIBLE} or {@link #INVISIBLE}.
12842      */
dispatchDisplayHint(@isibility int hint)12843     public void dispatchDisplayHint(@Visibility int hint) {
12844         onDisplayHint(hint);
12845     }
12846 
12847     /**
12848      * Gives this view a hint about whether is displayed or not. For instance, when
12849      * a View moves out of the screen, it might receives a display hint indicating
12850      * the view is not displayed. Applications should not <em>rely</em> on this hint
12851      * as there is no guarantee that they will receive one.
12852      *
12853      * @param hint A hint about whether or not this view is displayed:
12854      * {@link #VISIBLE} or {@link #INVISIBLE}.
12855      */
onDisplayHint(@isibility int hint)12856     protected void onDisplayHint(@Visibility int hint) {
12857     }
12858 
12859     /**
12860      * Dispatch a window visibility change down the view hierarchy.
12861      * ViewGroups should override to route to their children.
12862      *
12863      * @param visibility The new visibility of the window.
12864      *
12865      * @see #onWindowVisibilityChanged(int)
12866      */
dispatchWindowVisibilityChanged(@isibility int visibility)12867     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
12868         onWindowVisibilityChanged(visibility);
12869     }
12870 
12871     /**
12872      * Called when the window containing has change its visibility
12873      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
12874      * that this tells you whether or not your window is being made visible
12875      * to the window manager; this does <em>not</em> tell you whether or not
12876      * your window is obscured by other windows on the screen, even if it
12877      * is itself visible.
12878      *
12879      * @param visibility The new visibility of the window.
12880      */
onWindowVisibilityChanged(@isibility int visibility)12881     protected void onWindowVisibilityChanged(@Visibility int visibility) {
12882         if (visibility == VISIBLE) {
12883             initialAwakenScrollBars();
12884         }
12885     }
12886 
12887     /**
12888      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
12889      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
12890      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
12891      *
12892      * @param isVisible true if this view's visibility to the user is uninterrupted by its
12893      *                  ancestors or by window visibility
12894      * @return true if this view is visible to the user, not counting clipping or overlapping
12895      */
dispatchVisibilityAggregated(boolean isVisible)12896     boolean dispatchVisibilityAggregated(boolean isVisible) {
12897         final boolean thisVisible = getVisibility() == VISIBLE;
12898         // If we're not visible but something is telling us we are, ignore it.
12899         if (thisVisible || !isVisible) {
12900             onVisibilityAggregated(isVisible);
12901         }
12902         return thisVisible && isVisible;
12903     }
12904 
12905     /**
12906      * Called when the user-visibility of this View is potentially affected by a change
12907      * to this view itself, an ancestor view or the window this view is attached to.
12908      *
12909      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
12910      *                  and this view's window is also visible
12911      */
12912     @CallSuper
onVisibilityAggregated(boolean isVisible)12913     public void onVisibilityAggregated(boolean isVisible) {
12914         // Update our internal visibility tracking so we can detect changes
12915         boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
12916         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
12917                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
12918         if (isVisible && mAttachInfo != null) {
12919             initialAwakenScrollBars();
12920         }
12921 
12922         final Drawable dr = mBackground;
12923         if (dr != null && isVisible != dr.isVisible()) {
12924             dr.setVisible(isVisible, false);
12925         }
12926         final Drawable hl = mDefaultFocusHighlight;
12927         if (hl != null && isVisible != hl.isVisible()) {
12928             hl.setVisible(isVisible, false);
12929         }
12930         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
12931         if (fg != null && isVisible != fg.isVisible()) {
12932             fg.setVisible(isVisible, false);
12933         }
12934 
12935         if (isAutofillable()) {
12936             AutofillManager afm = getAutofillManager();
12937 
12938             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
12939                 if (mVisibilityChangeForAutofillHandler != null) {
12940                     mVisibilityChangeForAutofillHandler.removeMessages(0);
12941                 }
12942 
12943                 // If the view is in the background but still part of the hierarchy this is called
12944                 // with isVisible=false. Hence visibility==false requires further checks
12945                 if (isVisible) {
12946                     afm.notifyViewVisibilityChanged(this, true);
12947                 } else {
12948                     if (mVisibilityChangeForAutofillHandler == null) {
12949                         mVisibilityChangeForAutofillHandler =
12950                                 new VisibilityChangeForAutofillHandler(afm, this);
12951                     }
12952                     // Let current operation (e.g. removal of the view from the hierarchy)
12953                     // finish before checking state
12954                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
12955                 }
12956             }
12957         }
12958         if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
12959             if (isVisible != oldVisible) {
12960                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
12961                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
12962                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
12963             }
12964         }
12965     }
12966 
12967     /**
12968      * Returns the current visibility of the window this view is attached to
12969      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
12970      *
12971      * @return Returns the current visibility of the view's window.
12972      */
12973     @Visibility
getWindowVisibility()12974     public int getWindowVisibility() {
12975         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
12976     }
12977 
12978     /**
12979      * Retrieve the overall visible display size in which the window this view is
12980      * attached to has been positioned in.  This takes into account screen
12981      * decorations above the window, for both cases where the window itself
12982      * is being position inside of them or the window is being placed under
12983      * then and covered insets are used for the window to position its content
12984      * inside.  In effect, this tells you the available area where content can
12985      * be placed and remain visible to users.
12986      *
12987      * <p>This function requires an IPC back to the window manager to retrieve
12988      * the requested information, so should not be used in performance critical
12989      * code like drawing.
12990      *
12991      * @param outRect Filled in with the visible display frame.  If the view
12992      * is not attached to a window, this is simply the raw display size.
12993      */
getWindowVisibleDisplayFrame(Rect outRect)12994     public void getWindowVisibleDisplayFrame(Rect outRect) {
12995         if (mAttachInfo != null) {
12996             try {
12997                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12998             } catch (RemoteException e) {
12999                 return;
13000             }
13001             // XXX This is really broken, and probably all needs to be done
13002             // in the window manager, and we need to know more about whether
13003             // we want the area behind or in front of the IME.
13004             final Rect insets = mAttachInfo.mVisibleInsets;
13005             outRect.left += insets.left;
13006             outRect.top += insets.top;
13007             outRect.right -= insets.right;
13008             outRect.bottom -= insets.bottom;
13009             return;
13010         }
13011         // The view is not attached to a display so we don't have a context.
13012         // Make a best guess about the display size.
13013         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
13014         d.getRectSize(outRect);
13015     }
13016 
13017     /**
13018      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
13019      * is currently in without any insets.
13020      *
13021      * @hide
13022      */
getWindowDisplayFrame(Rect outRect)13023     public void getWindowDisplayFrame(Rect outRect) {
13024         if (mAttachInfo != null) {
13025             try {
13026                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
13027             } catch (RemoteException e) {
13028                 return;
13029             }
13030             return;
13031         }
13032         // The view is not attached to a display so we don't have a context.
13033         // Make a best guess about the display size.
13034         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
13035         d.getRectSize(outRect);
13036     }
13037 
13038     /**
13039      * Dispatch a notification about a resource configuration change down
13040      * the view hierarchy.
13041      * ViewGroups should override to route to their children.
13042      *
13043      * @param newConfig The new resource configuration.
13044      *
13045      * @see #onConfigurationChanged(android.content.res.Configuration)
13046      */
dispatchConfigurationChanged(Configuration newConfig)13047     public void dispatchConfigurationChanged(Configuration newConfig) {
13048         onConfigurationChanged(newConfig);
13049     }
13050 
13051     /**
13052      * Called when the current configuration of the resources being used
13053      * by the application have changed.  You can use this to decide when
13054      * to reload resources that can changed based on orientation and other
13055      * configuration characteristics.  You only need to use this if you are
13056      * not relying on the normal {@link android.app.Activity} mechanism of
13057      * recreating the activity instance upon a configuration change.
13058      *
13059      * @param newConfig The new resource configuration.
13060      */
onConfigurationChanged(Configuration newConfig)13061     protected void onConfigurationChanged(Configuration newConfig) {
13062     }
13063 
13064     /**
13065      * Private function to aggregate all per-view attributes in to the view
13066      * root.
13067      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)13068     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
13069         performCollectViewAttributes(attachInfo, visibility);
13070     }
13071 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)13072     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
13073         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
13074             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
13075                 attachInfo.mKeepScreenOn = true;
13076             }
13077             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
13078             ListenerInfo li = mListenerInfo;
13079             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
13080                 attachInfo.mHasSystemUiListeners = true;
13081             }
13082         }
13083     }
13084 
needGlobalAttributesUpdate(boolean force)13085     void needGlobalAttributesUpdate(boolean force) {
13086         final AttachInfo ai = mAttachInfo;
13087         if (ai != null && !ai.mRecomputeGlobalAttributes) {
13088             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
13089                     || ai.mHasSystemUiListeners) {
13090                 ai.mRecomputeGlobalAttributes = true;
13091             }
13092         }
13093     }
13094 
13095     /**
13096      * Returns whether the device is currently in touch mode.  Touch mode is entered
13097      * once the user begins interacting with the device by touch, and affects various
13098      * things like whether focus is always visible to the user.
13099      *
13100      * @return Whether the device is in touch mode.
13101      */
13102     @ViewDebug.ExportedProperty
isInTouchMode()13103     public boolean isInTouchMode() {
13104         if (mAttachInfo != null) {
13105             return mAttachInfo.mInTouchMode;
13106         } else {
13107             return ViewRootImpl.isInTouchMode();
13108         }
13109     }
13110 
13111     /**
13112      * Returns the context the view is running in, through which it can
13113      * access the current theme, resources, etc.
13114      *
13115      * @return The view's Context.
13116      */
13117     @ViewDebug.CapturedViewProperty
getContext()13118     public final Context getContext() {
13119         return mContext;
13120     }
13121 
13122     /**
13123      * Handle a key event before it is processed by any input method
13124      * associated with the view hierarchy.  This can be used to intercept
13125      * key events in special situations before the IME consumes them; a
13126      * typical example would be handling the BACK key to update the application's
13127      * UI instead of allowing the IME to see it and close itself.
13128      *
13129      * @param keyCode The value in event.getKeyCode().
13130      * @param event Description of the key event.
13131      * @return If you handled the event, return true. If you want to allow the
13132      *         event to be handled by the next receiver, return false.
13133      */
onKeyPreIme(int keyCode, KeyEvent event)13134     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
13135         return false;
13136     }
13137 
13138     /**
13139      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
13140      * KeyEvent.Callback.onKeyDown()}: perform press of the view
13141      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
13142      * is released, if the view is enabled and clickable.
13143      * <p>
13144      * Key presses in software keyboards will generally NOT trigger this
13145      * listener, although some may elect to do so in some situations. Do not
13146      * rely on this to catch software key presses.
13147      *
13148      * @param keyCode a key code that represents the button pressed, from
13149      *                {@link android.view.KeyEvent}
13150      * @param event the KeyEvent object that defines the button action
13151      */
onKeyDown(int keyCode, KeyEvent event)13152     public boolean onKeyDown(int keyCode, KeyEvent event) {
13153         if (KeyEvent.isConfirmKey(keyCode)) {
13154             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
13155                 return true;
13156             }
13157 
13158             if (event.getRepeatCount() == 0) {
13159                 // Long clickable items don't necessarily have to be clickable.
13160                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
13161                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
13162                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
13163                     // For the purposes of menu anchoring and drawable hotspots,
13164                     // key events are considered to be at the center of the view.
13165                     final float x = getWidth() / 2f;
13166                     final float y = getHeight() / 2f;
13167                     if (clickable) {
13168                         setPressed(true, x, y);
13169                     }
13170                     checkForLongClick(0, x, y);
13171                     return true;
13172                 }
13173             }
13174         }
13175 
13176         return false;
13177     }
13178 
13179     /**
13180      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
13181      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
13182      * the event).
13183      * <p>Key presses in software keyboards will generally NOT trigger this listener,
13184      * although some may elect to do so in some situations. Do not rely on this to
13185      * catch software key presses.
13186      */
onKeyLongPress(int keyCode, KeyEvent event)13187     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
13188         return false;
13189     }
13190 
13191     /**
13192      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
13193      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
13194      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
13195      * or {@link KeyEvent#KEYCODE_SPACE} is released.
13196      * <p>Key presses in software keyboards will generally NOT trigger this listener,
13197      * although some may elect to do so in some situations. Do not rely on this to
13198      * catch software key presses.
13199      *
13200      * @param keyCode A key code that represents the button pressed, from
13201      *                {@link android.view.KeyEvent}.
13202      * @param event   The KeyEvent object that defines the button action.
13203      */
onKeyUp(int keyCode, KeyEvent event)13204     public boolean onKeyUp(int keyCode, KeyEvent event) {
13205         if (KeyEvent.isConfirmKey(keyCode)) {
13206             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
13207                 return true;
13208             }
13209             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
13210                 setPressed(false);
13211 
13212                 if (!mHasPerformedLongPress) {
13213                     // This is a tap, so remove the longpress check
13214                     removeLongPressCallback();
13215                     if (!event.isCanceled()) {
13216                         return performClickInternal();
13217                     }
13218                 }
13219             }
13220         }
13221         return false;
13222     }
13223 
13224     /**
13225      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
13226      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
13227      * the event).
13228      * <p>Key presses in software keyboards will generally NOT trigger this listener,
13229      * although some may elect to do so in some situations. Do not rely on this to
13230      * catch software key presses.
13231      *
13232      * @param keyCode     A key code that represents the button pressed, from
13233      *                    {@link android.view.KeyEvent}.
13234      * @param repeatCount The number of times the action was made.
13235      * @param event       The KeyEvent object that defines the button action.
13236      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)13237     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
13238         return false;
13239     }
13240 
13241     /**
13242      * Called on the focused view when a key shortcut event is not handled.
13243      * Override this method to implement local key shortcuts for the View.
13244      * Key shortcuts can also be implemented by setting the
13245      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
13246      *
13247      * @param keyCode The value in event.getKeyCode().
13248      * @param event Description of the key event.
13249      * @return If you handled the event, return true. If you want to allow the
13250      *         event to be handled by the next receiver, return false.
13251      */
onKeyShortcut(int keyCode, KeyEvent event)13252     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
13253         return false;
13254     }
13255 
13256     /**
13257      * Check whether the called view is a text editor, in which case it
13258      * would make sense to automatically display a soft input window for
13259      * it.  Subclasses should override this if they implement
13260      * {@link #onCreateInputConnection(EditorInfo)} to return true if
13261      * a call on that method would return a non-null InputConnection, and
13262      * they are really a first-class editor that the user would normally
13263      * start typing on when the go into a window containing your view.
13264      *
13265      * <p>The default implementation always returns false.  This does
13266      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
13267      * will not be called or the user can not otherwise perform edits on your
13268      * view; it is just a hint to the system that this is not the primary
13269      * purpose of this view.
13270      *
13271      * @return Returns true if this view is a text editor, else false.
13272      */
onCheckIsTextEditor()13273     public boolean onCheckIsTextEditor() {
13274         return false;
13275     }
13276 
13277     /**
13278      * Create a new InputConnection for an InputMethod to interact
13279      * with the view.  The default implementation returns null, since it doesn't
13280      * support input methods.  You can override this to implement such support.
13281      * This is only needed for views that take focus and text input.
13282      *
13283      * <p>When implementing this, you probably also want to implement
13284      * {@link #onCheckIsTextEditor()} to indicate you will return a
13285      * non-null InputConnection.</p>
13286      *
13287      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
13288      * object correctly and in its entirety, so that the connected IME can rely
13289      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
13290      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
13291      * must be filled in with the correct cursor position for IMEs to work correctly
13292      * with your application.</p>
13293      *
13294      * @param outAttrs Fill in with attribute information about the connection.
13295      */
onCreateInputConnection(EditorInfo outAttrs)13296     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
13297         return null;
13298     }
13299 
13300     /**
13301      * Called by the {@link android.view.inputmethod.InputMethodManager}
13302      * when a view who is not the current
13303      * input connection target is trying to make a call on the manager.  The
13304      * default implementation returns false; you can override this to return
13305      * true for certain views if you are performing InputConnection proxying
13306      * to them.
13307      * @param view The View that is making the InputMethodManager call.
13308      * @return Return true to allow the call, false to reject.
13309      */
checkInputConnectionProxy(View view)13310     public boolean checkInputConnectionProxy(View view) {
13311         return false;
13312     }
13313 
13314     /**
13315      * Show the context menu for this view. It is not safe to hold on to the
13316      * menu after returning from this method.
13317      *
13318      * You should normally not overload this method. Overload
13319      * {@link #onCreateContextMenu(ContextMenu)} or define an
13320      * {@link OnCreateContextMenuListener} to add items to the context menu.
13321      *
13322      * @param menu The context menu to populate
13323      */
createContextMenu(ContextMenu menu)13324     public void createContextMenu(ContextMenu menu) {
13325         ContextMenuInfo menuInfo = getContextMenuInfo();
13326 
13327         // Sets the current menu info so all items added to menu will have
13328         // my extra info set.
13329         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
13330 
13331         onCreateContextMenu(menu);
13332         ListenerInfo li = mListenerInfo;
13333         if (li != null && li.mOnCreateContextMenuListener != null) {
13334             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
13335         }
13336 
13337         // Clear the extra information so subsequent items that aren't mine don't
13338         // have my extra info.
13339         ((MenuBuilder)menu).setCurrentMenuInfo(null);
13340 
13341         if (mParent != null) {
13342             mParent.createContextMenu(menu);
13343         }
13344     }
13345 
13346     /**
13347      * Views should implement this if they have extra information to associate
13348      * with the context menu. The return result is supplied as a parameter to
13349      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
13350      * callback.
13351      *
13352      * @return Extra information about the item for which the context menu
13353      *         should be shown. This information will vary across different
13354      *         subclasses of View.
13355      */
getContextMenuInfo()13356     protected ContextMenuInfo getContextMenuInfo() {
13357         return null;
13358     }
13359 
13360     /**
13361      * Views should implement this if the view itself is going to add items to
13362      * the context menu.
13363      *
13364      * @param menu the context menu to populate
13365      */
onCreateContextMenu(ContextMenu menu)13366     protected void onCreateContextMenu(ContextMenu menu) {
13367     }
13368 
13369     /**
13370      * Implement this method to handle trackball motion events.  The
13371      * <em>relative</em> movement of the trackball since the last event
13372      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
13373      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
13374      * that a movement of 1 corresponds to the user pressing one DPAD key (so
13375      * they will often be fractional values, representing the more fine-grained
13376      * movement information available from a trackball).
13377      *
13378      * @param event The motion event.
13379      * @return True if the event was handled, false otherwise.
13380      */
onTrackballEvent(MotionEvent event)13381     public boolean onTrackballEvent(MotionEvent event) {
13382         return false;
13383     }
13384 
13385     /**
13386      * Implement this method to handle generic motion events.
13387      * <p>
13388      * Generic motion events describe joystick movements, mouse hovers, track pad
13389      * touches, scroll wheel movements and other input events.  The
13390      * {@link MotionEvent#getSource() source} of the motion event specifies
13391      * the class of input that was received.  Implementations of this method
13392      * must examine the bits in the source before processing the event.
13393      * The following code example shows how this is done.
13394      * </p><p>
13395      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
13396      * are delivered to the view under the pointer.  All other generic motion events are
13397      * delivered to the focused view.
13398      * </p>
13399      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
13400      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
13401      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
13402      *             // process the joystick movement...
13403      *             return true;
13404      *         }
13405      *     }
13406      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
13407      *         switch (event.getAction()) {
13408      *             case MotionEvent.ACTION_HOVER_MOVE:
13409      *                 // process the mouse hover movement...
13410      *                 return true;
13411      *             case MotionEvent.ACTION_SCROLL:
13412      *                 // process the scroll wheel movement...
13413      *                 return true;
13414      *         }
13415      *     }
13416      *     return super.onGenericMotionEvent(event);
13417      * }</pre>
13418      *
13419      * @param event The generic motion event being processed.
13420      * @return True if the event was handled, false otherwise.
13421      */
onGenericMotionEvent(MotionEvent event)13422     public boolean onGenericMotionEvent(MotionEvent event) {
13423         return false;
13424     }
13425 
13426     /**
13427      * Implement this method to handle hover events.
13428      * <p>
13429      * This method is called whenever a pointer is hovering into, over, or out of the
13430      * bounds of a view and the view is not currently being touched.
13431      * Hover events are represented as pointer events with action
13432      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
13433      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
13434      * </p>
13435      * <ul>
13436      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
13437      * when the pointer enters the bounds of the view.</li>
13438      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
13439      * when the pointer has already entered the bounds of the view and has moved.</li>
13440      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
13441      * when the pointer has exited the bounds of the view or when the pointer is
13442      * about to go down due to a button click, tap, or similar user action that
13443      * causes the view to be touched.</li>
13444      * </ul>
13445      * <p>
13446      * The view should implement this method to return true to indicate that it is
13447      * handling the hover event, such as by changing its drawable state.
13448      * </p><p>
13449      * The default implementation calls {@link #setHovered} to update the hovered state
13450      * of the view when a hover enter or hover exit event is received, if the view
13451      * is enabled and is clickable.  The default implementation also sends hover
13452      * accessibility events.
13453      * </p>
13454      *
13455      * @param event The motion event that describes the hover.
13456      * @return True if the view handled the hover event.
13457      *
13458      * @see #isHovered
13459      * @see #setHovered
13460      * @see #onHoverChanged
13461      */
onHoverEvent(MotionEvent event)13462     public boolean onHoverEvent(MotionEvent event) {
13463         // The root view may receive hover (or touch) events that are outside the bounds of
13464         // the window.  This code ensures that we only send accessibility events for
13465         // hovers that are actually within the bounds of the root view.
13466         final int action = event.getActionMasked();
13467         if (!mSendingHoverAccessibilityEvents) {
13468             if ((action == MotionEvent.ACTION_HOVER_ENTER
13469                     || action == MotionEvent.ACTION_HOVER_MOVE)
13470                     && !hasHoveredChild()
13471                     && pointInView(event.getX(), event.getY())) {
13472                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
13473                 mSendingHoverAccessibilityEvents = true;
13474             }
13475         } else {
13476             if (action == MotionEvent.ACTION_HOVER_EXIT
13477                     || (action == MotionEvent.ACTION_MOVE
13478                             && !pointInView(event.getX(), event.getY()))) {
13479                 mSendingHoverAccessibilityEvents = false;
13480                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
13481             }
13482         }
13483 
13484         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
13485                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
13486                 && isOnScrollbar(event.getX(), event.getY())) {
13487             awakenScrollBars();
13488         }
13489 
13490         // If we consider ourself hoverable, or if we we're already hovered,
13491         // handle changing state in response to ENTER and EXIT events.
13492         if (isHoverable() || isHovered()) {
13493             switch (action) {
13494                 case MotionEvent.ACTION_HOVER_ENTER:
13495                     setHovered(true);
13496                     break;
13497                 case MotionEvent.ACTION_HOVER_EXIT:
13498                     setHovered(false);
13499                     break;
13500             }
13501 
13502             // Dispatch the event to onGenericMotionEvent before returning true.
13503             // This is to provide compatibility with existing applications that
13504             // handled HOVER_MOVE events in onGenericMotionEvent and that would
13505             // break because of the new default handling for hoverable views
13506             // in onHoverEvent.
13507             // Note that onGenericMotionEvent will be called by default when
13508             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
13509             dispatchGenericMotionEventInternal(event);
13510             // The event was already handled by calling setHovered(), so always
13511             // return true.
13512             return true;
13513         }
13514 
13515         return false;
13516     }
13517 
13518     /**
13519      * Returns true if the view should handle {@link #onHoverEvent}
13520      * by calling {@link #setHovered} to change its hovered state.
13521      *
13522      * @return True if the view is hoverable.
13523      */
isHoverable()13524     private boolean isHoverable() {
13525         final int viewFlags = mViewFlags;
13526         if ((viewFlags & ENABLED_MASK) == DISABLED) {
13527             return false;
13528         }
13529 
13530         return (viewFlags & CLICKABLE) == CLICKABLE
13531                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
13532                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
13533     }
13534 
13535     /**
13536      * Returns true if the view is currently hovered.
13537      *
13538      * @return True if the view is currently hovered.
13539      *
13540      * @see #setHovered
13541      * @see #onHoverChanged
13542      */
13543     @ViewDebug.ExportedProperty
isHovered()13544     public boolean isHovered() {
13545         return (mPrivateFlags & PFLAG_HOVERED) != 0;
13546     }
13547 
13548     /**
13549      * Sets whether the view is currently hovered.
13550      * <p>
13551      * Calling this method also changes the drawable state of the view.  This
13552      * enables the view to react to hover by using different drawable resources
13553      * to change its appearance.
13554      * </p><p>
13555      * The {@link #onHoverChanged} method is called when the hovered state changes.
13556      * </p>
13557      *
13558      * @param hovered True if the view is hovered.
13559      *
13560      * @see #isHovered
13561      * @see #onHoverChanged
13562      */
setHovered(boolean hovered)13563     public void setHovered(boolean hovered) {
13564         if (hovered) {
13565             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
13566                 mPrivateFlags |= PFLAG_HOVERED;
13567                 refreshDrawableState();
13568                 onHoverChanged(true);
13569             }
13570         } else {
13571             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
13572                 mPrivateFlags &= ~PFLAG_HOVERED;
13573                 refreshDrawableState();
13574                 onHoverChanged(false);
13575             }
13576         }
13577     }
13578 
13579     /**
13580      * Implement this method to handle hover state changes.
13581      * <p>
13582      * This method is called whenever the hover state changes as a result of a
13583      * call to {@link #setHovered}.
13584      * </p>
13585      *
13586      * @param hovered The current hover state, as returned by {@link #isHovered}.
13587      *
13588      * @see #isHovered
13589      * @see #setHovered
13590      */
onHoverChanged(boolean hovered)13591     public void onHoverChanged(boolean hovered) {
13592     }
13593 
13594     /**
13595      * Handles scroll bar dragging by mouse input.
13596      *
13597      * @hide
13598      * @param event The motion event.
13599      *
13600      * @return true if the event was handled as a scroll bar dragging, false otherwise.
13601      */
handleScrollBarDragging(MotionEvent event)13602     protected boolean handleScrollBarDragging(MotionEvent event) {
13603         if (mScrollCache == null) {
13604             return false;
13605         }
13606         final float x = event.getX();
13607         final float y = event.getY();
13608         final int action = event.getAction();
13609         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
13610                 && action != MotionEvent.ACTION_DOWN)
13611                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
13612                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
13613             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
13614             return false;
13615         }
13616 
13617         switch (action) {
13618             case MotionEvent.ACTION_MOVE:
13619                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
13620                     return false;
13621                 }
13622                 if (mScrollCache.mScrollBarDraggingState
13623                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
13624                     final Rect bounds = mScrollCache.mScrollBarBounds;
13625                     getVerticalScrollBarBounds(bounds, null);
13626                     final int range = computeVerticalScrollRange();
13627                     final int offset = computeVerticalScrollOffset();
13628                     final int extent = computeVerticalScrollExtent();
13629 
13630                     final int thumbLength = ScrollBarUtils.getThumbLength(
13631                             bounds.height(), bounds.width(), extent, range);
13632                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
13633                             bounds.height(), thumbLength, extent, range, offset);
13634 
13635                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
13636                     final float maxThumbOffset = bounds.height() - thumbLength;
13637                     final float newThumbOffset =
13638                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
13639                     final int height = getHeight();
13640                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
13641                             && height > 0 && extent > 0) {
13642                         final int newY = Math.round((range - extent)
13643                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
13644                         if (newY != getScrollY()) {
13645                             mScrollCache.mScrollBarDraggingPos = y;
13646                             setScrollY(newY);
13647                         }
13648                     }
13649                     return true;
13650                 }
13651                 if (mScrollCache.mScrollBarDraggingState
13652                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
13653                     final Rect bounds = mScrollCache.mScrollBarBounds;
13654                     getHorizontalScrollBarBounds(bounds, null);
13655                     final int range = computeHorizontalScrollRange();
13656                     final int offset = computeHorizontalScrollOffset();
13657                     final int extent = computeHorizontalScrollExtent();
13658 
13659                     final int thumbLength = ScrollBarUtils.getThumbLength(
13660                             bounds.width(), bounds.height(), extent, range);
13661                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
13662                             bounds.width(), thumbLength, extent, range, offset);
13663 
13664                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
13665                     final float maxThumbOffset = bounds.width() - thumbLength;
13666                     final float newThumbOffset =
13667                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
13668                     final int width = getWidth();
13669                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
13670                             && width > 0 && extent > 0) {
13671                         final int newX = Math.round((range - extent)
13672                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
13673                         if (newX != getScrollX()) {
13674                             mScrollCache.mScrollBarDraggingPos = x;
13675                             setScrollX(newX);
13676                         }
13677                     }
13678                     return true;
13679                 }
13680             case MotionEvent.ACTION_DOWN:
13681                 if (mScrollCache.state == ScrollabilityCache.OFF) {
13682                     return false;
13683                 }
13684                 if (isOnVerticalScrollbarThumb(x, y)) {
13685                     mScrollCache.mScrollBarDraggingState =
13686                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
13687                     mScrollCache.mScrollBarDraggingPos = y;
13688                     return true;
13689                 }
13690                 if (isOnHorizontalScrollbarThumb(x, y)) {
13691                     mScrollCache.mScrollBarDraggingState =
13692                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
13693                     mScrollCache.mScrollBarDraggingPos = x;
13694                     return true;
13695                 }
13696         }
13697         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
13698         return false;
13699     }
13700 
13701     /**
13702      * Implement this method to handle touch screen motion events.
13703      * <p>
13704      * If this method is used to detect click actions, it is recommended that
13705      * the actions be performed by implementing and calling
13706      * {@link #performClick()}. This will ensure consistent system behavior,
13707      * including:
13708      * <ul>
13709      * <li>obeying click sound preferences
13710      * <li>dispatching OnClickListener calls
13711      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
13712      * accessibility features are enabled
13713      * </ul>
13714      *
13715      * @param event The motion event.
13716      * @return True if the event was handled, false otherwise.
13717      */
onTouchEvent(MotionEvent event)13718     public boolean onTouchEvent(MotionEvent event) {
13719         final float x = event.getX();
13720         final float y = event.getY();
13721         final int viewFlags = mViewFlags;
13722         final int action = event.getAction();
13723 
13724         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
13725                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
13726                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
13727 
13728         if ((viewFlags & ENABLED_MASK) == DISABLED) {
13729             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
13730                 setPressed(false);
13731             }
13732             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13733             // A disabled view that is clickable still consumes the touch
13734             // events, it just doesn't respond to them.
13735             return clickable;
13736         }
13737         if (mTouchDelegate != null) {
13738             if (mTouchDelegate.onTouchEvent(event)) {
13739                 return true;
13740             }
13741         }
13742 
13743         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
13744             switch (action) {
13745                 case MotionEvent.ACTION_UP:
13746                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13747                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
13748                         handleTooltipUp();
13749                     }
13750                     if (!clickable) {
13751                         removeTapCallback();
13752                         removeLongPressCallback();
13753                         mInContextButtonPress = false;
13754                         mHasPerformedLongPress = false;
13755                         mIgnoreNextUpEvent = false;
13756                         break;
13757                     }
13758                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
13759                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
13760                         // take focus if we don't have it already and we should in
13761                         // touch mode.
13762                         boolean focusTaken = false;
13763                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
13764                             focusTaken = requestFocus();
13765                         }
13766 
13767                         if (prepressed) {
13768                             // The button is being released before we actually
13769                             // showed it as pressed.  Make it show the pressed
13770                             // state now (before scheduling the click) to ensure
13771                             // the user sees it.
13772                             setPressed(true, x, y);
13773                         }
13774 
13775                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
13776                             // This is a tap, so remove the longpress check
13777                             removeLongPressCallback();
13778 
13779                             // Only perform take click actions if we were in the pressed state
13780                             if (!focusTaken) {
13781                                 // Use a Runnable and post this rather than calling
13782                                 // performClick directly. This lets other visual state
13783                                 // of the view update before click actions start.
13784                                 if (mPerformClick == null) {
13785                                     mPerformClick = new PerformClick();
13786                                 }
13787                                 if (!post(mPerformClick)) {
13788                                     performClickInternal();
13789                                 }
13790                             }
13791                         }
13792 
13793                         if (mUnsetPressedState == null) {
13794                             mUnsetPressedState = new UnsetPressedState();
13795                         }
13796 
13797                         if (prepressed) {
13798                             postDelayed(mUnsetPressedState,
13799                                     ViewConfiguration.getPressedStateDuration());
13800                         } else if (!post(mUnsetPressedState)) {
13801                             // If the post failed, unpress right now
13802                             mUnsetPressedState.run();
13803                         }
13804 
13805                         removeTapCallback();
13806                     }
13807                     mIgnoreNextUpEvent = false;
13808                     break;
13809 
13810                 case MotionEvent.ACTION_DOWN:
13811                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
13812                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
13813                     }
13814                     mHasPerformedLongPress = false;
13815 
13816                     if (!clickable) {
13817                         checkForLongClick(0, x, y);
13818                         break;
13819                     }
13820 
13821                     if (performButtonActionOnTouchDown(event)) {
13822                         break;
13823                     }
13824 
13825                     // Walk up the hierarchy to determine if we're inside a scrolling container.
13826                     boolean isInScrollingContainer = isInScrollingContainer();
13827 
13828                     // For views inside a scrolling container, delay the pressed feedback for
13829                     // a short period in case this is a scroll.
13830                     if (isInScrollingContainer) {
13831                         mPrivateFlags |= PFLAG_PREPRESSED;
13832                         if (mPendingCheckForTap == null) {
13833                             mPendingCheckForTap = new CheckForTap();
13834                         }
13835                         mPendingCheckForTap.x = event.getX();
13836                         mPendingCheckForTap.y = event.getY();
13837                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
13838                     } else {
13839                         // Not inside a scrolling container, so show the feedback right away
13840                         setPressed(true, x, y);
13841                         checkForLongClick(0, x, y);
13842                     }
13843                     break;
13844 
13845                 case MotionEvent.ACTION_CANCEL:
13846                     if (clickable) {
13847                         setPressed(false);
13848                     }
13849                     removeTapCallback();
13850                     removeLongPressCallback();
13851                     mInContextButtonPress = false;
13852                     mHasPerformedLongPress = false;
13853                     mIgnoreNextUpEvent = false;
13854                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13855                     break;
13856 
13857                 case MotionEvent.ACTION_MOVE:
13858                     if (clickable) {
13859                         drawableHotspotChanged(x, y);
13860                     }
13861 
13862                     // Be lenient about moving outside of buttons
13863                     if (!pointInView(x, y, mTouchSlop)) {
13864                         // Outside button
13865                         // Remove any future long press/tap checks
13866                         removeTapCallback();
13867                         removeLongPressCallback();
13868                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
13869                             setPressed(false);
13870                         }
13871                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13872                     }
13873                     break;
13874             }
13875 
13876             return true;
13877         }
13878 
13879         return false;
13880     }
13881 
13882     /**
13883      * @hide
13884      */
isInScrollingContainer()13885     public boolean isInScrollingContainer() {
13886         ViewParent p = getParent();
13887         while (p != null && p instanceof ViewGroup) {
13888             if (((ViewGroup) p).shouldDelayChildPressedState()) {
13889                 return true;
13890             }
13891             p = p.getParent();
13892         }
13893         return false;
13894     }
13895 
13896     /**
13897      * Remove the longpress detection timer.
13898      */
removeLongPressCallback()13899     private void removeLongPressCallback() {
13900         if (mPendingCheckForLongPress != null) {
13901             removeCallbacks(mPendingCheckForLongPress);
13902         }
13903     }
13904 
13905     /**
13906      * Remove the pending click action
13907      */
removePerformClickCallback()13908     private void removePerformClickCallback() {
13909         if (mPerformClick != null) {
13910             removeCallbacks(mPerformClick);
13911         }
13912     }
13913 
13914     /**
13915      * Remove the prepress detection timer.
13916      */
removeUnsetPressCallback()13917     private void removeUnsetPressCallback() {
13918         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
13919             setPressed(false);
13920             removeCallbacks(mUnsetPressedState);
13921         }
13922     }
13923 
13924     /**
13925      * Remove the tap detection timer.
13926      */
removeTapCallback()13927     private void removeTapCallback() {
13928         if (mPendingCheckForTap != null) {
13929             mPrivateFlags &= ~PFLAG_PREPRESSED;
13930             removeCallbacks(mPendingCheckForTap);
13931         }
13932     }
13933 
13934     /**
13935      * Cancels a pending long press.  Your subclass can use this if you
13936      * want the context menu to come up if the user presses and holds
13937      * at the same place, but you don't want it to come up if they press
13938      * and then move around enough to cause scrolling.
13939      */
cancelLongPress()13940     public void cancelLongPress() {
13941         removeLongPressCallback();
13942 
13943         /*
13944          * The prepressed state handled by the tap callback is a display
13945          * construct, but the tap callback will post a long press callback
13946          * less its own timeout. Remove it here.
13947          */
13948         removeTapCallback();
13949     }
13950 
13951     /**
13952      * Sets the TouchDelegate for this View.
13953      */
setTouchDelegate(TouchDelegate delegate)13954     public void setTouchDelegate(TouchDelegate delegate) {
13955         mTouchDelegate = delegate;
13956     }
13957 
13958     /**
13959      * Gets the TouchDelegate for this View.
13960      */
getTouchDelegate()13961     public TouchDelegate getTouchDelegate() {
13962         return mTouchDelegate;
13963     }
13964 
13965     /**
13966      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
13967      *
13968      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
13969      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
13970      * available. This method should only be called for touch events.
13971      *
13972      * <p class="note">This api is not intended for most applications. Buffered dispatch
13973      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
13974      * streams will not improve your input latency. Side effects include: increased latency,
13975      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
13976      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
13977      * you.</p>
13978      */
requestUnbufferedDispatch(MotionEvent event)13979     public final void requestUnbufferedDispatch(MotionEvent event) {
13980         final int action = event.getAction();
13981         if (mAttachInfo == null
13982                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
13983                 || !event.isTouchEvent()) {
13984             return;
13985         }
13986         mAttachInfo.mUnbufferedDispatchRequested = true;
13987     }
13988 
hasSize()13989     private boolean hasSize() {
13990         return (mBottom > mTop) && (mRight > mLeft);
13991     }
13992 
canTakeFocus()13993     private boolean canTakeFocus() {
13994         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
13995                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
13996                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
13997                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
13998     }
13999 
14000     /**
14001      * Set flags controlling behavior of this view.
14002      *
14003      * @param flags Constant indicating the value which should be set
14004      * @param mask Constant indicating the bit range that should be changed
14005      */
setFlags(int flags, int mask)14006     void setFlags(int flags, int mask) {
14007         final boolean accessibilityEnabled =
14008                 AccessibilityManager.getInstance(mContext).isEnabled();
14009         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
14010 
14011         int old = mViewFlags;
14012         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
14013 
14014         int changed = mViewFlags ^ old;
14015         if (changed == 0) {
14016             return;
14017         }
14018         int privateFlags = mPrivateFlags;
14019         boolean shouldNotifyFocusableAvailable = false;
14020 
14021         // If focusable is auto, update the FOCUSABLE bit.
14022         int focusableChangedByAuto = 0;
14023         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
14024                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
14025             // Heuristic only takes into account whether view is clickable.
14026             final int newFocus;
14027             if ((mViewFlags & CLICKABLE) != 0) {
14028                 newFocus = FOCUSABLE;
14029             } else {
14030                 newFocus = NOT_FOCUSABLE;
14031             }
14032             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
14033             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
14034             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
14035         }
14036 
14037         /* Check if the FOCUSABLE bit has changed */
14038         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
14039             if (((old & FOCUSABLE) == FOCUSABLE)
14040                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
14041                 /* Give up focus if we are no longer focusable */
14042                 clearFocus();
14043                 if (mParent instanceof ViewGroup) {
14044                     ((ViewGroup) mParent).clearFocusedInCluster();
14045                 }
14046             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
14047                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
14048                 /*
14049                  * Tell the view system that we are now available to take focus
14050                  * if no one else already has it.
14051                  */
14052                 if (mParent != null) {
14053                     ViewRootImpl viewRootImpl = getViewRootImpl();
14054                     if (!sAutoFocusableOffUIThreadWontNotifyParents
14055                             || focusableChangedByAuto == 0
14056                             || viewRootImpl == null
14057                             || viewRootImpl.mThread == Thread.currentThread()) {
14058                         shouldNotifyFocusableAvailable = canTakeFocus();
14059                     }
14060                 }
14061             }
14062         }
14063 
14064         final int newVisibility = flags & VISIBILITY_MASK;
14065         if (newVisibility == VISIBLE) {
14066             if ((changed & VISIBILITY_MASK) != 0) {
14067                 /*
14068                  * If this view is becoming visible, invalidate it in case it changed while
14069                  * it was not visible. Marking it drawn ensures that the invalidation will
14070                  * go through.
14071                  */
14072                 mPrivateFlags |= PFLAG_DRAWN;
14073                 invalidate(true);
14074 
14075                 needGlobalAttributesUpdate(true);
14076 
14077                 // a view becoming visible is worth notifying the parent about in case nothing has
14078                 // focus. Even if this specific view isn't focusable, it may contain something that
14079                 // is, so let the root view try to give this focus if nothing else does.
14080                 shouldNotifyFocusableAvailable = hasSize();
14081             }
14082         }
14083 
14084         if ((changed & ENABLED_MASK) != 0) {
14085             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
14086                 // a view becoming enabled should notify the parent as long as the view is also
14087                 // visible and the parent wasn't already notified by becoming visible during this
14088                 // setFlags invocation.
14089                 shouldNotifyFocusableAvailable = canTakeFocus();
14090             } else {
14091                 if (isFocused()) clearFocus();
14092             }
14093         }
14094 
14095         if (shouldNotifyFocusableAvailable && mParent != null) {
14096             mParent.focusableViewAvailable(this);
14097         }
14098 
14099         /* Check if the GONE bit has changed */
14100         if ((changed & GONE) != 0) {
14101             needGlobalAttributesUpdate(false);
14102             requestLayout();
14103 
14104             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
14105                 if (hasFocus()) {
14106                     clearFocus();
14107                     if (mParent instanceof ViewGroup) {
14108                         ((ViewGroup) mParent).clearFocusedInCluster();
14109                     }
14110                 }
14111                 clearAccessibilityFocus();
14112                 destroyDrawingCache();
14113                 if (mParent instanceof View) {
14114                     // GONE views noop invalidation, so invalidate the parent
14115                     ((View) mParent).invalidate(true);
14116                 }
14117                 // Mark the view drawn to ensure that it gets invalidated properly the next
14118                 // time it is visible and gets invalidated
14119                 mPrivateFlags |= PFLAG_DRAWN;
14120             }
14121             if (mAttachInfo != null) {
14122                 mAttachInfo.mViewVisibilityChanged = true;
14123             }
14124         }
14125 
14126         /* Check if the VISIBLE bit has changed */
14127         if ((changed & INVISIBLE) != 0) {
14128             needGlobalAttributesUpdate(false);
14129             /*
14130              * If this view is becoming invisible, set the DRAWN flag so that
14131              * the next invalidate() will not be skipped.
14132              */
14133             mPrivateFlags |= PFLAG_DRAWN;
14134 
14135             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
14136                 // root view becoming invisible shouldn't clear focus and accessibility focus
14137                 if (getRootView() != this) {
14138                     if (hasFocus()) {
14139                         clearFocus();
14140                         if (mParent instanceof ViewGroup) {
14141                             ((ViewGroup) mParent).clearFocusedInCluster();
14142                         }
14143                     }
14144                     clearAccessibilityFocus();
14145                 }
14146             }
14147             if (mAttachInfo != null) {
14148                 mAttachInfo.mViewVisibilityChanged = true;
14149             }
14150         }
14151 
14152         if ((changed & VISIBILITY_MASK) != 0) {
14153             // If the view is invisible, cleanup its display list to free up resources
14154             if (newVisibility != VISIBLE && mAttachInfo != null) {
14155                 cleanupDraw();
14156             }
14157 
14158             if (mParent instanceof ViewGroup) {
14159                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
14160                         (changed & VISIBILITY_MASK), newVisibility);
14161                 ((View) mParent).invalidate(true);
14162             } else if (mParent != null) {
14163                 mParent.invalidateChild(this, null);
14164             }
14165 
14166             if (mAttachInfo != null) {
14167                 dispatchVisibilityChanged(this, newVisibility);
14168 
14169                 // Aggregated visibility changes are dispatched to attached views
14170                 // in visible windows where the parent is currently shown/drawn
14171                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
14172                 // discounting clipping or overlapping. This makes it a good place
14173                 // to change animation states.
14174                 if (mParent != null && getWindowVisibility() == VISIBLE &&
14175                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
14176                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
14177                 }
14178                 notifySubtreeAccessibilityStateChangedIfNeeded();
14179             }
14180         }
14181 
14182         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
14183             destroyDrawingCache();
14184         }
14185 
14186         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
14187             destroyDrawingCache();
14188             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14189             invalidateParentCaches();
14190         }
14191 
14192         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
14193             destroyDrawingCache();
14194             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14195         }
14196 
14197         if ((changed & DRAW_MASK) != 0) {
14198             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
14199                 if (mBackground != null
14200                         || mDefaultFocusHighlight != null
14201                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
14202                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14203                 } else {
14204                     mPrivateFlags |= PFLAG_SKIP_DRAW;
14205                 }
14206             } else {
14207                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14208             }
14209             requestLayout();
14210             invalidate(true);
14211         }
14212 
14213         if ((changed & KEEP_SCREEN_ON) != 0) {
14214             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
14215                 mParent.recomputeViewAttributes(this);
14216             }
14217         }
14218 
14219         if (accessibilityEnabled) {
14220             // If we're an accessibility pane and the visibility changed, we already have sent
14221             // a state change, so we really don't need to report other changes.
14222             if (isAccessibilityPane()) {
14223                 changed &= ~VISIBILITY_MASK;
14224             }
14225             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
14226                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
14227                     || (changed & CONTEXT_CLICKABLE) != 0) {
14228                 if (oldIncludeForAccessibility != includeForAccessibility()) {
14229                     notifySubtreeAccessibilityStateChangedIfNeeded();
14230                 } else {
14231                     notifyViewAccessibilityStateChangedIfNeeded(
14232                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14233                 }
14234             } else if ((changed & ENABLED_MASK) != 0) {
14235                 notifyViewAccessibilityStateChangedIfNeeded(
14236                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14237             }
14238         }
14239     }
14240 
14241     /**
14242      * Change the view's z order in the tree, so it's on top of other sibling
14243      * views. This ordering change may affect layout, if the parent container
14244      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
14245      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
14246      * method should be followed by calls to {@link #requestLayout()} and
14247      * {@link View#invalidate()} on the view's parent to force the parent to redraw
14248      * with the new child ordering.
14249      *
14250      * @see ViewGroup#bringChildToFront(View)
14251      */
bringToFront()14252     public void bringToFront() {
14253         if (mParent != null) {
14254             mParent.bringChildToFront(this);
14255         }
14256     }
14257 
14258     /**
14259      * This is called in response to an internal scroll in this view (i.e., the
14260      * view scrolled its own contents). This is typically as a result of
14261      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
14262      * called.
14263      *
14264      * @param l Current horizontal scroll origin.
14265      * @param t Current vertical scroll origin.
14266      * @param oldl Previous horizontal scroll origin.
14267      * @param oldt Previous vertical scroll origin.
14268      */
onScrollChanged(int l, int t, int oldl, int oldt)14269     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
14270         notifySubtreeAccessibilityStateChangedIfNeeded();
14271 
14272         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
14273             postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
14274         }
14275 
14276         mBackgroundSizeChanged = true;
14277         mDefaultFocusHighlightSizeChanged = true;
14278         if (mForegroundInfo != null) {
14279             mForegroundInfo.mBoundsChanged = true;
14280         }
14281 
14282         final AttachInfo ai = mAttachInfo;
14283         if (ai != null) {
14284             ai.mViewScrollChanged = true;
14285         }
14286 
14287         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
14288             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
14289         }
14290     }
14291 
14292     /**
14293      * Interface definition for a callback to be invoked when the scroll
14294      * X or Y positions of a view change.
14295      * <p>
14296      * <b>Note:</b> Some views handle scrolling independently from View and may
14297      * have their own separate listeners for scroll-type events. For example,
14298      * {@link android.widget.ListView ListView} allows clients to register an
14299      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
14300      * to listen for changes in list scroll position.
14301      *
14302      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
14303      */
14304     public interface OnScrollChangeListener {
14305         /**
14306          * Called when the scroll position of a view changes.
14307          *
14308          * @param v The view whose scroll position has changed.
14309          * @param scrollX Current horizontal scroll origin.
14310          * @param scrollY Current vertical scroll origin.
14311          * @param oldScrollX Previous horizontal scroll origin.
14312          * @param oldScrollY Previous vertical scroll origin.
14313          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)14314         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
14315     }
14316 
14317     /**
14318      * Interface definition for a callback to be invoked when the layout bounds of a view
14319      * changes due to layout processing.
14320      */
14321     public interface OnLayoutChangeListener {
14322         /**
14323          * Called when the layout bounds of a view changes due to layout processing.
14324          *
14325          * @param v The view whose bounds have changed.
14326          * @param left The new value of the view's left property.
14327          * @param top The new value of the view's top property.
14328          * @param right The new value of the view's right property.
14329          * @param bottom The new value of the view's bottom property.
14330          * @param oldLeft The previous value of the view's left property.
14331          * @param oldTop The previous value of the view's top property.
14332          * @param oldRight The previous value of the view's right property.
14333          * @param oldBottom The previous value of the view's bottom property.
14334          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)14335         void onLayoutChange(View v, int left, int top, int right, int bottom,
14336             int oldLeft, int oldTop, int oldRight, int oldBottom);
14337     }
14338 
14339     /**
14340      * This is called during layout when the size of this view has changed. If
14341      * you were just added to the view hierarchy, you're called with the old
14342      * values of 0.
14343      *
14344      * @param w Current width of this view.
14345      * @param h Current height of this view.
14346      * @param oldw Old width of this view.
14347      * @param oldh Old height of this view.
14348      */
onSizeChanged(int w, int h, int oldw, int oldh)14349     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
14350     }
14351 
14352     /**
14353      * Called by draw to draw the child views. This may be overridden
14354      * by derived classes to gain control just before its children are drawn
14355      * (but after its own view has been drawn).
14356      * @param canvas the canvas on which to draw the view
14357      */
dispatchDraw(Canvas canvas)14358     protected void dispatchDraw(Canvas canvas) {
14359 
14360     }
14361 
14362     /**
14363      * Gets the parent of this view. Note that the parent is a
14364      * ViewParent and not necessarily a View.
14365      *
14366      * @return Parent of this view.
14367      */
getParent()14368     public final ViewParent getParent() {
14369         return mParent;
14370     }
14371 
14372     /**
14373      * Set the horizontal scrolled position of your view. This will cause a call to
14374      * {@link #onScrollChanged(int, int, int, int)} and the view will be
14375      * invalidated.
14376      * @param value the x position to scroll to
14377      */
setScrollX(int value)14378     public void setScrollX(int value) {
14379         scrollTo(value, mScrollY);
14380     }
14381 
14382     /**
14383      * Set the vertical scrolled position of your view. This will cause a call to
14384      * {@link #onScrollChanged(int, int, int, int)} and the view will be
14385      * invalidated.
14386      * @param value the y position to scroll to
14387      */
setScrollY(int value)14388     public void setScrollY(int value) {
14389         scrollTo(mScrollX, value);
14390     }
14391 
14392     /**
14393      * Return the scrolled left position of this view. This is the left edge of
14394      * the displayed part of your view. You do not need to draw any pixels
14395      * farther left, since those are outside of the frame of your view on
14396      * screen.
14397      *
14398      * @return The left edge of the displayed part of your view, in pixels.
14399      */
getScrollX()14400     public final int getScrollX() {
14401         return mScrollX;
14402     }
14403 
14404     /**
14405      * Return the scrolled top position of this view. This is the top edge of
14406      * the displayed part of your view. You do not need to draw any pixels above
14407      * it, since those are outside of the frame of your view on screen.
14408      *
14409      * @return The top edge of the displayed part of your view, in pixels.
14410      */
getScrollY()14411     public final int getScrollY() {
14412         return mScrollY;
14413     }
14414 
14415     /**
14416      * Return the width of your view.
14417      *
14418      * @return The width of your view, in pixels.
14419      */
14420     @ViewDebug.ExportedProperty(category = "layout")
getWidth()14421     public final int getWidth() {
14422         return mRight - mLeft;
14423     }
14424 
14425     /**
14426      * Return the height of your view.
14427      *
14428      * @return The height of your view, in pixels.
14429      */
14430     @ViewDebug.ExportedProperty(category = "layout")
getHeight()14431     public final int getHeight() {
14432         return mBottom - mTop;
14433     }
14434 
14435     /**
14436      * Return the visible drawing bounds of your view. Fills in the output
14437      * rectangle with the values from getScrollX(), getScrollY(),
14438      * getWidth(), and getHeight(). These bounds do not account for any
14439      * transformation properties currently set on the view, such as
14440      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
14441      *
14442      * @param outRect The (scrolled) drawing bounds of the view.
14443      */
getDrawingRect(Rect outRect)14444     public void getDrawingRect(Rect outRect) {
14445         outRect.left = mScrollX;
14446         outRect.top = mScrollY;
14447         outRect.right = mScrollX + (mRight - mLeft);
14448         outRect.bottom = mScrollY + (mBottom - mTop);
14449     }
14450 
14451     /**
14452      * Like {@link #getMeasuredWidthAndState()}, but only returns the
14453      * raw width component (that is the result is masked by
14454      * {@link #MEASURED_SIZE_MASK}).
14455      *
14456      * @return The raw measured width of this view.
14457      */
getMeasuredWidth()14458     public final int getMeasuredWidth() {
14459         return mMeasuredWidth & MEASURED_SIZE_MASK;
14460     }
14461 
14462     /**
14463      * Return the full width measurement information for this view as computed
14464      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
14465      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
14466      * This should be used during measurement and layout calculations only. Use
14467      * {@link #getWidth()} to see how wide a view is after layout.
14468      *
14469      * @return The measured width of this view as a bit mask.
14470      */
14471     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
14472             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
14473                     name = "MEASURED_STATE_TOO_SMALL"),
14474     })
getMeasuredWidthAndState()14475     public final int getMeasuredWidthAndState() {
14476         return mMeasuredWidth;
14477     }
14478 
14479     /**
14480      * Like {@link #getMeasuredHeightAndState()}, but only returns the
14481      * raw height component (that is the result is masked by
14482      * {@link #MEASURED_SIZE_MASK}).
14483      *
14484      * @return The raw measured height of this view.
14485      */
getMeasuredHeight()14486     public final int getMeasuredHeight() {
14487         return mMeasuredHeight & MEASURED_SIZE_MASK;
14488     }
14489 
14490     /**
14491      * Return the full height measurement information for this view as computed
14492      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
14493      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
14494      * This should be used during measurement and layout calculations only. Use
14495      * {@link #getHeight()} to see how wide a view is after layout.
14496      *
14497      * @return The measured height of this view as a bit mask.
14498      */
14499     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
14500             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
14501                     name = "MEASURED_STATE_TOO_SMALL"),
14502     })
getMeasuredHeightAndState()14503     public final int getMeasuredHeightAndState() {
14504         return mMeasuredHeight;
14505     }
14506 
14507     /**
14508      * Return only the state bits of {@link #getMeasuredWidthAndState()}
14509      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
14510      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
14511      * and the height component is at the shifted bits
14512      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
14513      */
getMeasuredState()14514     public final int getMeasuredState() {
14515         return (mMeasuredWidth&MEASURED_STATE_MASK)
14516                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
14517                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
14518     }
14519 
14520     /**
14521      * The transform matrix of this view, which is calculated based on the current
14522      * rotation, scale, and pivot properties.
14523      *
14524      * @see #getRotation()
14525      * @see #getScaleX()
14526      * @see #getScaleY()
14527      * @see #getPivotX()
14528      * @see #getPivotY()
14529      * @return The current transform matrix for the view
14530      */
getMatrix()14531     public Matrix getMatrix() {
14532         ensureTransformationInfo();
14533         final Matrix matrix = mTransformationInfo.mMatrix;
14534         mRenderNode.getMatrix(matrix);
14535         return matrix;
14536     }
14537 
14538     /**
14539      * Returns true if the transform matrix is the identity matrix.
14540      * Recomputes the matrix if necessary.
14541      *
14542      * @return True if the transform matrix is the identity matrix, false otherwise.
14543      */
hasIdentityMatrix()14544     final boolean hasIdentityMatrix() {
14545         return mRenderNode.hasIdentityMatrix();
14546     }
14547 
ensureTransformationInfo()14548     void ensureTransformationInfo() {
14549         if (mTransformationInfo == null) {
14550             mTransformationInfo = new TransformationInfo();
14551         }
14552     }
14553 
14554     /**
14555      * Utility method to retrieve the inverse of the current mMatrix property.
14556      * We cache the matrix to avoid recalculating it when transform properties
14557      * have not changed.
14558      *
14559      * @return The inverse of the current matrix of this view.
14560      * @hide
14561      */
getInverseMatrix()14562     public final Matrix getInverseMatrix() {
14563         ensureTransformationInfo();
14564         if (mTransformationInfo.mInverseMatrix == null) {
14565             mTransformationInfo.mInverseMatrix = new Matrix();
14566         }
14567         final Matrix matrix = mTransformationInfo.mInverseMatrix;
14568         mRenderNode.getInverseMatrix(matrix);
14569         return matrix;
14570     }
14571 
14572     /**
14573      * Gets the distance along the Z axis from the camera to this view.
14574      *
14575      * @see #setCameraDistance(float)
14576      *
14577      * @return The distance along the Z axis.
14578      */
getCameraDistance()14579     public float getCameraDistance() {
14580         final float dpi = mResources.getDisplayMetrics().densityDpi;
14581         return -(mRenderNode.getCameraDistance() * dpi);
14582     }
14583 
14584     /**
14585      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
14586      * views are drawn) from the camera to this view. The camera's distance
14587      * affects 3D transformations, for instance rotations around the X and Y
14588      * axis. If the rotationX or rotationY properties are changed and this view is
14589      * large (more than half the size of the screen), it is recommended to always
14590      * use a camera distance that's greater than the height (X axis rotation) or
14591      * the width (Y axis rotation) of this view.</p>
14592      *
14593      * <p>The distance of the camera from the view plane can have an affect on the
14594      * perspective distortion of the view when it is rotated around the x or y axis.
14595      * For example, a large distance will result in a large viewing angle, and there
14596      * will not be much perspective distortion of the view as it rotates. A short
14597      * distance may cause much more perspective distortion upon rotation, and can
14598      * also result in some drawing artifacts if the rotated view ends up partially
14599      * behind the camera (which is why the recommendation is to use a distance at
14600      * least as far as the size of the view, if the view is to be rotated.)</p>
14601      *
14602      * <p>The distance is expressed in "depth pixels." The default distance depends
14603      * on the screen density. For instance, on a medium density display, the
14604      * default distance is 1280. On a high density display, the default distance
14605      * is 1920.</p>
14606      *
14607      * <p>If you want to specify a distance that leads to visually consistent
14608      * results across various densities, use the following formula:</p>
14609      * <pre>
14610      * float scale = context.getResources().getDisplayMetrics().density;
14611      * view.setCameraDistance(distance * scale);
14612      * </pre>
14613      *
14614      * <p>The density scale factor of a high density display is 1.5,
14615      * and 1920 = 1280 * 1.5.</p>
14616      *
14617      * @param distance The distance in "depth pixels", if negative the opposite
14618      *        value is used
14619      *
14620      * @see #setRotationX(float)
14621      * @see #setRotationY(float)
14622      */
setCameraDistance(float distance)14623     public void setCameraDistance(float distance) {
14624         final float dpi = mResources.getDisplayMetrics().densityDpi;
14625 
14626         invalidateViewProperty(true, false);
14627         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
14628         invalidateViewProperty(false, false);
14629 
14630         invalidateParentIfNeededAndWasQuickRejected();
14631     }
14632 
14633     /**
14634      * The degrees that the view is rotated around the pivot point.
14635      *
14636      * @see #setRotation(float)
14637      * @see #getPivotX()
14638      * @see #getPivotY()
14639      *
14640      * @return The degrees of rotation.
14641      */
14642     @ViewDebug.ExportedProperty(category = "drawing")
getRotation()14643     public float getRotation() {
14644         return mRenderNode.getRotation();
14645     }
14646 
14647     /**
14648      * Sets the degrees that the view is rotated around the pivot point. Increasing values
14649      * result in clockwise rotation.
14650      *
14651      * @param rotation The degrees of rotation.
14652      *
14653      * @see #getRotation()
14654      * @see #getPivotX()
14655      * @see #getPivotY()
14656      * @see #setRotationX(float)
14657      * @see #setRotationY(float)
14658      *
14659      * @attr ref android.R.styleable#View_rotation
14660      */
setRotation(float rotation)14661     public void setRotation(float rotation) {
14662         if (rotation != getRotation()) {
14663             // Double-invalidation is necessary to capture view's old and new areas
14664             invalidateViewProperty(true, false);
14665             mRenderNode.setRotation(rotation);
14666             invalidateViewProperty(false, true);
14667 
14668             invalidateParentIfNeededAndWasQuickRejected();
14669             notifySubtreeAccessibilityStateChangedIfNeeded();
14670         }
14671     }
14672 
14673     /**
14674      * The degrees that the view is rotated around the vertical axis through the pivot point.
14675      *
14676      * @see #getPivotX()
14677      * @see #getPivotY()
14678      * @see #setRotationY(float)
14679      *
14680      * @return The degrees of Y rotation.
14681      */
14682     @ViewDebug.ExportedProperty(category = "drawing")
getRotationY()14683     public float getRotationY() {
14684         return mRenderNode.getRotationY();
14685     }
14686 
14687     /**
14688      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
14689      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
14690      * down the y axis.
14691      *
14692      * When rotating large views, it is recommended to adjust the camera distance
14693      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
14694      *
14695      * @param rotationY The degrees of Y rotation.
14696      *
14697      * @see #getRotationY()
14698      * @see #getPivotX()
14699      * @see #getPivotY()
14700      * @see #setRotation(float)
14701      * @see #setRotationX(float)
14702      * @see #setCameraDistance(float)
14703      *
14704      * @attr ref android.R.styleable#View_rotationY
14705      */
setRotationY(float rotationY)14706     public void setRotationY(float rotationY) {
14707         if (rotationY != getRotationY()) {
14708             invalidateViewProperty(true, false);
14709             mRenderNode.setRotationY(rotationY);
14710             invalidateViewProperty(false, true);
14711 
14712             invalidateParentIfNeededAndWasQuickRejected();
14713             notifySubtreeAccessibilityStateChangedIfNeeded();
14714         }
14715     }
14716 
14717     /**
14718      * The degrees that the view is rotated around the horizontal axis through the pivot point.
14719      *
14720      * @see #getPivotX()
14721      * @see #getPivotY()
14722      * @see #setRotationX(float)
14723      *
14724      * @return The degrees of X rotation.
14725      */
14726     @ViewDebug.ExportedProperty(category = "drawing")
getRotationX()14727     public float getRotationX() {
14728         return mRenderNode.getRotationX();
14729     }
14730 
14731     /**
14732      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
14733      * Increasing values result in clockwise rotation from the viewpoint of looking down the
14734      * x axis.
14735      *
14736      * When rotating large views, it is recommended to adjust the camera distance
14737      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
14738      *
14739      * @param rotationX The degrees of X rotation.
14740      *
14741      * @see #getRotationX()
14742      * @see #getPivotX()
14743      * @see #getPivotY()
14744      * @see #setRotation(float)
14745      * @see #setRotationY(float)
14746      * @see #setCameraDistance(float)
14747      *
14748      * @attr ref android.R.styleable#View_rotationX
14749      */
setRotationX(float rotationX)14750     public void setRotationX(float rotationX) {
14751         if (rotationX != getRotationX()) {
14752             invalidateViewProperty(true, false);
14753             mRenderNode.setRotationX(rotationX);
14754             invalidateViewProperty(false, true);
14755 
14756             invalidateParentIfNeededAndWasQuickRejected();
14757             notifySubtreeAccessibilityStateChangedIfNeeded();
14758         }
14759     }
14760 
14761     /**
14762      * The amount that the view is scaled in x around the pivot point, as a proportion of
14763      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
14764      *
14765      * <p>By default, this is 1.0f.
14766      *
14767      * @see #getPivotX()
14768      * @see #getPivotY()
14769      * @return The scaling factor.
14770      */
14771     @ViewDebug.ExportedProperty(category = "drawing")
getScaleX()14772     public float getScaleX() {
14773         return mRenderNode.getScaleX();
14774     }
14775 
14776     /**
14777      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
14778      * the view's unscaled width. A value of 1 means that no scaling is applied.
14779      *
14780      * @param scaleX The scaling factor.
14781      * @see #getPivotX()
14782      * @see #getPivotY()
14783      *
14784      * @attr ref android.R.styleable#View_scaleX
14785      */
setScaleX(float scaleX)14786     public void setScaleX(float scaleX) {
14787         if (scaleX != getScaleX()) {
14788             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
14789             invalidateViewProperty(true, false);
14790             mRenderNode.setScaleX(scaleX);
14791             invalidateViewProperty(false, true);
14792 
14793             invalidateParentIfNeededAndWasQuickRejected();
14794             notifySubtreeAccessibilityStateChangedIfNeeded();
14795         }
14796     }
14797 
14798     /**
14799      * The amount that the view is scaled in y around the pivot point, as a proportion of
14800      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
14801      *
14802      * <p>By default, this is 1.0f.
14803      *
14804      * @see #getPivotX()
14805      * @see #getPivotY()
14806      * @return The scaling factor.
14807      */
14808     @ViewDebug.ExportedProperty(category = "drawing")
getScaleY()14809     public float getScaleY() {
14810         return mRenderNode.getScaleY();
14811     }
14812 
14813     /**
14814      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
14815      * the view's unscaled width. A value of 1 means that no scaling is applied.
14816      *
14817      * @param scaleY The scaling factor.
14818      * @see #getPivotX()
14819      * @see #getPivotY()
14820      *
14821      * @attr ref android.R.styleable#View_scaleY
14822      */
setScaleY(float scaleY)14823     public void setScaleY(float scaleY) {
14824         if (scaleY != getScaleY()) {
14825             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
14826             invalidateViewProperty(true, false);
14827             mRenderNode.setScaleY(scaleY);
14828             invalidateViewProperty(false, true);
14829 
14830             invalidateParentIfNeededAndWasQuickRejected();
14831             notifySubtreeAccessibilityStateChangedIfNeeded();
14832         }
14833     }
14834 
14835     /**
14836      * The x location of the point around which the view is {@link #setRotation(float) rotated}
14837      * and {@link #setScaleX(float) scaled}.
14838      *
14839      * @see #getRotation()
14840      * @see #getScaleX()
14841      * @see #getScaleY()
14842      * @see #getPivotY()
14843      * @return The x location of the pivot point.
14844      *
14845      * @attr ref android.R.styleable#View_transformPivotX
14846      */
14847     @ViewDebug.ExportedProperty(category = "drawing")
getPivotX()14848     public float getPivotX() {
14849         return mRenderNode.getPivotX();
14850     }
14851 
14852     /**
14853      * Sets the x location of the point around which the view is
14854      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
14855      * By default, the pivot point is centered on the object.
14856      * Setting this property disables this behavior and causes the view to use only the
14857      * explicitly set pivotX and pivotY values.
14858      *
14859      * @param pivotX The x location of the pivot point.
14860      * @see #getRotation()
14861      * @see #getScaleX()
14862      * @see #getScaleY()
14863      * @see #getPivotY()
14864      *
14865      * @attr ref android.R.styleable#View_transformPivotX
14866      */
setPivotX(float pivotX)14867     public void setPivotX(float pivotX) {
14868         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
14869             invalidateViewProperty(true, false);
14870             mRenderNode.setPivotX(pivotX);
14871             invalidateViewProperty(false, true);
14872 
14873             invalidateParentIfNeededAndWasQuickRejected();
14874         }
14875     }
14876 
14877     /**
14878      * The y location of the point around which the view is {@link #setRotation(float) rotated}
14879      * and {@link #setScaleY(float) scaled}.
14880      *
14881      * @see #getRotation()
14882      * @see #getScaleX()
14883      * @see #getScaleY()
14884      * @see #getPivotY()
14885      * @return The y location of the pivot point.
14886      *
14887      * @attr ref android.R.styleable#View_transformPivotY
14888      */
14889     @ViewDebug.ExportedProperty(category = "drawing")
getPivotY()14890     public float getPivotY() {
14891         return mRenderNode.getPivotY();
14892     }
14893 
14894     /**
14895      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
14896      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
14897      * Setting this property disables this behavior and causes the view to use only the
14898      * explicitly set pivotX and pivotY values.
14899      *
14900      * @param pivotY The y location of the pivot point.
14901      * @see #getRotation()
14902      * @see #getScaleX()
14903      * @see #getScaleY()
14904      * @see #getPivotY()
14905      *
14906      * @attr ref android.R.styleable#View_transformPivotY
14907      */
setPivotY(float pivotY)14908     public void setPivotY(float pivotY) {
14909         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
14910             invalidateViewProperty(true, false);
14911             mRenderNode.setPivotY(pivotY);
14912             invalidateViewProperty(false, true);
14913 
14914             invalidateParentIfNeededAndWasQuickRejected();
14915         }
14916     }
14917 
14918     /**
14919      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
14920      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
14921      * of the view.
14922      *
14923      * @return True if a pivot has been set, false if the default pivot is being used
14924      */
isPivotSet()14925     public boolean isPivotSet() {
14926         return mRenderNode.isPivotExplicitlySet();
14927     }
14928 
14929     /**
14930      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
14931      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
14932      * and the pivot used for rotation will return to default of being centered on the view.
14933      */
resetPivot()14934     public void resetPivot() {
14935         if (mRenderNode.resetPivot()) {
14936             invalidateViewProperty(false, false);
14937         }
14938     }
14939 
14940     /**
14941      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
14942      * completely transparent and 1 means the view is completely opaque.
14943      *
14944      * <p>By default this is 1.0f.
14945      * @return The opacity of the view.
14946      */
14947     @ViewDebug.ExportedProperty(category = "drawing")
getAlpha()14948     public float getAlpha() {
14949         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
14950     }
14951 
14952     /**
14953      * Sets the behavior for overlapping rendering for this view (see {@link
14954      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
14955      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
14956      * providing the value which is then used internally. That is, when {@link
14957      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
14958      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
14959      * instead.
14960      *
14961      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
14962      * instead of that returned by {@link #hasOverlappingRendering()}.
14963      *
14964      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
14965      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)14966     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
14967         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
14968         if (hasOverlappingRendering) {
14969             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14970         } else {
14971             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14972         }
14973     }
14974 
14975     /**
14976      * Returns the value for overlapping rendering that is used internally. This is either
14977      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
14978      * the return value of {@link #hasOverlappingRendering()}, otherwise.
14979      *
14980      * @return The value for overlapping rendering being used internally.
14981      */
getHasOverlappingRendering()14982     public final boolean getHasOverlappingRendering() {
14983         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
14984                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
14985                 hasOverlappingRendering();
14986     }
14987 
14988     /**
14989      * Returns whether this View has content which overlaps.
14990      *
14991      * <p>This function, intended to be overridden by specific View types, is an optimization when
14992      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
14993      * an offscreen buffer and then composited into place, which can be expensive. If the view has
14994      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
14995      * directly. An example of overlapping rendering is a TextView with a background image, such as
14996      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
14997      * ImageView with only the foreground image. The default implementation returns true; subclasses
14998      * should override if they have cases which can be optimized.</p>
14999      *
15000      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
15001      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
15002      *
15003      * @return true if the content in this view might overlap, false otherwise.
15004      */
15005     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()15006     public boolean hasOverlappingRendering() {
15007         return true;
15008     }
15009 
15010     /**
15011      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
15012      * completely transparent and 1 means the view is completely opaque.
15013      *
15014      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
15015      * can have significant performance implications, especially for large views. It is best to use
15016      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
15017      *
15018      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
15019      * strongly recommended for performance reasons to either override
15020      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
15021      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
15022      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
15023      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
15024      * of rendering cost, even for simple or small views. Starting with
15025      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
15026      * applied to the view at the rendering level.</p>
15027      *
15028      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
15029      * responsible for applying the opacity itself.</p>
15030      *
15031      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
15032      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
15033      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
15034      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
15035      *
15036      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
15037      * value will clip a View to its bounds, unless the View returns <code>false</code> from
15038      * {@link #hasOverlappingRendering}.</p>
15039      *
15040      * @param alpha The opacity of the view.
15041      *
15042      * @see #hasOverlappingRendering()
15043      * @see #setLayerType(int, android.graphics.Paint)
15044      *
15045      * @attr ref android.R.styleable#View_alpha
15046      */
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)15047     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
15048         ensureTransformationInfo();
15049         if (mTransformationInfo.mAlpha != alpha) {
15050             setAlphaInternal(alpha);
15051             if (onSetAlpha((int) (alpha * 255))) {
15052                 mPrivateFlags |= PFLAG_ALPHA_SET;
15053                 // subclass is handling alpha - don't optimize rendering cache invalidation
15054                 invalidateParentCaches();
15055                 invalidate(true);
15056             } else {
15057                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
15058                 invalidateViewProperty(true, false);
15059                 mRenderNode.setAlpha(getFinalAlpha());
15060             }
15061         }
15062     }
15063 
15064     /**
15065      * Faster version of setAlpha() which performs the same steps except there are
15066      * no calls to invalidate(). The caller of this function should perform proper invalidation
15067      * on the parent and this object. The return value indicates whether the subclass handles
15068      * alpha (the return value for onSetAlpha()).
15069      *
15070      * @param alpha The new value for the alpha property
15071      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
15072      *         the new value for the alpha property is different from the old value
15073      */
setAlphaNoInvalidation(float alpha)15074     boolean setAlphaNoInvalidation(float alpha) {
15075         ensureTransformationInfo();
15076         if (mTransformationInfo.mAlpha != alpha) {
15077             setAlphaInternal(alpha);
15078             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
15079             if (subclassHandlesAlpha) {
15080                 mPrivateFlags |= PFLAG_ALPHA_SET;
15081                 return true;
15082             } else {
15083                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
15084                 mRenderNode.setAlpha(getFinalAlpha());
15085             }
15086         }
15087         return false;
15088     }
15089 
setAlphaInternal(float alpha)15090     private void setAlphaInternal(float alpha) {
15091         float oldAlpha = mTransformationInfo.mAlpha;
15092         mTransformationInfo.mAlpha = alpha;
15093         // Report visibility changes, which can affect children, to accessibility
15094         if ((alpha == 0) ^ (oldAlpha == 0)) {
15095             notifySubtreeAccessibilityStateChangedIfNeeded();
15096         }
15097     }
15098 
15099     /**
15100      * This property is hidden and intended only for use by the Fade transition, which
15101      * animates it to produce a visual translucency that does not side-effect (or get
15102      * affected by) the real alpha property. This value is composited with the other
15103      * alpha value (and the AlphaAnimation value, when that is present) to produce
15104      * a final visual translucency result, which is what is passed into the DisplayList.
15105      *
15106      * @hide
15107      */
setTransitionAlpha(float alpha)15108     public void setTransitionAlpha(float alpha) {
15109         ensureTransformationInfo();
15110         if (mTransformationInfo.mTransitionAlpha != alpha) {
15111             mTransformationInfo.mTransitionAlpha = alpha;
15112             mPrivateFlags &= ~PFLAG_ALPHA_SET;
15113             invalidateViewProperty(true, false);
15114             mRenderNode.setAlpha(getFinalAlpha());
15115         }
15116     }
15117 
15118     /**
15119      * Calculates the visual alpha of this view, which is a combination of the actual
15120      * alpha value and the transitionAlpha value (if set).
15121      */
getFinalAlpha()15122     private float getFinalAlpha() {
15123         if (mTransformationInfo != null) {
15124             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
15125         }
15126         return 1;
15127     }
15128 
15129     /**
15130      * This property is hidden and intended only for use by the Fade transition, which
15131      * animates it to produce a visual translucency that does not side-effect (or get
15132      * affected by) the real alpha property. This value is composited with the other
15133      * alpha value (and the AlphaAnimation value, when that is present) to produce
15134      * a final visual translucency result, which is what is passed into the DisplayList.
15135      *
15136      * @hide
15137      */
15138     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()15139     public float getTransitionAlpha() {
15140         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
15141     }
15142 
15143     /**
15144      * Top position of this view relative to its parent.
15145      *
15146      * @return The top of this view, in pixels.
15147      */
15148     @ViewDebug.CapturedViewProperty
getTop()15149     public final int getTop() {
15150         return mTop;
15151     }
15152 
15153     /**
15154      * Sets the top position of this view relative to its parent. This method is meant to be called
15155      * by the layout system and should not generally be called otherwise, because the property
15156      * may be changed at any time by the layout.
15157      *
15158      * @param top The top of this view, in pixels.
15159      */
setTop(int top)15160     public final void setTop(int top) {
15161         if (top != mTop) {
15162             final boolean matrixIsIdentity = hasIdentityMatrix();
15163             if (matrixIsIdentity) {
15164                 if (mAttachInfo != null) {
15165                     int minTop;
15166                     int yLoc;
15167                     if (top < mTop) {
15168                         minTop = top;
15169                         yLoc = top - mTop;
15170                     } else {
15171                         minTop = mTop;
15172                         yLoc = 0;
15173                     }
15174                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
15175                 }
15176             } else {
15177                 // Double-invalidation is necessary to capture view's old and new areas
15178                 invalidate(true);
15179             }
15180 
15181             int width = mRight - mLeft;
15182             int oldHeight = mBottom - mTop;
15183 
15184             mTop = top;
15185             mRenderNode.setTop(mTop);
15186 
15187             sizeChange(width, mBottom - mTop, width, oldHeight);
15188 
15189             if (!matrixIsIdentity) {
15190                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15191                 invalidate(true);
15192             }
15193             mBackgroundSizeChanged = true;
15194             mDefaultFocusHighlightSizeChanged = true;
15195             if (mForegroundInfo != null) {
15196                 mForegroundInfo.mBoundsChanged = true;
15197             }
15198             invalidateParentIfNeeded();
15199             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
15200                 // View was rejected last time it was drawn by its parent; this may have changed
15201                 invalidateParentIfNeeded();
15202             }
15203         }
15204     }
15205 
15206     /**
15207      * Bottom position of this view relative to its parent.
15208      *
15209      * @return The bottom of this view, in pixels.
15210      */
15211     @ViewDebug.CapturedViewProperty
getBottom()15212     public final int getBottom() {
15213         return mBottom;
15214     }
15215 
15216     /**
15217      * True if this view has changed since the last time being drawn.
15218      *
15219      * @return The dirty state of this view.
15220      */
isDirty()15221     public boolean isDirty() {
15222         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
15223     }
15224 
15225     /**
15226      * Sets the bottom position of this view relative to its parent. This method is meant to be
15227      * called by the layout system and should not generally be called otherwise, because the
15228      * property may be changed at any time by the layout.
15229      *
15230      * @param bottom The bottom of this view, in pixels.
15231      */
setBottom(int bottom)15232     public final void setBottom(int bottom) {
15233         if (bottom != mBottom) {
15234             final boolean matrixIsIdentity = hasIdentityMatrix();
15235             if (matrixIsIdentity) {
15236                 if (mAttachInfo != null) {
15237                     int maxBottom;
15238                     if (bottom < mBottom) {
15239                         maxBottom = mBottom;
15240                     } else {
15241                         maxBottom = bottom;
15242                     }
15243                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
15244                 }
15245             } else {
15246                 // Double-invalidation is necessary to capture view's old and new areas
15247                 invalidate(true);
15248             }
15249 
15250             int width = mRight - mLeft;
15251             int oldHeight = mBottom - mTop;
15252 
15253             mBottom = bottom;
15254             mRenderNode.setBottom(mBottom);
15255 
15256             sizeChange(width, mBottom - mTop, width, oldHeight);
15257 
15258             if (!matrixIsIdentity) {
15259                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15260                 invalidate(true);
15261             }
15262             mBackgroundSizeChanged = true;
15263             mDefaultFocusHighlightSizeChanged = true;
15264             if (mForegroundInfo != null) {
15265                 mForegroundInfo.mBoundsChanged = true;
15266             }
15267             invalidateParentIfNeeded();
15268             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
15269                 // View was rejected last time it was drawn by its parent; this may have changed
15270                 invalidateParentIfNeeded();
15271             }
15272         }
15273     }
15274 
15275     /**
15276      * Left position of this view relative to its parent.
15277      *
15278      * @return The left edge of this view, in pixels.
15279      */
15280     @ViewDebug.CapturedViewProperty
getLeft()15281     public final int getLeft() {
15282         return mLeft;
15283     }
15284 
15285     /**
15286      * Sets the left position of this view relative to its parent. This method is meant to be called
15287      * by the layout system and should not generally be called otherwise, because the property
15288      * may be changed at any time by the layout.
15289      *
15290      * @param left The left of this view, in pixels.
15291      */
setLeft(int left)15292     public final void setLeft(int left) {
15293         if (left != mLeft) {
15294             final boolean matrixIsIdentity = hasIdentityMatrix();
15295             if (matrixIsIdentity) {
15296                 if (mAttachInfo != null) {
15297                     int minLeft;
15298                     int xLoc;
15299                     if (left < mLeft) {
15300                         minLeft = left;
15301                         xLoc = left - mLeft;
15302                     } else {
15303                         minLeft = mLeft;
15304                         xLoc = 0;
15305                     }
15306                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
15307                 }
15308             } else {
15309                 // Double-invalidation is necessary to capture view's old and new areas
15310                 invalidate(true);
15311             }
15312 
15313             int oldWidth = mRight - mLeft;
15314             int height = mBottom - mTop;
15315 
15316             mLeft = left;
15317             mRenderNode.setLeft(left);
15318 
15319             sizeChange(mRight - mLeft, height, oldWidth, height);
15320 
15321             if (!matrixIsIdentity) {
15322                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15323                 invalidate(true);
15324             }
15325             mBackgroundSizeChanged = true;
15326             mDefaultFocusHighlightSizeChanged = true;
15327             if (mForegroundInfo != null) {
15328                 mForegroundInfo.mBoundsChanged = true;
15329             }
15330             invalidateParentIfNeeded();
15331             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
15332                 // View was rejected last time it was drawn by its parent; this may have changed
15333                 invalidateParentIfNeeded();
15334             }
15335         }
15336     }
15337 
15338     /**
15339      * Right position of this view relative to its parent.
15340      *
15341      * @return The right edge of this view, in pixels.
15342      */
15343     @ViewDebug.CapturedViewProperty
getRight()15344     public final int getRight() {
15345         return mRight;
15346     }
15347 
15348     /**
15349      * Sets the right position of this view relative to its parent. This method is meant to be called
15350      * by the layout system and should not generally be called otherwise, because the property
15351      * may be changed at any time by the layout.
15352      *
15353      * @param right The right of this view, in pixels.
15354      */
setRight(int right)15355     public final void setRight(int right) {
15356         if (right != mRight) {
15357             final boolean matrixIsIdentity = hasIdentityMatrix();
15358             if (matrixIsIdentity) {
15359                 if (mAttachInfo != null) {
15360                     int maxRight;
15361                     if (right < mRight) {
15362                         maxRight = mRight;
15363                     } else {
15364                         maxRight = right;
15365                     }
15366                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
15367                 }
15368             } else {
15369                 // Double-invalidation is necessary to capture view's old and new areas
15370                 invalidate(true);
15371             }
15372 
15373             int oldWidth = mRight - mLeft;
15374             int height = mBottom - mTop;
15375 
15376             mRight = right;
15377             mRenderNode.setRight(mRight);
15378 
15379             sizeChange(mRight - mLeft, height, oldWidth, height);
15380 
15381             if (!matrixIsIdentity) {
15382                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15383                 invalidate(true);
15384             }
15385             mBackgroundSizeChanged = true;
15386             mDefaultFocusHighlightSizeChanged = true;
15387             if (mForegroundInfo != null) {
15388                 mForegroundInfo.mBoundsChanged = true;
15389             }
15390             invalidateParentIfNeeded();
15391             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
15392                 // View was rejected last time it was drawn by its parent; this may have changed
15393                 invalidateParentIfNeeded();
15394             }
15395         }
15396     }
15397 
sanitizeFloatPropertyValue(float value, String propertyName)15398     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
15399         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
15400     }
15401 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)15402     private static float sanitizeFloatPropertyValue(float value, String propertyName,
15403             float min, float max) {
15404         // The expected "nothing bad happened" path
15405         if (value >= min && value <= max) return value;
15406 
15407         if (value < min || value == Float.NEGATIVE_INFINITY) {
15408             if (sThrowOnInvalidFloatProperties) {
15409                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
15410                         + value + ", the value must be >= " + min);
15411             }
15412             return min;
15413         }
15414 
15415         if (value > max || value == Float.POSITIVE_INFINITY) {
15416             if (sThrowOnInvalidFloatProperties) {
15417                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
15418                         + value + ", the value must be <= " + max);
15419             }
15420             return max;
15421         }
15422 
15423         if (Float.isNaN(value)) {
15424             if (sThrowOnInvalidFloatProperties) {
15425                 throw new IllegalArgumentException(
15426                         "Cannot set '" + propertyName + "' to Float.NaN");
15427             }
15428             return 0; // Unclear which direction this NaN went so... 0?
15429         }
15430 
15431         // Shouldn't be possible to reach this.
15432         throw new IllegalStateException("How do you get here?? " + value);
15433     }
15434 
15435     /**
15436      * The visual x position of this view, in pixels. This is equivalent to the
15437      * {@link #setTranslationX(float) translationX} property plus the current
15438      * {@link #getLeft() left} property.
15439      *
15440      * @return The visual x position of this view, in pixels.
15441      */
15442     @ViewDebug.ExportedProperty(category = "drawing")
getX()15443     public float getX() {
15444         return mLeft + getTranslationX();
15445     }
15446 
15447     /**
15448      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
15449      * {@link #setTranslationX(float) translationX} property to be the difference between
15450      * the x value passed in and the current {@link #getLeft() left} property.
15451      *
15452      * @param x The visual x position of this view, in pixels.
15453      */
setX(float x)15454     public void setX(float x) {
15455         setTranslationX(x - mLeft);
15456     }
15457 
15458     /**
15459      * The visual y position of this view, in pixels. This is equivalent to the
15460      * {@link #setTranslationY(float) translationY} property plus the current
15461      * {@link #getTop() top} property.
15462      *
15463      * @return The visual y position of this view, in pixels.
15464      */
15465     @ViewDebug.ExportedProperty(category = "drawing")
getY()15466     public float getY() {
15467         return mTop + getTranslationY();
15468     }
15469 
15470     /**
15471      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
15472      * {@link #setTranslationY(float) translationY} property to be the difference between
15473      * the y value passed in and the current {@link #getTop() top} property.
15474      *
15475      * @param y The visual y position of this view, in pixels.
15476      */
setY(float y)15477     public void setY(float y) {
15478         setTranslationY(y - mTop);
15479     }
15480 
15481     /**
15482      * The visual z position of this view, in pixels. This is equivalent to the
15483      * {@link #setTranslationZ(float) translationZ} property plus the current
15484      * {@link #getElevation() elevation} property.
15485      *
15486      * @return The visual z position of this view, in pixels.
15487      */
15488     @ViewDebug.ExportedProperty(category = "drawing")
getZ()15489     public float getZ() {
15490         return getElevation() + getTranslationZ();
15491     }
15492 
15493     /**
15494      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
15495      * {@link #setTranslationZ(float) translationZ} property to be the difference between
15496      * the x value passed in and the current {@link #getElevation() elevation} property.
15497      *
15498      * @param z The visual z position of this view, in pixels.
15499      */
setZ(float z)15500     public void setZ(float z) {
15501         setTranslationZ(z - getElevation());
15502     }
15503 
15504     /**
15505      * The base elevation of this view relative to its parent, in pixels.
15506      *
15507      * @return The base depth position of the view, in pixels.
15508      */
15509     @ViewDebug.ExportedProperty(category = "drawing")
getElevation()15510     public float getElevation() {
15511         return mRenderNode.getElevation();
15512     }
15513 
15514     /**
15515      * Sets the base elevation of this view, in pixels.
15516      *
15517      * @attr ref android.R.styleable#View_elevation
15518      */
setElevation(float elevation)15519     public void setElevation(float elevation) {
15520         if (elevation != getElevation()) {
15521             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
15522             invalidateViewProperty(true, false);
15523             mRenderNode.setElevation(elevation);
15524             invalidateViewProperty(false, true);
15525 
15526             invalidateParentIfNeededAndWasQuickRejected();
15527         }
15528     }
15529 
15530     /**
15531      * The horizontal location of this view relative to its {@link #getLeft() left} position.
15532      * This position is post-layout, in addition to wherever the object's
15533      * layout placed it.
15534      *
15535      * @return The horizontal position of this view relative to its left position, in pixels.
15536      */
15537     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationX()15538     public float getTranslationX() {
15539         return mRenderNode.getTranslationX();
15540     }
15541 
15542     /**
15543      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
15544      * This effectively positions the object post-layout, in addition to wherever the object's
15545      * layout placed it.
15546      *
15547      * @param translationX The horizontal position of this view relative to its left position,
15548      * in pixels.
15549      *
15550      * @attr ref android.R.styleable#View_translationX
15551      */
setTranslationX(float translationX)15552     public void setTranslationX(float translationX) {
15553         if (translationX != getTranslationX()) {
15554             invalidateViewProperty(true, false);
15555             mRenderNode.setTranslationX(translationX);
15556             invalidateViewProperty(false, true);
15557 
15558             invalidateParentIfNeededAndWasQuickRejected();
15559             notifySubtreeAccessibilityStateChangedIfNeeded();
15560         }
15561     }
15562 
15563     /**
15564      * The vertical location of this view relative to its {@link #getTop() top} position.
15565      * This position is post-layout, in addition to wherever the object's
15566      * layout placed it.
15567      *
15568      * @return The vertical position of this view relative to its top position,
15569      * in pixels.
15570      */
15571     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationY()15572     public float getTranslationY() {
15573         return mRenderNode.getTranslationY();
15574     }
15575 
15576     /**
15577      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
15578      * This effectively positions the object post-layout, in addition to wherever the object's
15579      * layout placed it.
15580      *
15581      * @param translationY The vertical position of this view relative to its top position,
15582      * in pixels.
15583      *
15584      * @attr ref android.R.styleable#View_translationY
15585      */
setTranslationY(float translationY)15586     public void setTranslationY(float translationY) {
15587         if (translationY != getTranslationY()) {
15588             invalidateViewProperty(true, false);
15589             mRenderNode.setTranslationY(translationY);
15590             invalidateViewProperty(false, true);
15591 
15592             invalidateParentIfNeededAndWasQuickRejected();
15593             notifySubtreeAccessibilityStateChangedIfNeeded();
15594         }
15595     }
15596 
15597     /**
15598      * The depth location of this view relative to its {@link #getElevation() elevation}.
15599      *
15600      * @return The depth of this view relative to its elevation.
15601      */
15602     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationZ()15603     public float getTranslationZ() {
15604         return mRenderNode.getTranslationZ();
15605     }
15606 
15607     /**
15608      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
15609      *
15610      * @attr ref android.R.styleable#View_translationZ
15611      */
setTranslationZ(float translationZ)15612     public void setTranslationZ(float translationZ) {
15613         if (translationZ != getTranslationZ()) {
15614             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
15615             invalidateViewProperty(true, false);
15616             mRenderNode.setTranslationZ(translationZ);
15617             invalidateViewProperty(false, true);
15618 
15619             invalidateParentIfNeededAndWasQuickRejected();
15620         }
15621     }
15622 
15623     /** @hide */
setAnimationMatrix(Matrix matrix)15624     public void setAnimationMatrix(Matrix matrix) {
15625         invalidateViewProperty(true, false);
15626         mRenderNode.setAnimationMatrix(matrix);
15627         invalidateViewProperty(false, true);
15628 
15629         invalidateParentIfNeededAndWasQuickRejected();
15630     }
15631 
15632     /**
15633      * Returns the current StateListAnimator if exists.
15634      *
15635      * @return StateListAnimator or null if it does not exists
15636      * @see    #setStateListAnimator(android.animation.StateListAnimator)
15637      */
getStateListAnimator()15638     public StateListAnimator getStateListAnimator() {
15639         return mStateListAnimator;
15640     }
15641 
15642     /**
15643      * Attaches the provided StateListAnimator to this View.
15644      * <p>
15645      * Any previously attached StateListAnimator will be detached.
15646      *
15647      * @param stateListAnimator The StateListAnimator to update the view
15648      * @see android.animation.StateListAnimator
15649      */
setStateListAnimator(StateListAnimator stateListAnimator)15650     public void setStateListAnimator(StateListAnimator stateListAnimator) {
15651         if (mStateListAnimator == stateListAnimator) {
15652             return;
15653         }
15654         if (mStateListAnimator != null) {
15655             mStateListAnimator.setTarget(null);
15656         }
15657         mStateListAnimator = stateListAnimator;
15658         if (stateListAnimator != null) {
15659             stateListAnimator.setTarget(this);
15660             if (isAttachedToWindow()) {
15661                 stateListAnimator.setState(getDrawableState());
15662             }
15663         }
15664     }
15665 
15666     /**
15667      * Returns whether the Outline should be used to clip the contents of the View.
15668      * <p>
15669      * Note that this flag will only be respected if the View's Outline returns true from
15670      * {@link Outline#canClip()}.
15671      *
15672      * @see #setOutlineProvider(ViewOutlineProvider)
15673      * @see #setClipToOutline(boolean)
15674      */
getClipToOutline()15675     public final boolean getClipToOutline() {
15676         return mRenderNode.getClipToOutline();
15677     }
15678 
15679     /**
15680      * Sets whether the View's Outline should be used to clip the contents of the View.
15681      * <p>
15682      * Only a single non-rectangular clip can be applied on a View at any time.
15683      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
15684      * circular reveal} animation take priority over Outline clipping, and
15685      * child Outline clipping takes priority over Outline clipping done by a
15686      * parent.
15687      * <p>
15688      * Note that this flag will only be respected if the View's Outline returns true from
15689      * {@link Outline#canClip()}.
15690      *
15691      * @see #setOutlineProvider(ViewOutlineProvider)
15692      * @see #getClipToOutline()
15693      */
setClipToOutline(boolean clipToOutline)15694     public void setClipToOutline(boolean clipToOutline) {
15695         damageInParent();
15696         if (getClipToOutline() != clipToOutline) {
15697             mRenderNode.setClipToOutline(clipToOutline);
15698         }
15699     }
15700 
15701     // correspond to the enum values of View_outlineProvider
15702     private static final int PROVIDER_BACKGROUND = 0;
15703     private static final int PROVIDER_NONE = 1;
15704     private static final int PROVIDER_BOUNDS = 2;
15705     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)15706     private void setOutlineProviderFromAttribute(int providerInt) {
15707         switch (providerInt) {
15708             case PROVIDER_BACKGROUND:
15709                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
15710                 break;
15711             case PROVIDER_NONE:
15712                 setOutlineProvider(null);
15713                 break;
15714             case PROVIDER_BOUNDS:
15715                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
15716                 break;
15717             case PROVIDER_PADDED_BOUNDS:
15718                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
15719                 break;
15720         }
15721     }
15722 
15723     /**
15724      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
15725      * the shape of the shadow it casts, and enables outline clipping.
15726      * <p>
15727      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
15728      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
15729      * outline provider with this method allows this behavior to be overridden.
15730      * <p>
15731      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
15732      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
15733      * <p>
15734      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
15735      *
15736      * @see #setClipToOutline(boolean)
15737      * @see #getClipToOutline()
15738      * @see #getOutlineProvider()
15739      */
setOutlineProvider(ViewOutlineProvider provider)15740     public void setOutlineProvider(ViewOutlineProvider provider) {
15741         mOutlineProvider = provider;
15742         invalidateOutline();
15743     }
15744 
15745     /**
15746      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
15747      * that defines the shape of the shadow it casts, and enables outline clipping.
15748      *
15749      * @see #setOutlineProvider(ViewOutlineProvider)
15750      */
getOutlineProvider()15751     public ViewOutlineProvider getOutlineProvider() {
15752         return mOutlineProvider;
15753     }
15754 
15755     /**
15756      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
15757      *
15758      * @see #setOutlineProvider(ViewOutlineProvider)
15759      */
invalidateOutline()15760     public void invalidateOutline() {
15761         rebuildOutline();
15762 
15763         notifySubtreeAccessibilityStateChangedIfNeeded();
15764         invalidateViewProperty(false, false);
15765     }
15766 
15767     /**
15768      * Internal version of {@link #invalidateOutline()} which invalidates the
15769      * outline without invalidating the view itself. This is intended to be called from
15770      * within methods in the View class itself which are the result of the view being
15771      * invalidated already. For example, when we are drawing the background of a View,
15772      * we invalidate the outline in case it changed in the meantime, but we do not
15773      * need to invalidate the view because we're already drawing the background as part
15774      * of drawing the view in response to an earlier invalidation of the view.
15775      */
rebuildOutline()15776     private void rebuildOutline() {
15777         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
15778         if (mAttachInfo == null) return;
15779 
15780         if (mOutlineProvider == null) {
15781             // no provider, remove outline
15782             mRenderNode.setOutline(null);
15783         } else {
15784             final Outline outline = mAttachInfo.mTmpOutline;
15785             outline.setEmpty();
15786             outline.setAlpha(1.0f);
15787 
15788             mOutlineProvider.getOutline(this, outline);
15789             mRenderNode.setOutline(outline);
15790         }
15791     }
15792 
15793     /**
15794      * HierarchyViewer only
15795      *
15796      * @hide
15797      */
15798     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()15799     public boolean hasShadow() {
15800         return mRenderNode.hasShadow();
15801     }
15802 
15803     /**
15804      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
15805      * elevation value.
15806      * <p>
15807      * By default the shadow color is black. Generally, this color will be opaque so the intensity
15808      * of the shadow is consistent between different views with different colors.
15809      * <p>
15810      * The opacity of the final spot shadow is a function of the shadow caster height, the
15811      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
15812      * {@link android.R.attr#spotShadowAlpha} theme attribute.
15813      *
15814      * @attr ref android.R.styleable#View_outlineSpotShadowColor
15815      * @param color The color this View will cast for its elevation spot shadow.
15816      */
setOutlineSpotShadowColor(@olorInt int color)15817     public void setOutlineSpotShadowColor(@ColorInt int color) {
15818         if (mRenderNode.setSpotShadowColor(color)) {
15819             invalidateViewProperty(true, true);
15820         }
15821     }
15822 
15823     /**
15824      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
15825      * was set
15826      */
getOutlineSpotShadowColor()15827     public @ColorInt int getOutlineSpotShadowColor() {
15828         return mRenderNode.getSpotShadowColor();
15829     }
15830 
15831     /**
15832      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
15833      * elevation value.
15834      * <p>
15835      * By default the shadow color is black. Generally, this color will be opaque so the intensity
15836      * of the shadow is consistent between different views with different colors.
15837      * <p>
15838      * The opacity of the final ambient shadow is a function of the shadow caster height, the
15839      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
15840      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
15841      *
15842      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
15843      * @param color The color this View will cast for its elevation shadow.
15844      */
setOutlineAmbientShadowColor(@olorInt int color)15845     public void setOutlineAmbientShadowColor(@ColorInt int color) {
15846         if (mRenderNode.setAmbientShadowColor(color)) {
15847             invalidateViewProperty(true, true);
15848         }
15849     }
15850 
15851     /**
15852      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
15853      * nothing was set
15854      */
getOutlineAmbientShadowColor()15855     public @ColorInt int getOutlineAmbientShadowColor() {
15856         return mRenderNode.getAmbientShadowColor();
15857     }
15858 
15859 
15860     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)15861     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
15862         mRenderNode.setRevealClip(shouldClip, x, y, radius);
15863         invalidateViewProperty(false, false);
15864     }
15865 
15866     /**
15867      * Hit rectangle in parent's coordinates
15868      *
15869      * @param outRect The hit rectangle of the view.
15870      */
getHitRect(Rect outRect)15871     public void getHitRect(Rect outRect) {
15872         if (hasIdentityMatrix() || mAttachInfo == null) {
15873             outRect.set(mLeft, mTop, mRight, mBottom);
15874         } else {
15875             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
15876             tmpRect.set(0, 0, getWidth(), getHeight());
15877             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
15878             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
15879                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
15880         }
15881     }
15882 
15883     /**
15884      * Determines whether the given point, in local coordinates is inside the view.
15885      */
pointInView(float localX, float localY)15886     /*package*/ final boolean pointInView(float localX, float localY) {
15887         return pointInView(localX, localY, 0);
15888     }
15889 
15890     /**
15891      * Utility method to determine whether the given point, in local coordinates,
15892      * is inside the view, where the area of the view is expanded by the slop factor.
15893      * This method is called while processing touch-move events to determine if the event
15894      * is still within the view.
15895      *
15896      * @hide
15897      */
pointInView(float localX, float localY, float slop)15898     public boolean pointInView(float localX, float localY, float slop) {
15899         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
15900                 localY < ((mBottom - mTop) + slop);
15901     }
15902 
15903     /**
15904      * When a view has focus and the user navigates away from it, the next view is searched for
15905      * starting from the rectangle filled in by this method.
15906      *
15907      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
15908      * of the view.  However, if your view maintains some idea of internal selection,
15909      * such as a cursor, or a selected row or column, you should override this method and
15910      * fill in a more specific rectangle.
15911      *
15912      * @param r The rectangle to fill in, in this view's coordinates.
15913      */
getFocusedRect(Rect r)15914     public void getFocusedRect(Rect r) {
15915         getDrawingRect(r);
15916     }
15917 
15918     /**
15919      * If some part of this view is not clipped by any of its parents, then
15920      * return that area in r in global (root) coordinates. To convert r to local
15921      * coordinates (without taking possible View rotations into account), offset
15922      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
15923      * If the view is completely clipped or translated out, return false.
15924      *
15925      * @param r If true is returned, r holds the global coordinates of the
15926      *        visible portion of this view.
15927      * @param globalOffset If true is returned, globalOffset holds the dx,dy
15928      *        between this view and its root. globalOffet may be null.
15929      * @return true if r is non-empty (i.e. part of the view is visible at the
15930      *         root level.
15931      */
getGlobalVisibleRect(Rect r, Point globalOffset)15932     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
15933         int width = mRight - mLeft;
15934         int height = mBottom - mTop;
15935         if (width > 0 && height > 0) {
15936             r.set(0, 0, width, height);
15937             if (globalOffset != null) {
15938                 globalOffset.set(-mScrollX, -mScrollY);
15939             }
15940             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
15941         }
15942         return false;
15943     }
15944 
getGlobalVisibleRect(Rect r)15945     public final boolean getGlobalVisibleRect(Rect r) {
15946         return getGlobalVisibleRect(r, null);
15947     }
15948 
getLocalVisibleRect(Rect r)15949     public final boolean getLocalVisibleRect(Rect r) {
15950         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
15951         if (getGlobalVisibleRect(r, offset)) {
15952             r.offset(-offset.x, -offset.y); // make r local
15953             return true;
15954         }
15955         return false;
15956     }
15957 
15958     /**
15959      * Offset this view's vertical location by the specified number of pixels.
15960      *
15961      * @param offset the number of pixels to offset the view by
15962      */
offsetTopAndBottom(int offset)15963     public void offsetTopAndBottom(int offset) {
15964         if (offset != 0) {
15965             final boolean matrixIsIdentity = hasIdentityMatrix();
15966             if (matrixIsIdentity) {
15967                 if (isHardwareAccelerated()) {
15968                     invalidateViewProperty(false, false);
15969                 } else {
15970                     final ViewParent p = mParent;
15971                     if (p != null && mAttachInfo != null) {
15972                         final Rect r = mAttachInfo.mTmpInvalRect;
15973                         int minTop;
15974                         int maxBottom;
15975                         int yLoc;
15976                         if (offset < 0) {
15977                             minTop = mTop + offset;
15978                             maxBottom = mBottom;
15979                             yLoc = offset;
15980                         } else {
15981                             minTop = mTop;
15982                             maxBottom = mBottom + offset;
15983                             yLoc = 0;
15984                         }
15985                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
15986                         p.invalidateChild(this, r);
15987                     }
15988                 }
15989             } else {
15990                 invalidateViewProperty(false, false);
15991             }
15992 
15993             mTop += offset;
15994             mBottom += offset;
15995             mRenderNode.offsetTopAndBottom(offset);
15996             if (isHardwareAccelerated()) {
15997                 invalidateViewProperty(false, false);
15998                 invalidateParentIfNeededAndWasQuickRejected();
15999             } else {
16000                 if (!matrixIsIdentity) {
16001                     invalidateViewProperty(false, true);
16002                 }
16003                 invalidateParentIfNeeded();
16004             }
16005             notifySubtreeAccessibilityStateChangedIfNeeded();
16006         }
16007     }
16008 
16009     /**
16010      * Offset this view's horizontal location by the specified amount of pixels.
16011      *
16012      * @param offset the number of pixels to offset the view by
16013      */
offsetLeftAndRight(int offset)16014     public void offsetLeftAndRight(int offset) {
16015         if (offset != 0) {
16016             final boolean matrixIsIdentity = hasIdentityMatrix();
16017             if (matrixIsIdentity) {
16018                 if (isHardwareAccelerated()) {
16019                     invalidateViewProperty(false, false);
16020                 } else {
16021                     final ViewParent p = mParent;
16022                     if (p != null && mAttachInfo != null) {
16023                         final Rect r = mAttachInfo.mTmpInvalRect;
16024                         int minLeft;
16025                         int maxRight;
16026                         if (offset < 0) {
16027                             minLeft = mLeft + offset;
16028                             maxRight = mRight;
16029                         } else {
16030                             minLeft = mLeft;
16031                             maxRight = mRight + offset;
16032                         }
16033                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
16034                         p.invalidateChild(this, r);
16035                     }
16036                 }
16037             } else {
16038                 invalidateViewProperty(false, false);
16039             }
16040 
16041             mLeft += offset;
16042             mRight += offset;
16043             mRenderNode.offsetLeftAndRight(offset);
16044             if (isHardwareAccelerated()) {
16045                 invalidateViewProperty(false, false);
16046                 invalidateParentIfNeededAndWasQuickRejected();
16047             } else {
16048                 if (!matrixIsIdentity) {
16049                     invalidateViewProperty(false, true);
16050                 }
16051                 invalidateParentIfNeeded();
16052             }
16053             notifySubtreeAccessibilityStateChangedIfNeeded();
16054         }
16055     }
16056 
16057     /**
16058      * Get the LayoutParams associated with this view. All views should have
16059      * layout parameters. These supply parameters to the <i>parent</i> of this
16060      * view specifying how it should be arranged. There are many subclasses of
16061      * ViewGroup.LayoutParams, and these correspond to the different subclasses
16062      * of ViewGroup that are responsible for arranging their children.
16063      *
16064      * This method may return null if this View is not attached to a parent
16065      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
16066      * was not invoked successfully. When a View is attached to a parent
16067      * ViewGroup, this method must not return null.
16068      *
16069      * @return The LayoutParams associated with this view, or null if no
16070      *         parameters have been set yet
16071      */
16072     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()16073     public ViewGroup.LayoutParams getLayoutParams() {
16074         return mLayoutParams;
16075     }
16076 
16077     /**
16078      * Set the layout parameters associated with this view. These supply
16079      * parameters to the <i>parent</i> of this view specifying how it should be
16080      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
16081      * correspond to the different subclasses of ViewGroup that are responsible
16082      * for arranging their children.
16083      *
16084      * @param params The layout parameters for this view, cannot be null
16085      */
setLayoutParams(ViewGroup.LayoutParams params)16086     public void setLayoutParams(ViewGroup.LayoutParams params) {
16087         if (params == null) {
16088             throw new NullPointerException("Layout parameters cannot be null");
16089         }
16090         mLayoutParams = params;
16091         resolveLayoutParams();
16092         if (mParent instanceof ViewGroup) {
16093             ((ViewGroup) mParent).onSetLayoutParams(this, params);
16094         }
16095         requestLayout();
16096     }
16097 
16098     /**
16099      * Resolve the layout parameters depending on the resolved layout direction
16100      *
16101      * @hide
16102      */
resolveLayoutParams()16103     public void resolveLayoutParams() {
16104         if (mLayoutParams != null) {
16105             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
16106         }
16107     }
16108 
16109     /**
16110      * Set the scrolled position of your view. This will cause a call to
16111      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16112      * invalidated.
16113      * @param x the x position to scroll to
16114      * @param y the y position to scroll to
16115      */
scrollTo(int x, int y)16116     public void scrollTo(int x, int y) {
16117         if (mScrollX != x || mScrollY != y) {
16118             int oldX = mScrollX;
16119             int oldY = mScrollY;
16120             mScrollX = x;
16121             mScrollY = y;
16122             invalidateParentCaches();
16123             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
16124             if (!awakenScrollBars()) {
16125                 postInvalidateOnAnimation();
16126             }
16127         }
16128     }
16129 
16130     /**
16131      * Move the scrolled position of your view. This will cause a call to
16132      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16133      * invalidated.
16134      * @param x the amount of pixels to scroll by horizontally
16135      * @param y the amount of pixels to scroll by vertically
16136      */
scrollBy(int x, int y)16137     public void scrollBy(int x, int y) {
16138         scrollTo(mScrollX + x, mScrollY + y);
16139     }
16140 
16141     /**
16142      * <p>Trigger the scrollbars to draw. When invoked this method starts an
16143      * animation to fade the scrollbars out after a default delay. If a subclass
16144      * provides animated scrolling, the start delay should equal the duration
16145      * of the scrolling animation.</p>
16146      *
16147      * <p>The animation starts only if at least one of the scrollbars is
16148      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
16149      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
16150      * this method returns true, and false otherwise. If the animation is
16151      * started, this method calls {@link #invalidate()}; in that case the
16152      * caller should not call {@link #invalidate()}.</p>
16153      *
16154      * <p>This method should be invoked every time a subclass directly updates
16155      * the scroll parameters.</p>
16156      *
16157      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
16158      * and {@link #scrollTo(int, int)}.</p>
16159      *
16160      * @return true if the animation is played, false otherwise
16161      *
16162      * @see #awakenScrollBars(int)
16163      * @see #scrollBy(int, int)
16164      * @see #scrollTo(int, int)
16165      * @see #isHorizontalScrollBarEnabled()
16166      * @see #isVerticalScrollBarEnabled()
16167      * @see #setHorizontalScrollBarEnabled(boolean)
16168      * @see #setVerticalScrollBarEnabled(boolean)
16169      */
awakenScrollBars()16170     protected boolean awakenScrollBars() {
16171         return mScrollCache != null &&
16172                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
16173     }
16174 
16175     /**
16176      * Trigger the scrollbars to draw.
16177      * This method differs from awakenScrollBars() only in its default duration.
16178      * initialAwakenScrollBars() will show the scroll bars for longer than
16179      * usual to give the user more of a chance to notice them.
16180      *
16181      * @return true if the animation is played, false otherwise.
16182      */
initialAwakenScrollBars()16183     private boolean initialAwakenScrollBars() {
16184         return mScrollCache != null &&
16185                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
16186     }
16187 
16188     /**
16189      * <p>
16190      * Trigger the scrollbars to draw. When invoked this method starts an
16191      * animation to fade the scrollbars out after a fixed delay. If a subclass
16192      * provides animated scrolling, the start delay should equal the duration of
16193      * the scrolling animation.
16194      * </p>
16195      *
16196      * <p>
16197      * The animation starts only if at least one of the scrollbars is enabled,
16198      * as specified by {@link #isHorizontalScrollBarEnabled()} and
16199      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
16200      * this method returns true, and false otherwise. If the animation is
16201      * started, this method calls {@link #invalidate()}; in that case the caller
16202      * should not call {@link #invalidate()}.
16203      * </p>
16204      *
16205      * <p>
16206      * This method should be invoked every time a subclass directly updates the
16207      * scroll parameters.
16208      * </p>
16209      *
16210      * @param startDelay the delay, in milliseconds, after which the animation
16211      *        should start; when the delay is 0, the animation starts
16212      *        immediately
16213      * @return true if the animation is played, false otherwise
16214      *
16215      * @see #scrollBy(int, int)
16216      * @see #scrollTo(int, int)
16217      * @see #isHorizontalScrollBarEnabled()
16218      * @see #isVerticalScrollBarEnabled()
16219      * @see #setHorizontalScrollBarEnabled(boolean)
16220      * @see #setVerticalScrollBarEnabled(boolean)
16221      */
awakenScrollBars(int startDelay)16222     protected boolean awakenScrollBars(int startDelay) {
16223         return awakenScrollBars(startDelay, true);
16224     }
16225 
16226     /**
16227      * <p>
16228      * Trigger the scrollbars to draw. When invoked this method starts an
16229      * animation to fade the scrollbars out after a fixed delay. If a subclass
16230      * provides animated scrolling, the start delay should equal the duration of
16231      * the scrolling animation.
16232      * </p>
16233      *
16234      * <p>
16235      * The animation starts only if at least one of the scrollbars is enabled,
16236      * as specified by {@link #isHorizontalScrollBarEnabled()} and
16237      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
16238      * this method returns true, and false otherwise. If the animation is
16239      * started, this method calls {@link #invalidate()} if the invalidate parameter
16240      * is set to true; in that case the caller
16241      * should not call {@link #invalidate()}.
16242      * </p>
16243      *
16244      * <p>
16245      * This method should be invoked every time a subclass directly updates the
16246      * scroll parameters.
16247      * </p>
16248      *
16249      * @param startDelay the delay, in milliseconds, after which the animation
16250      *        should start; when the delay is 0, the animation starts
16251      *        immediately
16252      *
16253      * @param invalidate Whether this method should call invalidate
16254      *
16255      * @return true if the animation is played, false otherwise
16256      *
16257      * @see #scrollBy(int, int)
16258      * @see #scrollTo(int, int)
16259      * @see #isHorizontalScrollBarEnabled()
16260      * @see #isVerticalScrollBarEnabled()
16261      * @see #setHorizontalScrollBarEnabled(boolean)
16262      * @see #setVerticalScrollBarEnabled(boolean)
16263      */
awakenScrollBars(int startDelay, boolean invalidate)16264     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
16265         final ScrollabilityCache scrollCache = mScrollCache;
16266 
16267         if (scrollCache == null || !scrollCache.fadeScrollBars) {
16268             return false;
16269         }
16270 
16271         if (scrollCache.scrollBar == null) {
16272             scrollCache.scrollBar = new ScrollBarDrawable();
16273             scrollCache.scrollBar.setState(getDrawableState());
16274             scrollCache.scrollBar.setCallback(this);
16275         }
16276 
16277         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
16278 
16279             if (invalidate) {
16280                 // Invalidate to show the scrollbars
16281                 postInvalidateOnAnimation();
16282             }
16283 
16284             if (scrollCache.state == ScrollabilityCache.OFF) {
16285                 // FIXME: this is copied from WindowManagerService.
16286                 // We should get this value from the system when it
16287                 // is possible to do so.
16288                 final int KEY_REPEAT_FIRST_DELAY = 750;
16289                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
16290             }
16291 
16292             // Tell mScrollCache when we should start fading. This may
16293             // extend the fade start time if one was already scheduled
16294             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
16295             scrollCache.fadeStartTime = fadeStartTime;
16296             scrollCache.state = ScrollabilityCache.ON;
16297 
16298             // Schedule our fader to run, unscheduling any old ones first
16299             if (mAttachInfo != null) {
16300                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
16301                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
16302             }
16303 
16304             return true;
16305         }
16306 
16307         return false;
16308     }
16309 
16310     /**
16311      * Do not invalidate views which are not visible and which are not running an animation. They
16312      * will not get drawn and they should not set dirty flags as if they will be drawn
16313      */
skipInvalidate()16314     private boolean skipInvalidate() {
16315         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
16316                 (!(mParent instanceof ViewGroup) ||
16317                         !((ViewGroup) mParent).isViewTransitioning(this));
16318     }
16319 
16320     /**
16321      * Mark the area defined by dirty as needing to be drawn. If the view is
16322      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
16323      * point in the future.
16324      * <p>
16325      * This must be called from a UI thread. To call from a non-UI thread, call
16326      * {@link #postInvalidate()}.
16327      * <p>
16328      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
16329      * {@code dirty}.
16330      *
16331      * @param dirty the rectangle representing the bounds of the dirty region
16332      *
16333      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
16334      * the importance of the dirty rectangle. In API 21 the given rectangle is
16335      * ignored entirely in favor of an internally-calculated area instead.
16336      * Because of this, clients are encouraged to just call {@link #invalidate()}.
16337      */
16338     @Deprecated
invalidate(Rect dirty)16339     public void invalidate(Rect dirty) {
16340         final int scrollX = mScrollX;
16341         final int scrollY = mScrollY;
16342         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
16343                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
16344     }
16345 
16346     /**
16347      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
16348      * coordinates of the dirty rect are relative to the view. If the view is
16349      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
16350      * point in the future.
16351      * <p>
16352      * This must be called from a UI thread. To call from a non-UI thread, call
16353      * {@link #postInvalidate()}.
16354      *
16355      * @param l the left position of the dirty region
16356      * @param t the top position of the dirty region
16357      * @param r the right position of the dirty region
16358      * @param b the bottom position of the dirty region
16359      *
16360      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
16361      * the importance of the dirty rectangle. In API 21 the given rectangle is
16362      * ignored entirely in favor of an internally-calculated area instead.
16363      * Because of this, clients are encouraged to just call {@link #invalidate()}.
16364      */
16365     @Deprecated
invalidate(int l, int t, int r, int b)16366     public void invalidate(int l, int t, int r, int b) {
16367         final int scrollX = mScrollX;
16368         final int scrollY = mScrollY;
16369         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
16370     }
16371 
16372     /**
16373      * Invalidate the whole view. If the view is visible,
16374      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
16375      * the future.
16376      * <p>
16377      * This must be called from a UI thread. To call from a non-UI thread, call
16378      * {@link #postInvalidate()}.
16379      */
invalidate()16380     public void invalidate() {
16381         invalidate(true);
16382     }
16383 
16384     /**
16385      * This is where the invalidate() work actually happens. A full invalidate()
16386      * causes the drawing cache to be invalidated, but this function can be
16387      * called with invalidateCache set to false to skip that invalidation step
16388      * for cases that do not need it (for example, a component that remains at
16389      * the same dimensions with the same content).
16390      *
16391      * @param invalidateCache Whether the drawing cache for this view should be
16392      *            invalidated as well. This is usually true for a full
16393      *            invalidate, but may be set to false if the View's contents or
16394      *            dimensions have not changed.
16395      * @hide
16396      */
invalidate(boolean invalidateCache)16397     public void invalidate(boolean invalidateCache) {
16398         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
16399     }
16400 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)16401     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
16402             boolean fullInvalidate) {
16403         if (mGhostView != null) {
16404             mGhostView.invalidate(true);
16405             return;
16406         }
16407 
16408         if (skipInvalidate()) {
16409             return;
16410         }
16411 
16412         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
16413                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
16414                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
16415                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
16416             if (fullInvalidate) {
16417                 mLastIsOpaque = isOpaque();
16418                 mPrivateFlags &= ~PFLAG_DRAWN;
16419             }
16420 
16421             mPrivateFlags |= PFLAG_DIRTY;
16422 
16423             if (invalidateCache) {
16424                 mPrivateFlags |= PFLAG_INVALIDATED;
16425                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16426             }
16427 
16428             // Propagate the damage rectangle to the parent view.
16429             final AttachInfo ai = mAttachInfo;
16430             final ViewParent p = mParent;
16431             if (p != null && ai != null && l < r && t < b) {
16432                 final Rect damage = ai.mTmpInvalRect;
16433                 damage.set(l, t, r, b);
16434                 p.invalidateChild(this, damage);
16435             }
16436 
16437             // Damage the entire projection receiver, if necessary.
16438             if (mBackground != null && mBackground.isProjected()) {
16439                 final View receiver = getProjectionReceiver();
16440                 if (receiver != null) {
16441                     receiver.damageInParent();
16442                 }
16443             }
16444         }
16445     }
16446 
16447     /**
16448      * @return this view's projection receiver, or {@code null} if none exists
16449      */
getProjectionReceiver()16450     private View getProjectionReceiver() {
16451         ViewParent p = getParent();
16452         while (p != null && p instanceof View) {
16453             final View v = (View) p;
16454             if (v.isProjectionReceiver()) {
16455                 return v;
16456             }
16457             p = p.getParent();
16458         }
16459 
16460         return null;
16461     }
16462 
16463     /**
16464      * @return whether the view is a projection receiver
16465      */
isProjectionReceiver()16466     private boolean isProjectionReceiver() {
16467         return mBackground != null;
16468     }
16469 
16470     /**
16471      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
16472      * set any flags or handle all of the cases handled by the default invalidation methods.
16473      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
16474      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
16475      * walk up the hierarchy, transforming the dirty rect as necessary.
16476      *
16477      * The method also handles normal invalidation logic if display list properties are not
16478      * being used in this view. The invalidateParent and forceRedraw flags are used by that
16479      * backup approach, to handle these cases used in the various property-setting methods.
16480      *
16481      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
16482      * are not being used in this view
16483      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
16484      * list properties are not being used in this view
16485      */
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)16486     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
16487         if (!isHardwareAccelerated()
16488                 || !mRenderNode.isValid()
16489                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
16490             if (invalidateParent) {
16491                 invalidateParentCaches();
16492             }
16493             if (forceRedraw) {
16494                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
16495             }
16496             invalidate(false);
16497         } else {
16498             damageInParent();
16499         }
16500     }
16501 
16502     /**
16503      * Tells the parent view to damage this view's bounds.
16504      *
16505      * @hide
16506      */
damageInParent()16507     protected void damageInParent() {
16508         if (mParent != null && mAttachInfo != null) {
16509             mParent.onDescendantInvalidated(this, this);
16510         }
16511     }
16512 
16513     /**
16514      * Utility method to transform a given Rect by the current matrix of this view.
16515      */
transformRect(final Rect rect)16516     void transformRect(final Rect rect) {
16517         if (!getMatrix().isIdentity()) {
16518             RectF boundingRect = mAttachInfo.mTmpTransformRect;
16519             boundingRect.set(rect);
16520             getMatrix().mapRect(boundingRect);
16521             rect.set((int) Math.floor(boundingRect.left),
16522                     (int) Math.floor(boundingRect.top),
16523                     (int) Math.ceil(boundingRect.right),
16524                     (int) Math.ceil(boundingRect.bottom));
16525         }
16526     }
16527 
16528     /**
16529      * Used to indicate that the parent of this view should clear its caches. This functionality
16530      * is used to force the parent to rebuild its display list (when hardware-accelerated),
16531      * which is necessary when various parent-managed properties of the view change, such as
16532      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
16533      * clears the parent caches and does not causes an invalidate event.
16534      *
16535      * @hide
16536      */
invalidateParentCaches()16537     protected void invalidateParentCaches() {
16538         if (mParent instanceof View) {
16539             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
16540         }
16541     }
16542 
16543     /**
16544      * Used to indicate that the parent of this view should be invalidated. This functionality
16545      * is used to force the parent to rebuild its display list (when hardware-accelerated),
16546      * which is necessary when various parent-managed properties of the view change, such as
16547      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
16548      * an invalidation event to the parent.
16549      *
16550      * @hide
16551      */
invalidateParentIfNeeded()16552     protected void invalidateParentIfNeeded() {
16553         if (isHardwareAccelerated() && mParent instanceof View) {
16554             ((View) mParent).invalidate(true);
16555         }
16556     }
16557 
16558     /**
16559      * @hide
16560      */
invalidateParentIfNeededAndWasQuickRejected()16561     protected void invalidateParentIfNeededAndWasQuickRejected() {
16562         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
16563             // View was rejected last time it was drawn by its parent; this may have changed
16564             invalidateParentIfNeeded();
16565         }
16566     }
16567 
16568     /**
16569      * Indicates whether this View is opaque. An opaque View guarantees that it will
16570      * draw all the pixels overlapping its bounds using a fully opaque color.
16571      *
16572      * Subclasses of View should override this method whenever possible to indicate
16573      * whether an instance is opaque. Opaque Views are treated in a special way by
16574      * the View hierarchy, possibly allowing it to perform optimizations during
16575      * invalidate/draw passes.
16576      *
16577      * @return True if this View is guaranteed to be fully opaque, false otherwise.
16578      */
16579     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()16580     public boolean isOpaque() {
16581         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
16582                 getFinalAlpha() >= 1.0f;
16583     }
16584 
16585     /**
16586      * @hide
16587      */
computeOpaqueFlags()16588     protected void computeOpaqueFlags() {
16589         // Opaque if:
16590         //   - Has a background
16591         //   - Background is opaque
16592         //   - Doesn't have scrollbars or scrollbars overlay
16593 
16594         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
16595             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
16596         } else {
16597             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
16598         }
16599 
16600         final int flags = mViewFlags;
16601         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
16602                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
16603                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
16604             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
16605         } else {
16606             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
16607         }
16608     }
16609 
16610     /**
16611      * @hide
16612      */
hasOpaqueScrollbars()16613     protected boolean hasOpaqueScrollbars() {
16614         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
16615     }
16616 
16617     /**
16618      * @return A handler associated with the thread running the View. This
16619      * handler can be used to pump events in the UI events queue.
16620      */
getHandler()16621     public Handler getHandler() {
16622         final AttachInfo attachInfo = mAttachInfo;
16623         if (attachInfo != null) {
16624             return attachInfo.mHandler;
16625         }
16626         return null;
16627     }
16628 
16629     /**
16630      * Returns the queue of runnable for this view.
16631      *
16632      * @return the queue of runnables for this view
16633      */
getRunQueue()16634     private HandlerActionQueue getRunQueue() {
16635         if (mRunQueue == null) {
16636             mRunQueue = new HandlerActionQueue();
16637         }
16638         return mRunQueue;
16639     }
16640 
16641     /**
16642      * Gets the view root associated with the View.
16643      * @return The view root, or null if none.
16644      * @hide
16645      */
getViewRootImpl()16646     public ViewRootImpl getViewRootImpl() {
16647         if (mAttachInfo != null) {
16648             return mAttachInfo.mViewRootImpl;
16649         }
16650         return null;
16651     }
16652 
16653     /**
16654      * @hide
16655      */
getThreadedRenderer()16656     public ThreadedRenderer getThreadedRenderer() {
16657         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
16658     }
16659 
16660     /**
16661      * <p>Causes the Runnable to be added to the message queue.
16662      * The runnable will be run on the user interface thread.</p>
16663      *
16664      * @param action The Runnable that will be executed.
16665      *
16666      * @return Returns true if the Runnable was successfully placed in to the
16667      *         message queue.  Returns false on failure, usually because the
16668      *         looper processing the message queue is exiting.
16669      *
16670      * @see #postDelayed
16671      * @see #removeCallbacks
16672      */
post(Runnable action)16673     public boolean post(Runnable action) {
16674         final AttachInfo attachInfo = mAttachInfo;
16675         if (attachInfo != null) {
16676             return attachInfo.mHandler.post(action);
16677         }
16678 
16679         // Postpone the runnable until we know on which thread it needs to run.
16680         // Assume that the runnable will be successfully placed after attach.
16681         getRunQueue().post(action);
16682         return true;
16683     }
16684 
16685     /**
16686      * <p>Causes the Runnable to be added to the message queue, to be run
16687      * after the specified amount of time elapses.
16688      * The runnable will be run on the user interface thread.</p>
16689      *
16690      * @param action The Runnable that will be executed.
16691      * @param delayMillis The delay (in milliseconds) until the Runnable
16692      *        will be executed.
16693      *
16694      * @return true if the Runnable was successfully placed in to the
16695      *         message queue.  Returns false on failure, usually because the
16696      *         looper processing the message queue is exiting.  Note that a
16697      *         result of true does not mean the Runnable will be processed --
16698      *         if the looper is quit before the delivery time of the message
16699      *         occurs then the message will be dropped.
16700      *
16701      * @see #post
16702      * @see #removeCallbacks
16703      */
postDelayed(Runnable action, long delayMillis)16704     public boolean postDelayed(Runnable action, long delayMillis) {
16705         final AttachInfo attachInfo = mAttachInfo;
16706         if (attachInfo != null) {
16707             return attachInfo.mHandler.postDelayed(action, delayMillis);
16708         }
16709 
16710         // Postpone the runnable until we know on which thread it needs to run.
16711         // Assume that the runnable will be successfully placed after attach.
16712         getRunQueue().postDelayed(action, delayMillis);
16713         return true;
16714     }
16715 
16716     /**
16717      * <p>Causes the Runnable to execute on the next animation time step.
16718      * The runnable will be run on the user interface thread.</p>
16719      *
16720      * @param action The Runnable that will be executed.
16721      *
16722      * @see #postOnAnimationDelayed
16723      * @see #removeCallbacks
16724      */
postOnAnimation(Runnable action)16725     public void postOnAnimation(Runnable action) {
16726         final AttachInfo attachInfo = mAttachInfo;
16727         if (attachInfo != null) {
16728             attachInfo.mViewRootImpl.mChoreographer.postCallback(
16729                     Choreographer.CALLBACK_ANIMATION, action, null);
16730         } else {
16731             // Postpone the runnable until we know
16732             // on which thread it needs to run.
16733             getRunQueue().post(action);
16734         }
16735     }
16736 
16737     /**
16738      * <p>Causes the Runnable to execute on the next animation time step,
16739      * after the specified amount of time elapses.
16740      * The runnable will be run on the user interface thread.</p>
16741      *
16742      * @param action The Runnable that will be executed.
16743      * @param delayMillis The delay (in milliseconds) until the Runnable
16744      *        will be executed.
16745      *
16746      * @see #postOnAnimation
16747      * @see #removeCallbacks
16748      */
postOnAnimationDelayed(Runnable action, long delayMillis)16749     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
16750         final AttachInfo attachInfo = mAttachInfo;
16751         if (attachInfo != null) {
16752             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16753                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
16754         } else {
16755             // Postpone the runnable until we know
16756             // on which thread it needs to run.
16757             getRunQueue().postDelayed(action, delayMillis);
16758         }
16759     }
16760 
16761     /**
16762      * <p>Removes the specified Runnable from the message queue.</p>
16763      *
16764      * @param action The Runnable to remove from the message handling queue
16765      *
16766      * @return true if this view could ask the Handler to remove the Runnable,
16767      *         false otherwise. When the returned value is true, the Runnable
16768      *         may or may not have been actually removed from the message queue
16769      *         (for instance, if the Runnable was not in the queue already.)
16770      *
16771      * @see #post
16772      * @see #postDelayed
16773      * @see #postOnAnimation
16774      * @see #postOnAnimationDelayed
16775      */
removeCallbacks(Runnable action)16776     public boolean removeCallbacks(Runnable action) {
16777         if (action != null) {
16778             final AttachInfo attachInfo = mAttachInfo;
16779             if (attachInfo != null) {
16780                 attachInfo.mHandler.removeCallbacks(action);
16781                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16782                         Choreographer.CALLBACK_ANIMATION, action, null);
16783             }
16784             getRunQueue().removeCallbacks(action);
16785         }
16786         return true;
16787     }
16788 
16789     /**
16790      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
16791      * Use this to invalidate the View from a non-UI thread.</p>
16792      *
16793      * <p>This method can be invoked from outside of the UI thread
16794      * only when this View is attached to a window.</p>
16795      *
16796      * @see #invalidate()
16797      * @see #postInvalidateDelayed(long)
16798      */
postInvalidate()16799     public void postInvalidate() {
16800         postInvalidateDelayed(0);
16801     }
16802 
16803     /**
16804      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
16805      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
16806      *
16807      * <p>This method can be invoked from outside of the UI thread
16808      * only when this View is attached to a window.</p>
16809      *
16810      * @param left The left coordinate of the rectangle to invalidate.
16811      * @param top The top coordinate of the rectangle to invalidate.
16812      * @param right The right coordinate of the rectangle to invalidate.
16813      * @param bottom The bottom coordinate of the rectangle to invalidate.
16814      *
16815      * @see #invalidate(int, int, int, int)
16816      * @see #invalidate(Rect)
16817      * @see #postInvalidateDelayed(long, int, int, int, int)
16818      */
postInvalidate(int left, int top, int right, int bottom)16819     public void postInvalidate(int left, int top, int right, int bottom) {
16820         postInvalidateDelayed(0, left, top, right, bottom);
16821     }
16822 
16823     /**
16824      * <p>Cause an invalidate to happen on a subsequent cycle through the event
16825      * loop. Waits for the specified amount of time.</p>
16826      *
16827      * <p>This method can be invoked from outside of the UI thread
16828      * only when this View is attached to a window.</p>
16829      *
16830      * @param delayMilliseconds the duration in milliseconds to delay the
16831      *         invalidation by
16832      *
16833      * @see #invalidate()
16834      * @see #postInvalidate()
16835      */
postInvalidateDelayed(long delayMilliseconds)16836     public void postInvalidateDelayed(long delayMilliseconds) {
16837         // We try only with the AttachInfo because there's no point in invalidating
16838         // if we are not attached to our window
16839         final AttachInfo attachInfo = mAttachInfo;
16840         if (attachInfo != null) {
16841             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
16842         }
16843     }
16844 
16845     /**
16846      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
16847      * through the event loop. Waits for the specified amount of time.</p>
16848      *
16849      * <p>This method can be invoked from outside of the UI thread
16850      * only when this View is attached to a window.</p>
16851      *
16852      * @param delayMilliseconds the duration in milliseconds to delay the
16853      *         invalidation by
16854      * @param left The left coordinate of the rectangle to invalidate.
16855      * @param top The top coordinate of the rectangle to invalidate.
16856      * @param right The right coordinate of the rectangle to invalidate.
16857      * @param bottom The bottom coordinate of the rectangle to invalidate.
16858      *
16859      * @see #invalidate(int, int, int, int)
16860      * @see #invalidate(Rect)
16861      * @see #postInvalidate(int, int, int, int)
16862      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)16863     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
16864             int right, int bottom) {
16865 
16866         // We try only with the AttachInfo because there's no point in invalidating
16867         // if we are not attached to our window
16868         final AttachInfo attachInfo = mAttachInfo;
16869         if (attachInfo != null) {
16870             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
16871             info.target = this;
16872             info.left = left;
16873             info.top = top;
16874             info.right = right;
16875             info.bottom = bottom;
16876 
16877             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
16878         }
16879     }
16880 
16881     /**
16882      * <p>Cause an invalidate to happen on the next animation time step, typically the
16883      * next display frame.</p>
16884      *
16885      * <p>This method can be invoked from outside of the UI thread
16886      * only when this View is attached to a window.</p>
16887      *
16888      * @see #invalidate()
16889      */
postInvalidateOnAnimation()16890     public void postInvalidateOnAnimation() {
16891         // We try only with the AttachInfo because there's no point in invalidating
16892         // if we are not attached to our window
16893         final AttachInfo attachInfo = mAttachInfo;
16894         if (attachInfo != null) {
16895             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
16896         }
16897     }
16898 
16899     /**
16900      * <p>Cause an invalidate of the specified area to happen on the next animation
16901      * time step, typically the next display frame.</p>
16902      *
16903      * <p>This method can be invoked from outside of the UI thread
16904      * only when this View is attached to a window.</p>
16905      *
16906      * @param left The left coordinate of the rectangle to invalidate.
16907      * @param top The top coordinate of the rectangle to invalidate.
16908      * @param right The right coordinate of the rectangle to invalidate.
16909      * @param bottom The bottom coordinate of the rectangle to invalidate.
16910      *
16911      * @see #invalidate(int, int, int, int)
16912      * @see #invalidate(Rect)
16913      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)16914     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
16915         // We try only with the AttachInfo because there's no point in invalidating
16916         // if we are not attached to our window
16917         final AttachInfo attachInfo = mAttachInfo;
16918         if (attachInfo != null) {
16919             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
16920             info.target = this;
16921             info.left = left;
16922             info.top = top;
16923             info.right = right;
16924             info.bottom = bottom;
16925 
16926             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
16927         }
16928     }
16929 
16930     /**
16931      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
16932      * This event is sent at most once every
16933      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
16934      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)16935     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
16936         if (mSendViewScrolledAccessibilityEvent == null) {
16937             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
16938         }
16939         mSendViewScrolledAccessibilityEvent.post(dx, dy);
16940     }
16941 
16942     /**
16943      * Called by a parent to request that a child update its values for mScrollX
16944      * and mScrollY if necessary. This will typically be done if the child is
16945      * animating a scroll using a {@link android.widget.Scroller Scroller}
16946      * object.
16947      */
computeScroll()16948     public void computeScroll() {
16949     }
16950 
16951     /**
16952      * <p>Indicate whether the horizontal edges are faded when the view is
16953      * scrolled horizontally.</p>
16954      *
16955      * @return true if the horizontal edges should are faded on scroll, false
16956      *         otherwise
16957      *
16958      * @see #setHorizontalFadingEdgeEnabled(boolean)
16959      *
16960      * @attr ref android.R.styleable#View_requiresFadingEdge
16961      */
isHorizontalFadingEdgeEnabled()16962     public boolean isHorizontalFadingEdgeEnabled() {
16963         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
16964     }
16965 
16966     /**
16967      * <p>Define whether the horizontal edges should be faded when this view
16968      * is scrolled horizontally.</p>
16969      *
16970      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
16971      *                                    be faded when the view is scrolled
16972      *                                    horizontally
16973      *
16974      * @see #isHorizontalFadingEdgeEnabled()
16975      *
16976      * @attr ref android.R.styleable#View_requiresFadingEdge
16977      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)16978     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
16979         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
16980             if (horizontalFadingEdgeEnabled) {
16981                 initScrollCache();
16982             }
16983 
16984             mViewFlags ^= FADING_EDGE_HORIZONTAL;
16985         }
16986     }
16987 
16988     /**
16989      * <p>Indicate whether the vertical edges are faded when the view is
16990      * scrolled horizontally.</p>
16991      *
16992      * @return true if the vertical edges should are faded on scroll, false
16993      *         otherwise
16994      *
16995      * @see #setVerticalFadingEdgeEnabled(boolean)
16996      *
16997      * @attr ref android.R.styleable#View_requiresFadingEdge
16998      */
isVerticalFadingEdgeEnabled()16999     public boolean isVerticalFadingEdgeEnabled() {
17000         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
17001     }
17002 
17003     /**
17004      * <p>Define whether the vertical edges should be faded when this view
17005      * is scrolled vertically.</p>
17006      *
17007      * @param verticalFadingEdgeEnabled true if the vertical edges should
17008      *                                  be faded when the view is scrolled
17009      *                                  vertically
17010      *
17011      * @see #isVerticalFadingEdgeEnabled()
17012      *
17013      * @attr ref android.R.styleable#View_requiresFadingEdge
17014      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)17015     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
17016         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
17017             if (verticalFadingEdgeEnabled) {
17018                 initScrollCache();
17019             }
17020 
17021             mViewFlags ^= FADING_EDGE_VERTICAL;
17022         }
17023     }
17024 
17025     /**
17026      * Returns the strength, or intensity, of the top faded edge. The strength is
17027      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
17028      * returns 0.0 or 1.0 but no value in between.
17029      *
17030      * Subclasses should override this method to provide a smoother fade transition
17031      * when scrolling occurs.
17032      *
17033      * @return the intensity of the top fade as a float between 0.0f and 1.0f
17034      */
getTopFadingEdgeStrength()17035     protected float getTopFadingEdgeStrength() {
17036         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
17037     }
17038 
17039     /**
17040      * Returns the strength, or intensity, of the bottom faded edge. The strength is
17041      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
17042      * returns 0.0 or 1.0 but no value in between.
17043      *
17044      * Subclasses should override this method to provide a smoother fade transition
17045      * when scrolling occurs.
17046      *
17047      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
17048      */
getBottomFadingEdgeStrength()17049     protected float getBottomFadingEdgeStrength() {
17050         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
17051                 computeVerticalScrollRange() ? 1.0f : 0.0f;
17052     }
17053 
17054     /**
17055      * Returns the strength, or intensity, of the left faded edge. The strength is
17056      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
17057      * returns 0.0 or 1.0 but no value in between.
17058      *
17059      * Subclasses should override this method to provide a smoother fade transition
17060      * when scrolling occurs.
17061      *
17062      * @return the intensity of the left fade as a float between 0.0f and 1.0f
17063      */
getLeftFadingEdgeStrength()17064     protected float getLeftFadingEdgeStrength() {
17065         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
17066     }
17067 
17068     /**
17069      * Returns the strength, or intensity, of the right faded edge. The strength is
17070      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
17071      * returns 0.0 or 1.0 but no value in between.
17072      *
17073      * Subclasses should override this method to provide a smoother fade transition
17074      * when scrolling occurs.
17075      *
17076      * @return the intensity of the right fade as a float between 0.0f and 1.0f
17077      */
getRightFadingEdgeStrength()17078     protected float getRightFadingEdgeStrength() {
17079         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
17080                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
17081     }
17082 
17083     /**
17084      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
17085      * scrollbar is not drawn by default.</p>
17086      *
17087      * @return true if the horizontal scrollbar should be painted, false
17088      *         otherwise
17089      *
17090      * @see #setHorizontalScrollBarEnabled(boolean)
17091      */
isHorizontalScrollBarEnabled()17092     public boolean isHorizontalScrollBarEnabled() {
17093         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
17094     }
17095 
17096     /**
17097      * <p>Define whether the horizontal scrollbar should be drawn or not. The
17098      * scrollbar is not drawn by default.</p>
17099      *
17100      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
17101      *                                   be painted
17102      *
17103      * @see #isHorizontalScrollBarEnabled()
17104      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)17105     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
17106         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
17107             mViewFlags ^= SCROLLBARS_HORIZONTAL;
17108             computeOpaqueFlags();
17109             resolvePadding();
17110         }
17111     }
17112 
17113     /**
17114      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
17115      * scrollbar is not drawn by default.</p>
17116      *
17117      * @return true if the vertical scrollbar should be painted, false
17118      *         otherwise
17119      *
17120      * @see #setVerticalScrollBarEnabled(boolean)
17121      */
isVerticalScrollBarEnabled()17122     public boolean isVerticalScrollBarEnabled() {
17123         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
17124     }
17125 
17126     /**
17127      * <p>Define whether the vertical scrollbar should be drawn or not. The
17128      * scrollbar is not drawn by default.</p>
17129      *
17130      * @param verticalScrollBarEnabled true if the vertical scrollbar should
17131      *                                 be painted
17132      *
17133      * @see #isVerticalScrollBarEnabled()
17134      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)17135     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
17136         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
17137             mViewFlags ^= SCROLLBARS_VERTICAL;
17138             computeOpaqueFlags();
17139             resolvePadding();
17140         }
17141     }
17142 
17143     /**
17144      * @hide
17145      */
recomputePadding()17146     protected void recomputePadding() {
17147         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
17148     }
17149 
17150     /**
17151      * Define whether scrollbars will fade when the view is not scrolling.
17152      *
17153      * @param fadeScrollbars whether to enable fading
17154      *
17155      * @attr ref android.R.styleable#View_fadeScrollbars
17156      */
setScrollbarFadingEnabled(boolean fadeScrollbars)17157     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
17158         initScrollCache();
17159         final ScrollabilityCache scrollabilityCache = mScrollCache;
17160         scrollabilityCache.fadeScrollBars = fadeScrollbars;
17161         if (fadeScrollbars) {
17162             scrollabilityCache.state = ScrollabilityCache.OFF;
17163         } else {
17164             scrollabilityCache.state = ScrollabilityCache.ON;
17165         }
17166     }
17167 
17168     /**
17169      *
17170      * Returns true if scrollbars will fade when this view is not scrolling
17171      *
17172      * @return true if scrollbar fading is enabled
17173      *
17174      * @attr ref android.R.styleable#View_fadeScrollbars
17175      */
isScrollbarFadingEnabled()17176     public boolean isScrollbarFadingEnabled() {
17177         return mScrollCache != null && mScrollCache.fadeScrollBars;
17178     }
17179 
17180     /**
17181      *
17182      * Returns the delay before scrollbars fade.
17183      *
17184      * @return the delay before scrollbars fade
17185      *
17186      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
17187      */
getScrollBarDefaultDelayBeforeFade()17188     public int getScrollBarDefaultDelayBeforeFade() {
17189         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
17190                 mScrollCache.scrollBarDefaultDelayBeforeFade;
17191     }
17192 
17193     /**
17194      * Define the delay before scrollbars fade.
17195      *
17196      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
17197      *
17198      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
17199      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)17200     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
17201         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
17202     }
17203 
17204     /**
17205      *
17206      * Returns the scrollbar fade duration.
17207      *
17208      * @return the scrollbar fade duration, in milliseconds
17209      *
17210      * @attr ref android.R.styleable#View_scrollbarFadeDuration
17211      */
getScrollBarFadeDuration()17212     public int getScrollBarFadeDuration() {
17213         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
17214                 mScrollCache.scrollBarFadeDuration;
17215     }
17216 
17217     /**
17218      * Define the scrollbar fade duration.
17219      *
17220      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
17221      *
17222      * @attr ref android.R.styleable#View_scrollbarFadeDuration
17223      */
setScrollBarFadeDuration(int scrollBarFadeDuration)17224     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
17225         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
17226     }
17227 
17228     /**
17229      *
17230      * Returns the scrollbar size.
17231      *
17232      * @return the scrollbar size
17233      *
17234      * @attr ref android.R.styleable#View_scrollbarSize
17235      */
getScrollBarSize()17236     public int getScrollBarSize() {
17237         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
17238                 mScrollCache.scrollBarSize;
17239     }
17240 
17241     /**
17242      * Define the scrollbar size.
17243      *
17244      * @param scrollBarSize - the scrollbar size
17245      *
17246      * @attr ref android.R.styleable#View_scrollbarSize
17247      */
setScrollBarSize(int scrollBarSize)17248     public void setScrollBarSize(int scrollBarSize) {
17249         getScrollCache().scrollBarSize = scrollBarSize;
17250     }
17251 
17252     /**
17253      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
17254      * inset. When inset, they add to the padding of the view. And the scrollbars
17255      * can be drawn inside the padding area or on the edge of the view. For example,
17256      * if a view has a background drawable and you want to draw the scrollbars
17257      * inside the padding specified by the drawable, you can use
17258      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
17259      * appear at the edge of the view, ignoring the padding, then you can use
17260      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
17261      * @param style the style of the scrollbars. Should be one of
17262      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
17263      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
17264      * @see #SCROLLBARS_INSIDE_OVERLAY
17265      * @see #SCROLLBARS_INSIDE_INSET
17266      * @see #SCROLLBARS_OUTSIDE_OVERLAY
17267      * @see #SCROLLBARS_OUTSIDE_INSET
17268      *
17269      * @attr ref android.R.styleable#View_scrollbarStyle
17270      */
setScrollBarStyle(@crollBarStyle int style)17271     public void setScrollBarStyle(@ScrollBarStyle int style) {
17272         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
17273             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
17274             computeOpaqueFlags();
17275             resolvePadding();
17276         }
17277     }
17278 
17279     /**
17280      * <p>Returns the current scrollbar style.</p>
17281      * @return the current scrollbar style
17282      * @see #SCROLLBARS_INSIDE_OVERLAY
17283      * @see #SCROLLBARS_INSIDE_INSET
17284      * @see #SCROLLBARS_OUTSIDE_OVERLAY
17285      * @see #SCROLLBARS_OUTSIDE_INSET
17286      *
17287      * @attr ref android.R.styleable#View_scrollbarStyle
17288      */
17289     @ViewDebug.ExportedProperty(mapping = {
17290             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
17291             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
17292             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
17293             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
17294     })
17295     @ScrollBarStyle
getScrollBarStyle()17296     public int getScrollBarStyle() {
17297         return mViewFlags & SCROLLBARS_STYLE_MASK;
17298     }
17299 
17300     /**
17301      * <p>Compute the horizontal range that the horizontal scrollbar
17302      * represents.</p>
17303      *
17304      * <p>The range is expressed in arbitrary units that must be the same as the
17305      * units used by {@link #computeHorizontalScrollExtent()} and
17306      * {@link #computeHorizontalScrollOffset()}.</p>
17307      *
17308      * <p>The default range is the drawing width of this view.</p>
17309      *
17310      * @return the total horizontal range represented by the horizontal
17311      *         scrollbar
17312      *
17313      * @see #computeHorizontalScrollExtent()
17314      * @see #computeHorizontalScrollOffset()
17315      * @see android.widget.ScrollBarDrawable
17316      */
computeHorizontalScrollRange()17317     protected int computeHorizontalScrollRange() {
17318         return getWidth();
17319     }
17320 
17321     /**
17322      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
17323      * within the horizontal range. This value is used to compute the position
17324      * of the thumb within the scrollbar's track.</p>
17325      *
17326      * <p>The range is expressed in arbitrary units that must be the same as the
17327      * units used by {@link #computeHorizontalScrollRange()} and
17328      * {@link #computeHorizontalScrollExtent()}.</p>
17329      *
17330      * <p>The default offset is the scroll offset of this view.</p>
17331      *
17332      * @return the horizontal offset of the scrollbar's thumb
17333      *
17334      * @see #computeHorizontalScrollRange()
17335      * @see #computeHorizontalScrollExtent()
17336      * @see android.widget.ScrollBarDrawable
17337      */
computeHorizontalScrollOffset()17338     protected int computeHorizontalScrollOffset() {
17339         return mScrollX;
17340     }
17341 
17342     /**
17343      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
17344      * within the horizontal range. This value is used to compute the length
17345      * of the thumb within the scrollbar's track.</p>
17346      *
17347      * <p>The range is expressed in arbitrary units that must be the same as the
17348      * units used by {@link #computeHorizontalScrollRange()} and
17349      * {@link #computeHorizontalScrollOffset()}.</p>
17350      *
17351      * <p>The default extent is the drawing width of this view.</p>
17352      *
17353      * @return the horizontal extent of the scrollbar's thumb
17354      *
17355      * @see #computeHorizontalScrollRange()
17356      * @see #computeHorizontalScrollOffset()
17357      * @see android.widget.ScrollBarDrawable
17358      */
computeHorizontalScrollExtent()17359     protected int computeHorizontalScrollExtent() {
17360         return getWidth();
17361     }
17362 
17363     /**
17364      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
17365      *
17366      * <p>The range is expressed in arbitrary units that must be the same as the
17367      * units used by {@link #computeVerticalScrollExtent()} and
17368      * {@link #computeVerticalScrollOffset()}.</p>
17369      *
17370      * @return the total vertical range represented by the vertical scrollbar
17371      *
17372      * <p>The default range is the drawing height of this view.</p>
17373      *
17374      * @see #computeVerticalScrollExtent()
17375      * @see #computeVerticalScrollOffset()
17376      * @see android.widget.ScrollBarDrawable
17377      */
computeVerticalScrollRange()17378     protected int computeVerticalScrollRange() {
17379         return getHeight();
17380     }
17381 
17382     /**
17383      * <p>Compute the vertical offset of the vertical scrollbar's thumb
17384      * within the horizontal range. This value is used to compute the position
17385      * of the thumb within the scrollbar's track.</p>
17386      *
17387      * <p>The range is expressed in arbitrary units that must be the same as the
17388      * units used by {@link #computeVerticalScrollRange()} and
17389      * {@link #computeVerticalScrollExtent()}.</p>
17390      *
17391      * <p>The default offset is the scroll offset of this view.</p>
17392      *
17393      * @return the vertical offset of the scrollbar's thumb
17394      *
17395      * @see #computeVerticalScrollRange()
17396      * @see #computeVerticalScrollExtent()
17397      * @see android.widget.ScrollBarDrawable
17398      */
computeVerticalScrollOffset()17399     protected int computeVerticalScrollOffset() {
17400         return mScrollY;
17401     }
17402 
17403     /**
17404      * <p>Compute the vertical extent of the vertical scrollbar's thumb
17405      * within the vertical range. This value is used to compute the length
17406      * of the thumb within the scrollbar's track.</p>
17407      *
17408      * <p>The range is expressed in arbitrary units that must be the same as the
17409      * units used by {@link #computeVerticalScrollRange()} and
17410      * {@link #computeVerticalScrollOffset()}.</p>
17411      *
17412      * <p>The default extent is the drawing height of this view.</p>
17413      *
17414      * @return the vertical extent of the scrollbar's thumb
17415      *
17416      * @see #computeVerticalScrollRange()
17417      * @see #computeVerticalScrollOffset()
17418      * @see android.widget.ScrollBarDrawable
17419      */
computeVerticalScrollExtent()17420     protected int computeVerticalScrollExtent() {
17421         return getHeight();
17422     }
17423 
17424     /**
17425      * Check if this view can be scrolled horizontally in a certain direction.
17426      *
17427      * @param direction Negative to check scrolling left, positive to check scrolling right.
17428      * @return true if this view can be scrolled in the specified direction, false otherwise.
17429      */
canScrollHorizontally(int direction)17430     public boolean canScrollHorizontally(int direction) {
17431         final int offset = computeHorizontalScrollOffset();
17432         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
17433         if (range == 0) return false;
17434         if (direction < 0) {
17435             return offset > 0;
17436         } else {
17437             return offset < range - 1;
17438         }
17439     }
17440 
17441     /**
17442      * Check if this view can be scrolled vertically in a certain direction.
17443      *
17444      * @param direction Negative to check scrolling up, positive to check scrolling down.
17445      * @return true if this view can be scrolled in the specified direction, false otherwise.
17446      */
canScrollVertically(int direction)17447     public boolean canScrollVertically(int direction) {
17448         final int offset = computeVerticalScrollOffset();
17449         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
17450         if (range == 0) return false;
17451         if (direction < 0) {
17452             return offset > 0;
17453         } else {
17454             return offset < range - 1;
17455         }
17456     }
17457 
getScrollIndicatorBounds(@onNull Rect out)17458     void getScrollIndicatorBounds(@NonNull Rect out) {
17459         out.left = mScrollX;
17460         out.right = mScrollX + mRight - mLeft;
17461         out.top = mScrollY;
17462         out.bottom = mScrollY + mBottom - mTop;
17463     }
17464 
onDrawScrollIndicators(Canvas c)17465     private void onDrawScrollIndicators(Canvas c) {
17466         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
17467             // No scroll indicators enabled.
17468             return;
17469         }
17470 
17471         final Drawable dr = mScrollIndicatorDrawable;
17472         if (dr == null) {
17473             // Scroll indicators aren't supported here.
17474             return;
17475         }
17476 
17477         final int h = dr.getIntrinsicHeight();
17478         final int w = dr.getIntrinsicWidth();
17479         final Rect rect = mAttachInfo.mTmpInvalRect;
17480         getScrollIndicatorBounds(rect);
17481 
17482         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
17483             final boolean canScrollUp = canScrollVertically(-1);
17484             if (canScrollUp) {
17485                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
17486                 dr.draw(c);
17487             }
17488         }
17489 
17490         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
17491             final boolean canScrollDown = canScrollVertically(1);
17492             if (canScrollDown) {
17493                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
17494                 dr.draw(c);
17495             }
17496         }
17497 
17498         final int leftRtl;
17499         final int rightRtl;
17500         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
17501             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
17502             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
17503         } else {
17504             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
17505             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
17506         }
17507 
17508         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
17509         if ((mPrivateFlags3 & leftMask) != 0) {
17510             final boolean canScrollLeft = canScrollHorizontally(-1);
17511             if (canScrollLeft) {
17512                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
17513                 dr.draw(c);
17514             }
17515         }
17516 
17517         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
17518         if ((mPrivateFlags3 & rightMask) != 0) {
17519             final boolean canScrollRight = canScrollHorizontally(1);
17520             if (canScrollRight) {
17521                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
17522                 dr.draw(c);
17523             }
17524         }
17525     }
17526 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)17527     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
17528             @Nullable Rect touchBounds) {
17529         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
17530         if (bounds == null) {
17531             return;
17532         }
17533         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
17534         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
17535                 && !isVerticalScrollBarHidden();
17536         final int size = getHorizontalScrollbarHeight();
17537         final int verticalScrollBarGap = drawVerticalScrollBar ?
17538                 getVerticalScrollbarWidth() : 0;
17539         final int width = mRight - mLeft;
17540         final int height = mBottom - mTop;
17541         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
17542         bounds.left = mScrollX + (mPaddingLeft & inside);
17543         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
17544         bounds.bottom = bounds.top + size;
17545 
17546         if (touchBounds == null) {
17547             return;
17548         }
17549         if (touchBounds != bounds) {
17550             touchBounds.set(bounds);
17551         }
17552         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
17553         if (touchBounds.height() < minTouchTarget) {
17554             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
17555             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
17556             touchBounds.top = touchBounds.bottom - minTouchTarget;
17557         }
17558         if (touchBounds.width() < minTouchTarget) {
17559             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
17560             touchBounds.left -= adjust;
17561             touchBounds.right = touchBounds.left + minTouchTarget;
17562         }
17563     }
17564 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)17565     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
17566         if (mRoundScrollbarRenderer == null) {
17567             getStraightVerticalScrollBarBounds(bounds, touchBounds);
17568         } else {
17569             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
17570         }
17571     }
17572 
getRoundVerticalScrollBarBounds(Rect bounds)17573     private void getRoundVerticalScrollBarBounds(Rect bounds) {
17574         final int width = mRight - mLeft;
17575         final int height = mBottom - mTop;
17576         // Do not take padding into account as we always want the scrollbars
17577         // to hug the screen for round wearable devices.
17578         bounds.left = mScrollX;
17579         bounds.top = mScrollY;
17580         bounds.right = bounds.left + width;
17581         bounds.bottom = mScrollY + height;
17582     }
17583 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)17584     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
17585             @Nullable Rect touchBounds) {
17586         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
17587         if (bounds == null) {
17588             return;
17589         }
17590         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
17591         final int size = getVerticalScrollbarWidth();
17592         int verticalScrollbarPosition = mVerticalScrollbarPosition;
17593         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
17594             verticalScrollbarPosition = isLayoutRtl() ?
17595                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
17596         }
17597         final int width = mRight - mLeft;
17598         final int height = mBottom - mTop;
17599         switch (verticalScrollbarPosition) {
17600             default:
17601             case SCROLLBAR_POSITION_RIGHT:
17602                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
17603                 break;
17604             case SCROLLBAR_POSITION_LEFT:
17605                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
17606                 break;
17607         }
17608         bounds.top = mScrollY + (mPaddingTop & inside);
17609         bounds.right = bounds.left + size;
17610         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
17611 
17612         if (touchBounds == null) {
17613             return;
17614         }
17615         if (touchBounds != bounds) {
17616             touchBounds.set(bounds);
17617         }
17618         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
17619         if (touchBounds.width() < minTouchTarget) {
17620             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
17621             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
17622                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
17623                 touchBounds.left = touchBounds.right - minTouchTarget;
17624             } else {
17625                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
17626                 touchBounds.right = touchBounds.left + minTouchTarget;
17627             }
17628         }
17629         if (touchBounds.height() < minTouchTarget) {
17630             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
17631             touchBounds.top -= adjust;
17632             touchBounds.bottom = touchBounds.top + minTouchTarget;
17633         }
17634     }
17635 
17636     /**
17637      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
17638      * scrollbars are painted only if they have been awakened first.</p>
17639      *
17640      * @param canvas the canvas on which to draw the scrollbars
17641      *
17642      * @see #awakenScrollBars(int)
17643      */
onDrawScrollBars(Canvas canvas)17644     protected final void onDrawScrollBars(Canvas canvas) {
17645         // scrollbars are drawn only when the animation is running
17646         final ScrollabilityCache cache = mScrollCache;
17647 
17648         if (cache != null) {
17649 
17650             int state = cache.state;
17651 
17652             if (state == ScrollabilityCache.OFF) {
17653                 return;
17654             }
17655 
17656             boolean invalidate = false;
17657 
17658             if (state == ScrollabilityCache.FADING) {
17659                 // We're fading -- get our fade interpolation
17660                 if (cache.interpolatorValues == null) {
17661                     cache.interpolatorValues = new float[1];
17662                 }
17663 
17664                 float[] values = cache.interpolatorValues;
17665 
17666                 // Stops the animation if we're done
17667                 if (cache.scrollBarInterpolator.timeToValues(values) ==
17668                         Interpolator.Result.FREEZE_END) {
17669                     cache.state = ScrollabilityCache.OFF;
17670                 } else {
17671                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
17672                 }
17673 
17674                 // This will make the scroll bars inval themselves after
17675                 // drawing. We only want this when we're fading so that
17676                 // we prevent excessive redraws
17677                 invalidate = true;
17678             } else {
17679                 // We're just on -- but we may have been fading before so
17680                 // reset alpha
17681                 cache.scrollBar.mutate().setAlpha(255);
17682             }
17683 
17684             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
17685             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
17686                     && !isVerticalScrollBarHidden();
17687 
17688             // Fork out the scroll bar drawing for round wearable devices.
17689             if (mRoundScrollbarRenderer != null) {
17690                 if (drawVerticalScrollBar) {
17691                     final Rect bounds = cache.mScrollBarBounds;
17692                     getVerticalScrollBarBounds(bounds, null);
17693                     mRoundScrollbarRenderer.drawRoundScrollbars(
17694                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
17695                     if (invalidate) {
17696                         invalidate();
17697                     }
17698                 }
17699                 // Do not draw horizontal scroll bars for round wearable devices.
17700             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
17701                 final ScrollBarDrawable scrollBar = cache.scrollBar;
17702 
17703                 if (drawHorizontalScrollBar) {
17704                     scrollBar.setParameters(computeHorizontalScrollRange(),
17705                             computeHorizontalScrollOffset(),
17706                             computeHorizontalScrollExtent(), false);
17707                     final Rect bounds = cache.mScrollBarBounds;
17708                     getHorizontalScrollBarBounds(bounds, null);
17709                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
17710                             bounds.right, bounds.bottom);
17711                     if (invalidate) {
17712                         invalidate(bounds);
17713                     }
17714                 }
17715 
17716                 if (drawVerticalScrollBar) {
17717                     scrollBar.setParameters(computeVerticalScrollRange(),
17718                             computeVerticalScrollOffset(),
17719                             computeVerticalScrollExtent(), true);
17720                     final Rect bounds = cache.mScrollBarBounds;
17721                     getVerticalScrollBarBounds(bounds, null);
17722                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
17723                             bounds.right, bounds.bottom);
17724                     if (invalidate) {
17725                         invalidate(bounds);
17726                     }
17727                 }
17728             }
17729         }
17730     }
17731 
17732     /**
17733      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
17734      * FastScroller is visible.
17735      * @return whether to temporarily hide the vertical scrollbar
17736      * @hide
17737      */
isVerticalScrollBarHidden()17738     protected boolean isVerticalScrollBarHidden() {
17739         return false;
17740     }
17741 
17742     /**
17743      * <p>Draw the horizontal scrollbar if
17744      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
17745      *
17746      * @param canvas the canvas on which to draw the scrollbar
17747      * @param scrollBar the scrollbar's drawable
17748      *
17749      * @see #isHorizontalScrollBarEnabled()
17750      * @see #computeHorizontalScrollRange()
17751      * @see #computeHorizontalScrollExtent()
17752      * @see #computeHorizontalScrollOffset()
17753      * @see android.widget.ScrollBarDrawable
17754      * @hide
17755      */
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)17756     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
17757             int l, int t, int r, int b) {
17758         scrollBar.setBounds(l, t, r, b);
17759         scrollBar.draw(canvas);
17760     }
17761 
17762     /**
17763      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
17764      * returns true.</p>
17765      *
17766      * @param canvas the canvas on which to draw the scrollbar
17767      * @param scrollBar the scrollbar's drawable
17768      *
17769      * @see #isVerticalScrollBarEnabled()
17770      * @see #computeVerticalScrollRange()
17771      * @see #computeVerticalScrollExtent()
17772      * @see #computeVerticalScrollOffset()
17773      * @see android.widget.ScrollBarDrawable
17774      * @hide
17775      */
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)17776     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
17777             int l, int t, int r, int b) {
17778         scrollBar.setBounds(l, t, r, b);
17779         scrollBar.draw(canvas);
17780     }
17781 
17782     /**
17783      * Implement this to do your drawing.
17784      *
17785      * @param canvas the canvas on which the background will be drawn
17786      */
onDraw(Canvas canvas)17787     protected void onDraw(Canvas canvas) {
17788     }
17789 
17790     /*
17791      * Caller is responsible for calling requestLayout if necessary.
17792      * (This allows addViewInLayout to not request a new layout.)
17793      */
assignParent(ViewParent parent)17794     void assignParent(ViewParent parent) {
17795         if (mParent == null) {
17796             mParent = parent;
17797         } else if (parent == null) {
17798             mParent = null;
17799         } else {
17800             throw new RuntimeException("view " + this + " being added, but"
17801                     + " it already has a parent");
17802         }
17803     }
17804 
17805     /**
17806      * This is called when the view is attached to a window.  At this point it
17807      * has a Surface and will start drawing.  Note that this function is
17808      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
17809      * however it may be called any time before the first onDraw -- including
17810      * before or after {@link #onMeasure(int, int)}.
17811      *
17812      * @see #onDetachedFromWindow()
17813      */
17814     @CallSuper
onAttachedToWindow()17815     protected void onAttachedToWindow() {
17816         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
17817             mParent.requestTransparentRegion(this);
17818         }
17819 
17820         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
17821 
17822         jumpDrawablesToCurrentState();
17823 
17824         resetSubtreeAccessibilityStateChanged();
17825 
17826         // rebuild, since Outline not maintained while View is detached
17827         rebuildOutline();
17828 
17829         if (isFocused()) {
17830             InputMethodManager imm = InputMethodManager.peekInstance();
17831             if (imm != null) {
17832                 imm.focusIn(this);
17833             }
17834         }
17835     }
17836 
17837     /**
17838      * Resolve all RTL related properties.
17839      *
17840      * @return true if resolution of RTL properties has been done
17841      *
17842      * @hide
17843      */
resolveRtlPropertiesIfNeeded()17844     public boolean resolveRtlPropertiesIfNeeded() {
17845         if (!needRtlPropertiesResolution()) return false;
17846 
17847         // Order is important here: LayoutDirection MUST be resolved first
17848         if (!isLayoutDirectionResolved()) {
17849             resolveLayoutDirection();
17850             resolveLayoutParams();
17851         }
17852         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
17853         if (!isTextDirectionResolved()) {
17854             resolveTextDirection();
17855         }
17856         if (!isTextAlignmentResolved()) {
17857             resolveTextAlignment();
17858         }
17859         // Should resolve Drawables before Padding because we need the layout direction of the
17860         // Drawable to correctly resolve Padding.
17861         if (!areDrawablesResolved()) {
17862             resolveDrawables();
17863         }
17864         if (!isPaddingResolved()) {
17865             resolvePadding();
17866         }
17867         onRtlPropertiesChanged(getLayoutDirection());
17868         return true;
17869     }
17870 
17871     /**
17872      * Reset resolution of all RTL related properties.
17873      *
17874      * @hide
17875      */
resetRtlProperties()17876     public void resetRtlProperties() {
17877         resetResolvedLayoutDirection();
17878         resetResolvedTextDirection();
17879         resetResolvedTextAlignment();
17880         resetResolvedPadding();
17881         resetResolvedDrawables();
17882     }
17883 
17884     /**
17885      * @see #onScreenStateChanged(int)
17886      */
dispatchScreenStateChanged(int screenState)17887     void dispatchScreenStateChanged(int screenState) {
17888         onScreenStateChanged(screenState);
17889     }
17890 
17891     /**
17892      * This method is called whenever the state of the screen this view is
17893      * attached to changes. A state change will usually occurs when the screen
17894      * turns on or off (whether it happens automatically or the user does it
17895      * manually.)
17896      *
17897      * @param screenState The new state of the screen. Can be either
17898      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
17899      */
onScreenStateChanged(int screenState)17900     public void onScreenStateChanged(int screenState) {
17901     }
17902 
17903     /**
17904      * @see #onMovedToDisplay(int, Configuration)
17905      */
dispatchMovedToDisplay(Display display, Configuration config)17906     void dispatchMovedToDisplay(Display display, Configuration config) {
17907         mAttachInfo.mDisplay = display;
17908         mAttachInfo.mDisplayState = display.getState();
17909         onMovedToDisplay(display.getDisplayId(), config);
17910     }
17911 
17912     /**
17913      * Called by the system when the hosting activity is moved from one display to another without
17914      * recreation. This means that the activity is declared to handle all changes to configuration
17915      * that happened when it was switched to another display, so it wasn't destroyed and created
17916      * again.
17917      *
17918      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
17919      * applied configuration actually changed. It is up to app developer to choose whether to handle
17920      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
17921      * call.
17922      *
17923      * <p>Use this callback to track changes to the displays if some functionality relies on an
17924      * association with some display properties.
17925      *
17926      * @param displayId The id of the display to which the view was moved.
17927      * @param config Configuration of the resources on new display after move.
17928      *
17929      * @see #onConfigurationChanged(Configuration)
17930      * @hide
17931      */
onMovedToDisplay(int displayId, Configuration config)17932     public void onMovedToDisplay(int displayId, Configuration config) {
17933     }
17934 
17935     /**
17936      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
17937      */
hasRtlSupport()17938     private boolean hasRtlSupport() {
17939         return mContext.getApplicationInfo().hasRtlSupport();
17940     }
17941 
17942     /**
17943      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
17944      * RTL not supported)
17945      */
isRtlCompatibilityMode()17946     private boolean isRtlCompatibilityMode() {
17947         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
17948         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
17949     }
17950 
17951     /**
17952      * @return true if RTL properties need resolution.
17953      *
17954      */
needRtlPropertiesResolution()17955     private boolean needRtlPropertiesResolution() {
17956         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
17957     }
17958 
17959     /**
17960      * Called when any RTL property (layout direction or text direction or text alignment) has
17961      * been changed.
17962      *
17963      * Subclasses need to override this method to take care of cached information that depends on the
17964      * resolved layout direction, or to inform child views that inherit their layout direction.
17965      *
17966      * The default implementation does nothing.
17967      *
17968      * @param layoutDirection the direction of the layout
17969      *
17970      * @see #LAYOUT_DIRECTION_LTR
17971      * @see #LAYOUT_DIRECTION_RTL
17972      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)17973     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
17974     }
17975 
17976     /**
17977      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
17978      * that the parent directionality can and will be resolved before its children.
17979      *
17980      * @return true if resolution has been done, false otherwise.
17981      *
17982      * @hide
17983      */
resolveLayoutDirection()17984     public boolean resolveLayoutDirection() {
17985         // Clear any previous layout direction resolution
17986         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17987 
17988         if (hasRtlSupport()) {
17989             // Set resolved depending on layout direction
17990             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
17991                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
17992                 case LAYOUT_DIRECTION_INHERIT:
17993                     // We cannot resolve yet. LTR is by default and let the resolution happen again
17994                     // later to get the correct resolved value
17995                     if (!canResolveLayoutDirection()) return false;
17996 
17997                     // Parent has not yet resolved, LTR is still the default
17998                     try {
17999                         if (!mParent.isLayoutDirectionResolved()) return false;
18000 
18001                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
18002                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
18003                         }
18004                     } catch (AbstractMethodError e) {
18005                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18006                                 " does not fully implement ViewParent", e);
18007                     }
18008                     break;
18009                 case LAYOUT_DIRECTION_RTL:
18010                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
18011                     break;
18012                 case LAYOUT_DIRECTION_LOCALE:
18013                     if((LAYOUT_DIRECTION_RTL ==
18014                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
18015                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
18016                     }
18017                     break;
18018                 default:
18019                     // Nothing to do, LTR by default
18020             }
18021         }
18022 
18023         // Set to resolved
18024         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
18025         return true;
18026     }
18027 
18028     /**
18029      * Check if layout direction resolution can be done.
18030      *
18031      * @return true if layout direction resolution can be done otherwise return false.
18032      */
canResolveLayoutDirection()18033     public boolean canResolveLayoutDirection() {
18034         switch (getRawLayoutDirection()) {
18035             case LAYOUT_DIRECTION_INHERIT:
18036                 if (mParent != null) {
18037                     try {
18038                         return mParent.canResolveLayoutDirection();
18039                     } catch (AbstractMethodError e) {
18040                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18041                                 " does not fully implement ViewParent", e);
18042                     }
18043                 }
18044                 return false;
18045 
18046             default:
18047                 return true;
18048         }
18049     }
18050 
18051     /**
18052      * Reset the resolved layout direction. Layout direction will be resolved during a call to
18053      * {@link #onMeasure(int, int)}.
18054      *
18055      * @hide
18056      */
resetResolvedLayoutDirection()18057     public void resetResolvedLayoutDirection() {
18058         // Reset the current resolved bits
18059         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
18060     }
18061 
18062     /**
18063      * @return true if the layout direction is inherited.
18064      *
18065      * @hide
18066      */
isLayoutDirectionInherited()18067     public boolean isLayoutDirectionInherited() {
18068         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
18069     }
18070 
18071     /**
18072      * @return true if layout direction has been resolved.
18073      */
isLayoutDirectionResolved()18074     public boolean isLayoutDirectionResolved() {
18075         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
18076     }
18077 
18078     /**
18079      * Return if padding has been resolved
18080      *
18081      * @hide
18082      */
isPaddingResolved()18083     boolean isPaddingResolved() {
18084         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
18085     }
18086 
18087     /**
18088      * Resolves padding depending on layout direction, if applicable, and
18089      * recomputes internal padding values to adjust for scroll bars.
18090      *
18091      * @hide
18092      */
resolvePadding()18093     public void resolvePadding() {
18094         final int resolvedLayoutDirection = getLayoutDirection();
18095 
18096         if (!isRtlCompatibilityMode()) {
18097             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
18098             // If start / end padding are defined, they will be resolved (hence overriding) to
18099             // left / right or right / left depending on the resolved layout direction.
18100             // If start / end padding are not defined, use the left / right ones.
18101             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
18102                 Rect padding = sThreadLocal.get();
18103                 if (padding == null) {
18104                     padding = new Rect();
18105                     sThreadLocal.set(padding);
18106                 }
18107                 mBackground.getPadding(padding);
18108                 if (!mLeftPaddingDefined) {
18109                     mUserPaddingLeftInitial = padding.left;
18110                 }
18111                 if (!mRightPaddingDefined) {
18112                     mUserPaddingRightInitial = padding.right;
18113                 }
18114             }
18115             switch (resolvedLayoutDirection) {
18116                 case LAYOUT_DIRECTION_RTL:
18117                     if (mUserPaddingStart != UNDEFINED_PADDING) {
18118                         mUserPaddingRight = mUserPaddingStart;
18119                     } else {
18120                         mUserPaddingRight = mUserPaddingRightInitial;
18121                     }
18122                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
18123                         mUserPaddingLeft = mUserPaddingEnd;
18124                     } else {
18125                         mUserPaddingLeft = mUserPaddingLeftInitial;
18126                     }
18127                     break;
18128                 case LAYOUT_DIRECTION_LTR:
18129                 default:
18130                     if (mUserPaddingStart != UNDEFINED_PADDING) {
18131                         mUserPaddingLeft = mUserPaddingStart;
18132                     } else {
18133                         mUserPaddingLeft = mUserPaddingLeftInitial;
18134                     }
18135                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
18136                         mUserPaddingRight = mUserPaddingEnd;
18137                     } else {
18138                         mUserPaddingRight = mUserPaddingRightInitial;
18139                     }
18140             }
18141 
18142             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
18143         }
18144 
18145         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
18146         onRtlPropertiesChanged(resolvedLayoutDirection);
18147 
18148         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
18149     }
18150 
18151     /**
18152      * Reset the resolved layout direction.
18153      *
18154      * @hide
18155      */
resetResolvedPadding()18156     public void resetResolvedPadding() {
18157         resetResolvedPaddingInternal();
18158     }
18159 
18160     /**
18161      * Used when we only want to reset *this* view's padding and not trigger overrides
18162      * in ViewGroup that reset children too.
18163      */
resetResolvedPaddingInternal()18164     void resetResolvedPaddingInternal() {
18165         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
18166     }
18167 
18168     /**
18169      * This is called when the view is detached from a window.  At this point it
18170      * no longer has a surface for drawing.
18171      *
18172      * @see #onAttachedToWindow()
18173      */
18174     @CallSuper
onDetachedFromWindow()18175     protected void onDetachedFromWindow() {
18176     }
18177 
18178     /**
18179      * This is a framework-internal mirror of onDetachedFromWindow() that's called
18180      * after onDetachedFromWindow().
18181      *
18182      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
18183      * The super method should be called at the end of the overridden method to ensure
18184      * subclasses are destroyed first
18185      *
18186      * @hide
18187      */
18188     @CallSuper
onDetachedFromWindowInternal()18189     protected void onDetachedFromWindowInternal() {
18190         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
18191         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
18192         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
18193 
18194         removeUnsetPressCallback();
18195         removeLongPressCallback();
18196         removePerformClickCallback();
18197         cancel(mSendViewScrolledAccessibilityEvent);
18198         stopNestedScroll();
18199 
18200         // Anything that started animating right before detach should already
18201         // be in its final state when re-attached.
18202         jumpDrawablesToCurrentState();
18203 
18204         destroyDrawingCache();
18205 
18206         cleanupDraw();
18207         mCurrentAnimation = null;
18208 
18209         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
18210             hideTooltip();
18211         }
18212     }
18213 
cleanupDraw()18214     private void cleanupDraw() {
18215         resetDisplayList();
18216         if (mAttachInfo != null) {
18217             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
18218         }
18219     }
18220 
invalidateInheritedLayoutMode(int layoutModeOfRoot)18221     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
18222     }
18223 
18224     /**
18225      * @return The number of times this view has been attached to a window
18226      */
getWindowAttachCount()18227     protected int getWindowAttachCount() {
18228         return mWindowAttachCount;
18229     }
18230 
18231     /**
18232      * Retrieve a unique token identifying the window this view is attached to.
18233      * @return Return the window's token for use in
18234      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
18235      */
getWindowToken()18236     public IBinder getWindowToken() {
18237         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
18238     }
18239 
18240     /**
18241      * Retrieve the {@link WindowId} for the window this view is
18242      * currently attached to.
18243      */
getWindowId()18244     public WindowId getWindowId() {
18245         AttachInfo ai = mAttachInfo;
18246         if (ai == null) {
18247             return null;
18248         }
18249         if (ai.mWindowId == null) {
18250             try {
18251                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
18252                 if (ai.mIWindowId != null) {
18253                     ai.mWindowId = new WindowId(ai.mIWindowId);
18254                 }
18255             } catch (RemoteException e) {
18256             }
18257         }
18258         return ai.mWindowId;
18259     }
18260 
18261     /**
18262      * Retrieve a unique token identifying the top-level "real" window of
18263      * the window that this view is attached to.  That is, this is like
18264      * {@link #getWindowToken}, except if the window this view in is a panel
18265      * window (attached to another containing window), then the token of
18266      * the containing window is returned instead.
18267      *
18268      * @return Returns the associated window token, either
18269      * {@link #getWindowToken()} or the containing window's token.
18270      */
getApplicationWindowToken()18271     public IBinder getApplicationWindowToken() {
18272         AttachInfo ai = mAttachInfo;
18273         if (ai != null) {
18274             IBinder appWindowToken = ai.mPanelParentWindowToken;
18275             if (appWindowToken == null) {
18276                 appWindowToken = ai.mWindowToken;
18277             }
18278             return appWindowToken;
18279         }
18280         return null;
18281     }
18282 
18283     /**
18284      * Gets the logical display to which the view's window has been attached.
18285      *
18286      * @return The logical display, or null if the view is not currently attached to a window.
18287      */
getDisplay()18288     public Display getDisplay() {
18289         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
18290     }
18291 
18292     /**
18293      * Retrieve private session object this view hierarchy is using to
18294      * communicate with the window manager.
18295      * @return the session object to communicate with the window manager
18296      */
getWindowSession()18297     /*package*/ IWindowSession getWindowSession() {
18298         return mAttachInfo != null ? mAttachInfo.mSession : null;
18299     }
18300 
18301     /**
18302      * Return the window this view is currently attached to. Used in
18303      * {@link android.app.ActivityView} to communicate with WM.
18304      * @hide
18305      */
getWindow()18306     protected IWindow getWindow() {
18307         return mAttachInfo != null ? mAttachInfo.mWindow : null;
18308     }
18309 
18310     /**
18311      * Return the visibility value of the least visible component passed.
18312      */
combineVisibility(int vis1, int vis2)18313     int combineVisibility(int vis1, int vis2) {
18314         // This works because VISIBLE < INVISIBLE < GONE.
18315         return Math.max(vis1, vis2);
18316     }
18317 
18318     /**
18319      * @param info the {@link android.view.View.AttachInfo} to associated with
18320      *        this view
18321      */
dispatchAttachedToWindow(AttachInfo info, int visibility)18322     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
18323         mAttachInfo = info;
18324         if (mOverlay != null) {
18325             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
18326         }
18327         mWindowAttachCount++;
18328         // We will need to evaluate the drawable state at least once.
18329         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18330         if (mFloatingTreeObserver != null) {
18331             info.mTreeObserver.merge(mFloatingTreeObserver);
18332             mFloatingTreeObserver = null;
18333         }
18334 
18335         registerPendingFrameMetricsObservers();
18336 
18337         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
18338             mAttachInfo.mScrollContainers.add(this);
18339             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
18340         }
18341         // Transfer all pending runnables.
18342         if (mRunQueue != null) {
18343             mRunQueue.executeActions(info.mHandler);
18344             mRunQueue = null;
18345         }
18346         performCollectViewAttributes(mAttachInfo, visibility);
18347         onAttachedToWindow();
18348 
18349         ListenerInfo li = mListenerInfo;
18350         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
18351                 li != null ? li.mOnAttachStateChangeListeners : null;
18352         if (listeners != null && listeners.size() > 0) {
18353             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
18354             // perform the dispatching. The iterator is a safe guard against listeners that
18355             // could mutate the list by calling the various add/remove methods. This prevents
18356             // the array from being modified while we iterate it.
18357             for (OnAttachStateChangeListener listener : listeners) {
18358                 listener.onViewAttachedToWindow(this);
18359             }
18360         }
18361 
18362         int vis = info.mWindowVisibility;
18363         if (vis != GONE) {
18364             onWindowVisibilityChanged(vis);
18365             if (isShown()) {
18366                 // Calling onVisibilityAggregated directly here since the subtree will also
18367                 // receive dispatchAttachedToWindow and this same call
18368                 onVisibilityAggregated(vis == VISIBLE);
18369             }
18370         }
18371 
18372         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
18373         // As all views in the subtree will already receive dispatchAttachedToWindow
18374         // traversing the subtree again here is not desired.
18375         onVisibilityChanged(this, visibility);
18376 
18377         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
18378             // If nobody has evaluated the drawable state yet, then do it now.
18379             refreshDrawableState();
18380         }
18381         needGlobalAttributesUpdate(false);
18382 
18383         notifyEnterOrExitForAutoFillIfNeeded(true);
18384     }
18385 
dispatchDetachedFromWindow()18386     void dispatchDetachedFromWindow() {
18387         AttachInfo info = mAttachInfo;
18388         if (info != null) {
18389             int vis = info.mWindowVisibility;
18390             if (vis != GONE) {
18391                 onWindowVisibilityChanged(GONE);
18392                 if (isShown()) {
18393                     // Invoking onVisibilityAggregated directly here since the subtree
18394                     // will also receive detached from window
18395                     onVisibilityAggregated(false);
18396                 }
18397             }
18398         }
18399 
18400         onDetachedFromWindow();
18401         onDetachedFromWindowInternal();
18402 
18403         InputMethodManager imm = InputMethodManager.peekInstance();
18404         if (imm != null) {
18405             imm.onViewDetachedFromWindow(this);
18406         }
18407 
18408         ListenerInfo li = mListenerInfo;
18409         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
18410                 li != null ? li.mOnAttachStateChangeListeners : null;
18411         if (listeners != null && listeners.size() > 0) {
18412             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
18413             // perform the dispatching. The iterator is a safe guard against listeners that
18414             // could mutate the list by calling the various add/remove methods. This prevents
18415             // the array from being modified while we iterate it.
18416             for (OnAttachStateChangeListener listener : listeners) {
18417                 listener.onViewDetachedFromWindow(this);
18418             }
18419         }
18420 
18421         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
18422             mAttachInfo.mScrollContainers.remove(this);
18423             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
18424         }
18425 
18426         mAttachInfo = null;
18427         if (mOverlay != null) {
18428             mOverlay.getOverlayView().dispatchDetachedFromWindow();
18429         }
18430 
18431         notifyEnterOrExitForAutoFillIfNeeded(false);
18432     }
18433 
18434     /**
18435      * Cancel any deferred high-level input events that were previously posted to the event queue.
18436      *
18437      * <p>Many views post high-level events such as click handlers to the event queue
18438      * to run deferred in order to preserve a desired user experience - clearing visible
18439      * pressed states before executing, etc. This method will abort any events of this nature
18440      * that are currently in flight.</p>
18441      *
18442      * <p>Custom views that generate their own high-level deferred input events should override
18443      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
18444      *
18445      * <p>This will also cancel pending input events for any child views.</p>
18446      *
18447      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
18448      * This will not impact newer events posted after this call that may occur as a result of
18449      * lower-level input events still waiting in the queue. If you are trying to prevent
18450      * double-submitted  events for the duration of some sort of asynchronous transaction
18451      * you should also take other steps to protect against unexpected double inputs e.g. calling
18452      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
18453      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
18454      */
cancelPendingInputEvents()18455     public final void cancelPendingInputEvents() {
18456         dispatchCancelPendingInputEvents();
18457     }
18458 
18459     /**
18460      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
18461      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
18462      */
dispatchCancelPendingInputEvents()18463     void dispatchCancelPendingInputEvents() {
18464         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
18465         onCancelPendingInputEvents();
18466         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
18467             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
18468                     " did not call through to super.onCancelPendingInputEvents()");
18469         }
18470     }
18471 
18472     /**
18473      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
18474      * a parent view.
18475      *
18476      * <p>This method is responsible for removing any pending high-level input events that were
18477      * posted to the event queue to run later. Custom view classes that post their own deferred
18478      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
18479      * {@link android.os.Handler} should override this method, call
18480      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
18481      * </p>
18482      */
onCancelPendingInputEvents()18483     public void onCancelPendingInputEvents() {
18484         removePerformClickCallback();
18485         cancelLongPress();
18486         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
18487     }
18488 
18489     /**
18490      * Store this view hierarchy's frozen state into the given container.
18491      *
18492      * @param container The SparseArray in which to save the view's state.
18493      *
18494      * @see #restoreHierarchyState(android.util.SparseArray)
18495      * @see #dispatchSaveInstanceState(android.util.SparseArray)
18496      * @see #onSaveInstanceState()
18497      */
saveHierarchyState(SparseArray<Parcelable> container)18498     public void saveHierarchyState(SparseArray<Parcelable> container) {
18499         dispatchSaveInstanceState(container);
18500     }
18501 
18502     /**
18503      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
18504      * this view and its children. May be overridden to modify how freezing happens to a
18505      * view's children; for example, some views may want to not store state for their children.
18506      *
18507      * @param container The SparseArray in which to save the view's state.
18508      *
18509      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
18510      * @see #saveHierarchyState(android.util.SparseArray)
18511      * @see #onSaveInstanceState()
18512      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)18513     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
18514         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
18515             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
18516             Parcelable state = onSaveInstanceState();
18517             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
18518                 throw new IllegalStateException(
18519                         "Derived class did not call super.onSaveInstanceState()");
18520             }
18521             if (state != null) {
18522                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
18523                 // + ": " + state);
18524                 container.put(mID, state);
18525             }
18526         }
18527     }
18528 
18529     /**
18530      * Hook allowing a view to generate a representation of its internal state
18531      * that can later be used to create a new instance with that same state.
18532      * This state should only contain information that is not persistent or can
18533      * not be reconstructed later. For example, you will never store your
18534      * current position on screen because that will be computed again when a
18535      * new instance of the view is placed in its view hierarchy.
18536      * <p>
18537      * Some examples of things you may store here: the current cursor position
18538      * in a text view (but usually not the text itself since that is stored in a
18539      * content provider or other persistent storage), the currently selected
18540      * item in a list view.
18541      *
18542      * @return Returns a Parcelable object containing the view's current dynamic
18543      *         state, or null if there is nothing interesting to save.
18544      * @see #onRestoreInstanceState(Parcelable)
18545      * @see #saveHierarchyState(SparseArray)
18546      * @see #dispatchSaveInstanceState(SparseArray)
18547      * @see #setSaveEnabled(boolean)
18548      */
18549     @CallSuper
onSaveInstanceState()18550     @Nullable protected Parcelable onSaveInstanceState() {
18551         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
18552         if (mStartActivityRequestWho != null || isAutofilled()
18553                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
18554             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
18555 
18556             if (mStartActivityRequestWho != null) {
18557                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
18558             }
18559 
18560             if (isAutofilled()) {
18561                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
18562             }
18563 
18564             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
18565                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
18566             }
18567 
18568             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
18569             state.mIsAutofilled = isAutofilled();
18570             state.mAutofillViewId = mAutofillViewId;
18571             return state;
18572         }
18573         return BaseSavedState.EMPTY_STATE;
18574     }
18575 
18576     /**
18577      * Restore this view hierarchy's frozen state from the given container.
18578      *
18579      * @param container The SparseArray which holds previously frozen states.
18580      *
18581      * @see #saveHierarchyState(android.util.SparseArray)
18582      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
18583      * @see #onRestoreInstanceState(android.os.Parcelable)
18584      */
restoreHierarchyState(SparseArray<Parcelable> container)18585     public void restoreHierarchyState(SparseArray<Parcelable> container) {
18586         dispatchRestoreInstanceState(container);
18587     }
18588 
18589     /**
18590      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
18591      * state for this view and its children. May be overridden to modify how restoring
18592      * happens to a view's children; for example, some views may want to not store state
18593      * for their children.
18594      *
18595      * @param container The SparseArray which holds previously saved state.
18596      *
18597      * @see #dispatchSaveInstanceState(android.util.SparseArray)
18598      * @see #restoreHierarchyState(android.util.SparseArray)
18599      * @see #onRestoreInstanceState(android.os.Parcelable)
18600      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)18601     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
18602         if (mID != NO_ID) {
18603             Parcelable state = container.get(mID);
18604             if (state != null) {
18605                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
18606                 // + ": " + state);
18607                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
18608                 onRestoreInstanceState(state);
18609                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
18610                     throw new IllegalStateException(
18611                             "Derived class did not call super.onRestoreInstanceState()");
18612                 }
18613             }
18614         }
18615     }
18616 
18617     /**
18618      * Hook allowing a view to re-apply a representation of its internal state that had previously
18619      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
18620      * null state.
18621      *
18622      * @param state The frozen state that had previously been returned by
18623      *        {@link #onSaveInstanceState}.
18624      *
18625      * @see #onSaveInstanceState()
18626      * @see #restoreHierarchyState(android.util.SparseArray)
18627      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
18628      */
18629     @CallSuper
onRestoreInstanceState(Parcelable state)18630     protected void onRestoreInstanceState(Parcelable state) {
18631         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
18632         if (state != null && !(state instanceof AbsSavedState)) {
18633             throw new IllegalArgumentException("Wrong state class, expecting View State but "
18634                     + "received " + state.getClass().toString() + " instead. This usually happens "
18635                     + "when two views of different type have the same id in the same hierarchy. "
18636                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
18637                     + "other views do not use the same id.");
18638         }
18639         if (state != null && state instanceof BaseSavedState) {
18640             BaseSavedState baseState = (BaseSavedState) state;
18641 
18642             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
18643                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
18644             }
18645             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
18646                 setAutofilled(baseState.mIsAutofilled);
18647             }
18648             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
18649                 // It can happen that views have the same view id and the restoration path will not
18650                 // be able to distinguish between them. The autofill id needs to be unique though.
18651                 // Hence prevent the same autofill view id from being restored multiple times.
18652                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
18653 
18654                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
18655                     // Ignore when view already set it through setAutofillId();
18656                     if (android.view.autofill.Helper.sDebug) {
18657                         Log.d(VIEW_LOG_TAG, "onRestoreInstanceState(): not setting autofillId to "
18658                                 + baseState.mAutofillViewId + " because view explicitly set it to "
18659                                 + mAutofillId);
18660                     }
18661                 } else {
18662                     mAutofillViewId = baseState.mAutofillViewId;
18663                     mAutofillId = null; // will be set on demand by getAutofillId()
18664                 }
18665             }
18666         }
18667     }
18668 
18669     /**
18670      * <p>Return the time at which the drawing of the view hierarchy started.</p>
18671      *
18672      * @return the drawing start time in milliseconds
18673      */
getDrawingTime()18674     public long getDrawingTime() {
18675         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
18676     }
18677 
18678     /**
18679      * <p>Enables or disables the duplication of the parent's state into this view. When
18680      * duplication is enabled, this view gets its drawable state from its parent rather
18681      * than from its own internal properties.</p>
18682      *
18683      * <p>Note: in the current implementation, setting this property to true after the
18684      * view was added to a ViewGroup might have no effect at all. This property should
18685      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
18686      *
18687      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
18688      * property is enabled, an exception will be thrown.</p>
18689      *
18690      * <p>Note: if the child view uses and updates additional states which are unknown to the
18691      * parent, these states should not be affected by this method.</p>
18692      *
18693      * @param enabled True to enable duplication of the parent's drawable state, false
18694      *                to disable it.
18695      *
18696      * @see #getDrawableState()
18697      * @see #isDuplicateParentStateEnabled()
18698      */
setDuplicateParentStateEnabled(boolean enabled)18699     public void setDuplicateParentStateEnabled(boolean enabled) {
18700         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
18701     }
18702 
18703     /**
18704      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
18705      *
18706      * @return True if this view's drawable state is duplicated from the parent,
18707      *         false otherwise
18708      *
18709      * @see #getDrawableState()
18710      * @see #setDuplicateParentStateEnabled(boolean)
18711      */
isDuplicateParentStateEnabled()18712     public boolean isDuplicateParentStateEnabled() {
18713         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
18714     }
18715 
18716     /**
18717      * <p>Specifies the type of layer backing this view. The layer can be
18718      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
18719      * {@link #LAYER_TYPE_HARDWARE}.</p>
18720      *
18721      * <p>A layer is associated with an optional {@link android.graphics.Paint}
18722      * instance that controls how the layer is composed on screen. The following
18723      * properties of the paint are taken into account when composing the layer:</p>
18724      * <ul>
18725      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
18726      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
18727      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
18728      * </ul>
18729      *
18730      * <p>If this view has an alpha value set to < 1.0 by calling
18731      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
18732      * by this view's alpha value.</p>
18733      *
18734      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
18735      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
18736      * for more information on when and how to use layers.</p>
18737      *
18738      * @param layerType The type of layer to use with this view, must be one of
18739      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
18740      *        {@link #LAYER_TYPE_HARDWARE}
18741      * @param paint The paint used to compose the layer. This argument is optional
18742      *        and can be null. It is ignored when the layer type is
18743      *        {@link #LAYER_TYPE_NONE}
18744      *
18745      * @see #getLayerType()
18746      * @see #LAYER_TYPE_NONE
18747      * @see #LAYER_TYPE_SOFTWARE
18748      * @see #LAYER_TYPE_HARDWARE
18749      * @see #setAlpha(float)
18750      *
18751      * @attr ref android.R.styleable#View_layerType
18752      */
setLayerType(int layerType, @Nullable Paint paint)18753     public void setLayerType(int layerType, @Nullable Paint paint) {
18754         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
18755             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
18756                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
18757         }
18758 
18759         boolean typeChanged = mRenderNode.setLayerType(layerType);
18760 
18761         if (!typeChanged) {
18762             setLayerPaint(paint);
18763             return;
18764         }
18765 
18766         if (layerType != LAYER_TYPE_SOFTWARE) {
18767             // Destroy any previous software drawing cache if present
18768             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
18769             // drawing cache created in View#draw when drawing to a SW canvas.
18770             destroyDrawingCache();
18771         }
18772 
18773         mLayerType = layerType;
18774         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
18775         mRenderNode.setLayerPaint(mLayerPaint);
18776 
18777         // draw() behaves differently if we are on a layer, so we need to
18778         // invalidate() here
18779         invalidateParentCaches();
18780         invalidate(true);
18781     }
18782 
18783     /**
18784      * Updates the {@link Paint} object used with the current layer (used only if the current
18785      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
18786      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
18787      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
18788      * ensure that the view gets redrawn immediately.
18789      *
18790      * <p>A layer is associated with an optional {@link android.graphics.Paint}
18791      * instance that controls how the layer is composed on screen. The following
18792      * properties of the paint are taken into account when composing the layer:</p>
18793      * <ul>
18794      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
18795      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
18796      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
18797      * </ul>
18798      *
18799      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
18800      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
18801      *
18802      * @param paint The paint used to compose the layer. This argument is optional
18803      *        and can be null. It is ignored when the layer type is
18804      *        {@link #LAYER_TYPE_NONE}
18805      *
18806      * @see #setLayerType(int, android.graphics.Paint)
18807      */
setLayerPaint(@ullable Paint paint)18808     public void setLayerPaint(@Nullable Paint paint) {
18809         int layerType = getLayerType();
18810         if (layerType != LAYER_TYPE_NONE) {
18811             mLayerPaint = paint;
18812             if (layerType == LAYER_TYPE_HARDWARE) {
18813                 if (mRenderNode.setLayerPaint(paint)) {
18814                     invalidateViewProperty(false, false);
18815                 }
18816             } else {
18817                 invalidate();
18818             }
18819         }
18820     }
18821 
18822     /**
18823      * Indicates what type of layer is currently associated with this view. By default
18824      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
18825      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
18826      * for more information on the different types of layers.
18827      *
18828      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
18829      *         {@link #LAYER_TYPE_HARDWARE}
18830      *
18831      * @see #setLayerType(int, android.graphics.Paint)
18832      * @see #buildLayer()
18833      * @see #LAYER_TYPE_NONE
18834      * @see #LAYER_TYPE_SOFTWARE
18835      * @see #LAYER_TYPE_HARDWARE
18836      */
getLayerType()18837     public int getLayerType() {
18838         return mLayerType;
18839     }
18840 
18841     /**
18842      * Forces this view's layer to be created and this view to be rendered
18843      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
18844      * invoking this method will have no effect.
18845      *
18846      * This method can for instance be used to render a view into its layer before
18847      * starting an animation. If this view is complex, rendering into the layer
18848      * before starting the animation will avoid skipping frames.
18849      *
18850      * @throws IllegalStateException If this view is not attached to a window
18851      *
18852      * @see #setLayerType(int, android.graphics.Paint)
18853      */
buildLayer()18854     public void buildLayer() {
18855         if (mLayerType == LAYER_TYPE_NONE) return;
18856 
18857         final AttachInfo attachInfo = mAttachInfo;
18858         if (attachInfo == null) {
18859             throw new IllegalStateException("This view must be attached to a window first");
18860         }
18861 
18862         if (getWidth() == 0 || getHeight() == 0) {
18863             return;
18864         }
18865 
18866         switch (mLayerType) {
18867             case LAYER_TYPE_HARDWARE:
18868                 updateDisplayListIfDirty();
18869                 if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
18870                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
18871                 }
18872                 break;
18873             case LAYER_TYPE_SOFTWARE:
18874                 buildDrawingCache(true);
18875                 break;
18876         }
18877     }
18878 
18879     /**
18880      * Destroys all hardware rendering resources. This method is invoked
18881      * when the system needs to reclaim resources. Upon execution of this
18882      * method, you should free any OpenGL resources created by the view.
18883      *
18884      * Note: you <strong>must</strong> call
18885      * <code>super.destroyHardwareResources()</code> when overriding
18886      * this method.
18887      *
18888      * @hide
18889      */
18890     @CallSuper
destroyHardwareResources()18891     protected void destroyHardwareResources() {
18892         if (mOverlay != null) {
18893             mOverlay.getOverlayView().destroyHardwareResources();
18894         }
18895         if (mGhostView != null) {
18896             mGhostView.destroyHardwareResources();
18897         }
18898     }
18899 
18900     /**
18901      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
18902      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
18903      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
18904      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
18905      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
18906      * null.</p>
18907      *
18908      * <p>Enabling the drawing cache is similar to
18909      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
18910      * acceleration is turned off. When hardware acceleration is turned on, enabling the
18911      * drawing cache has no effect on rendering because the system uses a different mechanism
18912      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
18913      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
18914      * for information on how to enable software and hardware layers.</p>
18915      *
18916      * <p>This API can be used to manually generate
18917      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
18918      * {@link #getDrawingCache()}.</p>
18919      *
18920      * @param enabled true to enable the drawing cache, false otherwise
18921      *
18922      * @see #isDrawingCacheEnabled()
18923      * @see #getDrawingCache()
18924      * @see #buildDrawingCache()
18925      * @see #setLayerType(int, android.graphics.Paint)
18926      *
18927      * @deprecated The view drawing cache was largely made obsolete with the introduction of
18928      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
18929      * layers are largely unnecessary and can easily result in a net loss in performance due to the
18930      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
18931      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
18932      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
18933      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
18934      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
18935      * software-rendered usages are discouraged and have compatibility issues with hardware-only
18936      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
18937      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
18938      * reports or unit testing the {@link PixelCopy} API is recommended.
18939      */
18940     @Deprecated
setDrawingCacheEnabled(boolean enabled)18941     public void setDrawingCacheEnabled(boolean enabled) {
18942         mCachingFailed = false;
18943         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
18944     }
18945 
18946     /**
18947      * <p>Indicates whether the drawing cache is enabled for this view.</p>
18948      *
18949      * @return true if the drawing cache is enabled
18950      *
18951      * @see #setDrawingCacheEnabled(boolean)
18952      * @see #getDrawingCache()
18953      *
18954      * @deprecated The view drawing cache was largely made obsolete with the introduction of
18955      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
18956      * layers are largely unnecessary and can easily result in a net loss in performance due to the
18957      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
18958      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
18959      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
18960      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
18961      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
18962      * software-rendered usages are discouraged and have compatibility issues with hardware-only
18963      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
18964      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
18965      * reports or unit testing the {@link PixelCopy} API is recommended.
18966      */
18967     @Deprecated
18968     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()18969     public boolean isDrawingCacheEnabled() {
18970         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
18971     }
18972 
18973     /**
18974      * Debugging utility which recursively outputs the dirty state of a view and its
18975      * descendants.
18976      *
18977      * @hide
18978      */
18979     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)18980     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
18981         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
18982                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
18983                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
18984                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
18985                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
18986         if (clear) {
18987             mPrivateFlags &= clearMask;
18988         }
18989         if (this instanceof ViewGroup) {
18990             ViewGroup parent = (ViewGroup) this;
18991             final int count = parent.getChildCount();
18992             for (int i = 0; i < count; i++) {
18993                 final View child = parent.getChildAt(i);
18994                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
18995             }
18996         }
18997     }
18998 
18999     /**
19000      * This method is used by ViewGroup to cause its children to restore or recreate their
19001      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
19002      * to recreate its own display list, which would happen if it went through the normal
19003      * draw/dispatchDraw mechanisms.
19004      *
19005      * @hide
19006      */
dispatchGetDisplayList()19007     protected void dispatchGetDisplayList() {}
19008 
19009     /**
19010      * A view that is not attached or hardware accelerated cannot create a display list.
19011      * This method checks these conditions and returns the appropriate result.
19012      *
19013      * @return true if view has the ability to create a display list, false otherwise.
19014      *
19015      * @hide
19016      */
canHaveDisplayList()19017     public boolean canHaveDisplayList() {
19018         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
19019     }
19020 
19021     /**
19022      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
19023      * @hide
19024      */
19025     @NonNull
updateDisplayListIfDirty()19026     public RenderNode updateDisplayListIfDirty() {
19027         final RenderNode renderNode = mRenderNode;
19028         if (!canHaveDisplayList()) {
19029             // can't populate RenderNode, don't try
19030             return renderNode;
19031         }
19032 
19033         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
19034                 || !renderNode.isValid()
19035                 || (mRecreateDisplayList)) {
19036             // Don't need to recreate the display list, just need to tell our
19037             // children to restore/recreate theirs
19038             if (renderNode.isValid()
19039                     && !mRecreateDisplayList) {
19040                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
19041                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19042                 dispatchGetDisplayList();
19043 
19044                 return renderNode; // no work needed
19045             }
19046 
19047             // If we got here, we're recreating it. Mark it as such to ensure that
19048             // we copy in child display lists into ours in drawChild()
19049             mRecreateDisplayList = true;
19050 
19051             int width = mRight - mLeft;
19052             int height = mBottom - mTop;
19053             int layerType = getLayerType();
19054 
19055             final DisplayListCanvas canvas = renderNode.start(width, height);
19056 
19057             try {
19058                 if (layerType == LAYER_TYPE_SOFTWARE) {
19059                     buildDrawingCache(true);
19060                     Bitmap cache = getDrawingCache(true);
19061                     if (cache != null) {
19062                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
19063                     }
19064                 } else {
19065                     computeScroll();
19066 
19067                     canvas.translate(-mScrollX, -mScrollY);
19068                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
19069                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19070 
19071                     // Fast path for layouts with no backgrounds
19072                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
19073                         dispatchDraw(canvas);
19074                         drawAutofilledHighlight(canvas);
19075                         if (mOverlay != null && !mOverlay.isEmpty()) {
19076                             mOverlay.getOverlayView().draw(canvas);
19077                         }
19078                         if (debugDraw()) {
19079                             debugDrawFocus(canvas);
19080                         }
19081                     } else {
19082                         draw(canvas);
19083                     }
19084                 }
19085             } finally {
19086                 renderNode.end(canvas);
19087                 setDisplayListProperties(renderNode);
19088             }
19089         } else {
19090             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
19091             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19092         }
19093         return renderNode;
19094     }
19095 
resetDisplayList()19096     private void resetDisplayList() {
19097         mRenderNode.discardDisplayList();
19098         if (mBackgroundRenderNode != null) {
19099             mBackgroundRenderNode.discardDisplayList();
19100         }
19101     }
19102 
19103     /**
19104      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
19105      *
19106      * @return A non-scaled bitmap representing this view or null if cache is disabled.
19107      *
19108      * @see #getDrawingCache(boolean)
19109      *
19110      * @deprecated The view drawing cache was largely made obsolete with the introduction of
19111      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
19112      * layers are largely unnecessary and can easily result in a net loss in performance due to the
19113      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
19114      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
19115      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
19116      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
19117      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
19118      * software-rendered usages are discouraged and have compatibility issues with hardware-only
19119      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
19120      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
19121      * reports or unit testing the {@link PixelCopy} API is recommended.
19122      */
19123     @Deprecated
getDrawingCache()19124     public Bitmap getDrawingCache() {
19125         return getDrawingCache(false);
19126     }
19127 
19128     /**
19129      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
19130      * is null when caching is disabled. If caching is enabled and the cache is not ready,
19131      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
19132      * draw from the cache when the cache is enabled. To benefit from the cache, you must
19133      * request the drawing cache by calling this method and draw it on screen if the
19134      * returned bitmap is not null.</p>
19135      *
19136      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
19137      * this method will create a bitmap of the same size as this view. Because this bitmap
19138      * will be drawn scaled by the parent ViewGroup, the result on screen might show
19139      * scaling artifacts. To avoid such artifacts, you should call this method by setting
19140      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
19141      * size than the view. This implies that your application must be able to handle this
19142      * size.</p>
19143      *
19144      * @param autoScale Indicates whether the generated bitmap should be scaled based on
19145      *        the current density of the screen when the application is in compatibility
19146      *        mode.
19147      *
19148      * @return A bitmap representing this view or null if cache is disabled.
19149      *
19150      * @see #setDrawingCacheEnabled(boolean)
19151      * @see #isDrawingCacheEnabled()
19152      * @see #buildDrawingCache(boolean)
19153      * @see #destroyDrawingCache()
19154      *
19155      * @deprecated The view drawing cache was largely made obsolete with the introduction of
19156      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
19157      * layers are largely unnecessary and can easily result in a net loss in performance due to the
19158      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
19159      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
19160      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
19161      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
19162      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
19163      * software-rendered usages are discouraged and have compatibility issues with hardware-only
19164      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
19165      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
19166      * reports or unit testing the {@link PixelCopy} API is recommended.
19167      */
19168     @Deprecated
getDrawingCache(boolean autoScale)19169     public Bitmap getDrawingCache(boolean autoScale) {
19170         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
19171             return null;
19172         }
19173         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
19174             buildDrawingCache(autoScale);
19175         }
19176         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
19177     }
19178 
19179     /**
19180      * <p>Frees the resources used by the drawing cache. If you call
19181      * {@link #buildDrawingCache()} manually without calling
19182      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
19183      * should cleanup the cache with this method afterwards.</p>
19184      *
19185      * @see #setDrawingCacheEnabled(boolean)
19186      * @see #buildDrawingCache()
19187      * @see #getDrawingCache()
19188      *
19189      * @deprecated The view drawing cache was largely made obsolete with the introduction of
19190      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
19191      * layers are largely unnecessary and can easily result in a net loss in performance due to the
19192      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
19193      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
19194      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
19195      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
19196      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
19197      * software-rendered usages are discouraged and have compatibility issues with hardware-only
19198      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
19199      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
19200      * reports or unit testing the {@link PixelCopy} API is recommended.
19201      */
19202     @Deprecated
destroyDrawingCache()19203     public void destroyDrawingCache() {
19204         if (mDrawingCache != null) {
19205             mDrawingCache.recycle();
19206             mDrawingCache = null;
19207         }
19208         if (mUnscaledDrawingCache != null) {
19209             mUnscaledDrawingCache.recycle();
19210             mUnscaledDrawingCache = null;
19211         }
19212     }
19213 
19214     /**
19215      * Setting a solid background color for the drawing cache's bitmaps will improve
19216      * performance and memory usage. Note, though that this should only be used if this
19217      * view will always be drawn on top of a solid color.
19218      *
19219      * @param color The background color to use for the drawing cache's bitmap
19220      *
19221      * @see #setDrawingCacheEnabled(boolean)
19222      * @see #buildDrawingCache()
19223      * @see #getDrawingCache()
19224      *
19225      * @deprecated The view drawing cache was largely made obsolete with the introduction of
19226      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
19227      * layers are largely unnecessary and can easily result in a net loss in performance due to the
19228      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
19229      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
19230      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
19231      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
19232      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
19233      * software-rendered usages are discouraged and have compatibility issues with hardware-only
19234      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
19235      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
19236      * reports or unit testing the {@link PixelCopy} API is recommended.
19237      */
19238     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)19239     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
19240         if (color != mDrawingCacheBackgroundColor) {
19241             mDrawingCacheBackgroundColor = color;
19242             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
19243         }
19244     }
19245 
19246     /**
19247      * @see #setDrawingCacheBackgroundColor(int)
19248      *
19249      * @return The background color to used for the drawing cache's bitmap
19250      *
19251      * @deprecated The view drawing cache was largely made obsolete with the introduction of
19252      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
19253      * layers are largely unnecessary and can easily result in a net loss in performance due to the
19254      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
19255      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
19256      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
19257      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
19258      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
19259      * software-rendered usages are discouraged and have compatibility issues with hardware-only
19260      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
19261      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
19262      * reports or unit testing the {@link PixelCopy} API is recommended.
19263      */
19264     @Deprecated
19265     @ColorInt
getDrawingCacheBackgroundColor()19266     public int getDrawingCacheBackgroundColor() {
19267         return mDrawingCacheBackgroundColor;
19268     }
19269 
19270     /**
19271      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
19272      *
19273      * @see #buildDrawingCache(boolean)
19274      *
19275      * @deprecated The view drawing cache was largely made obsolete with the introduction of
19276      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
19277      * layers are largely unnecessary and can easily result in a net loss in performance due to the
19278      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
19279      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
19280      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
19281      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
19282      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
19283      * software-rendered usages are discouraged and have compatibility issues with hardware-only
19284      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
19285      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
19286      * reports or unit testing the {@link PixelCopy} API is recommended.
19287      */
19288     @Deprecated
buildDrawingCache()19289     public void buildDrawingCache() {
19290         buildDrawingCache(false);
19291     }
19292 
19293     /**
19294      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
19295      *
19296      * <p>If you call {@link #buildDrawingCache()} manually without calling
19297      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
19298      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
19299      *
19300      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
19301      * this method will create a bitmap of the same size as this view. Because this bitmap
19302      * will be drawn scaled by the parent ViewGroup, the result on screen might show
19303      * scaling artifacts. To avoid such artifacts, you should call this method by setting
19304      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
19305      * size than the view. This implies that your application must be able to handle this
19306      * size.</p>
19307      *
19308      * <p>You should avoid calling this method when hardware acceleration is enabled. If
19309      * you do not need the drawing cache bitmap, calling this method will increase memory
19310      * usage and cause the view to be rendered in software once, thus negatively impacting
19311      * performance.</p>
19312      *
19313      * @see #getDrawingCache()
19314      * @see #destroyDrawingCache()
19315      *
19316      * @deprecated The view drawing cache was largely made obsolete with the introduction of
19317      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
19318      * layers are largely unnecessary and can easily result in a net loss in performance due to the
19319      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
19320      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
19321      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
19322      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
19323      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
19324      * software-rendered usages are discouraged and have compatibility issues with hardware-only
19325      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
19326      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
19327      * reports or unit testing the {@link PixelCopy} API is recommended.
19328      */
19329     @Deprecated
buildDrawingCache(boolean autoScale)19330     public void buildDrawingCache(boolean autoScale) {
19331         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
19332                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
19333             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
19334                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
19335                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
19336             }
19337             try {
19338                 buildDrawingCacheImpl(autoScale);
19339             } finally {
19340                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
19341             }
19342         }
19343     }
19344 
19345     /**
19346      * private, internal implementation of buildDrawingCache, used to enable tracing
19347      */
buildDrawingCacheImpl(boolean autoScale)19348     private void buildDrawingCacheImpl(boolean autoScale) {
19349         mCachingFailed = false;
19350 
19351         int width = mRight - mLeft;
19352         int height = mBottom - mTop;
19353 
19354         final AttachInfo attachInfo = mAttachInfo;
19355         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
19356 
19357         if (autoScale && scalingRequired) {
19358             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
19359             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
19360         }
19361 
19362         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
19363         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
19364         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
19365 
19366         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
19367         final long drawingCacheSize =
19368                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
19369         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
19370             if (width > 0 && height > 0) {
19371                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
19372                         + " too large to fit into a software layer (or drawing cache), needs "
19373                         + projectedBitmapSize + " bytes, only "
19374                         + drawingCacheSize + " available");
19375             }
19376             destroyDrawingCache();
19377             mCachingFailed = true;
19378             return;
19379         }
19380 
19381         boolean clear = true;
19382         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
19383 
19384         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
19385             Bitmap.Config quality;
19386             if (!opaque) {
19387                 // Never pick ARGB_4444 because it looks awful
19388                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
19389                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
19390                     case DRAWING_CACHE_QUALITY_AUTO:
19391                     case DRAWING_CACHE_QUALITY_LOW:
19392                     case DRAWING_CACHE_QUALITY_HIGH:
19393                     default:
19394                         quality = Bitmap.Config.ARGB_8888;
19395                         break;
19396                 }
19397             } else {
19398                 // Optimization for translucent windows
19399                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
19400                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
19401             }
19402 
19403             // Try to cleanup memory
19404             if (bitmap != null) bitmap.recycle();
19405 
19406             try {
19407                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
19408                         width, height, quality);
19409                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
19410                 if (autoScale) {
19411                     mDrawingCache = bitmap;
19412                 } else {
19413                     mUnscaledDrawingCache = bitmap;
19414                 }
19415                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
19416             } catch (OutOfMemoryError e) {
19417                 // If there is not enough memory to create the bitmap cache, just
19418                 // ignore the issue as bitmap caches are not required to draw the
19419                 // view hierarchy
19420                 if (autoScale) {
19421                     mDrawingCache = null;
19422                 } else {
19423                     mUnscaledDrawingCache = null;
19424                 }
19425                 mCachingFailed = true;
19426                 return;
19427             }
19428 
19429             clear = drawingCacheBackgroundColor != 0;
19430         }
19431 
19432         Canvas canvas;
19433         if (attachInfo != null) {
19434             canvas = attachInfo.mCanvas;
19435             if (canvas == null) {
19436                 canvas = new Canvas();
19437             }
19438             canvas.setBitmap(bitmap);
19439             // Temporarily clobber the cached Canvas in case one of our children
19440             // is also using a drawing cache. Without this, the children would
19441             // steal the canvas by attaching their own bitmap to it and bad, bad
19442             // thing would happen (invisible views, corrupted drawings, etc.)
19443             attachInfo.mCanvas = null;
19444         } else {
19445             // This case should hopefully never or seldom happen
19446             canvas = new Canvas(bitmap);
19447         }
19448 
19449         if (clear) {
19450             bitmap.eraseColor(drawingCacheBackgroundColor);
19451         }
19452 
19453         computeScroll();
19454         final int restoreCount = canvas.save();
19455 
19456         if (autoScale && scalingRequired) {
19457             final float scale = attachInfo.mApplicationScale;
19458             canvas.scale(scale, scale);
19459         }
19460 
19461         canvas.translate(-mScrollX, -mScrollY);
19462 
19463         mPrivateFlags |= PFLAG_DRAWN;
19464         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
19465                 mLayerType != LAYER_TYPE_NONE) {
19466             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
19467         }
19468 
19469         // Fast path for layouts with no backgrounds
19470         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
19471             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19472             dispatchDraw(canvas);
19473             drawAutofilledHighlight(canvas);
19474             if (mOverlay != null && !mOverlay.isEmpty()) {
19475                 mOverlay.getOverlayView().draw(canvas);
19476             }
19477         } else {
19478             draw(canvas);
19479         }
19480 
19481         canvas.restoreToCount(restoreCount);
19482         canvas.setBitmap(null);
19483 
19484         if (attachInfo != null) {
19485             // Restore the cached Canvas for our siblings
19486             attachInfo.mCanvas = canvas;
19487         }
19488     }
19489 
19490     /**
19491      * Create a snapshot of the view into a bitmap.  We should probably make
19492      * some form of this public, but should think about the API.
19493      *
19494      * @hide
19495      */
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)19496     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
19497         int width = mRight - mLeft;
19498         int height = mBottom - mTop;
19499 
19500         final AttachInfo attachInfo = mAttachInfo;
19501         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
19502         width = (int) ((width * scale) + 0.5f);
19503         height = (int) ((height * scale) + 0.5f);
19504 
19505         Canvas oldCanvas = null;
19506         try {
19507             Canvas canvas = canvasProvider.getCanvas(this,
19508                     width > 0 ? width : 1, height > 0 ? height : 1);
19509 
19510             if (attachInfo != null) {
19511                 oldCanvas = attachInfo.mCanvas;
19512                 // Temporarily clobber the cached Canvas in case one of our children
19513                 // is also using a drawing cache. Without this, the children would
19514                 // steal the canvas by attaching their own bitmap to it and bad, bad
19515                 // things would happen (invisible views, corrupted drawings, etc.)
19516                 attachInfo.mCanvas = null;
19517             }
19518 
19519             computeScroll();
19520             final int restoreCount = canvas.save();
19521             canvas.scale(scale, scale);
19522             canvas.translate(-mScrollX, -mScrollY);
19523 
19524             // Temporarily remove the dirty mask
19525             int flags = mPrivateFlags;
19526             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19527 
19528             // Fast path for layouts with no backgrounds
19529             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
19530                 dispatchDraw(canvas);
19531                 drawAutofilledHighlight(canvas);
19532                 if (mOverlay != null && !mOverlay.isEmpty()) {
19533                     mOverlay.getOverlayView().draw(canvas);
19534                 }
19535             } else {
19536                 draw(canvas);
19537             }
19538 
19539             mPrivateFlags = flags;
19540             canvas.restoreToCount(restoreCount);
19541             return canvasProvider.createBitmap();
19542         } finally {
19543             if (oldCanvas != null) {
19544                 attachInfo.mCanvas = oldCanvas;
19545             }
19546         }
19547     }
19548 
19549     /**
19550      * Indicates whether this View is currently in edit mode. A View is usually
19551      * in edit mode when displayed within a developer tool. For instance, if
19552      * this View is being drawn by a visual user interface builder, this method
19553      * should return true.
19554      *
19555      * Subclasses should check the return value of this method to provide
19556      * different behaviors if their normal behavior might interfere with the
19557      * host environment. For instance: the class spawns a thread in its
19558      * constructor, the drawing code relies on device-specific features, etc.
19559      *
19560      * This method is usually checked in the drawing code of custom widgets.
19561      *
19562      * @return True if this View is in edit mode, false otherwise.
19563      */
isInEditMode()19564     public boolean isInEditMode() {
19565         return false;
19566     }
19567 
19568     /**
19569      * If the View draws content inside its padding and enables fading edges,
19570      * it needs to support padding offsets. Padding offsets are added to the
19571      * fading edges to extend the length of the fade so that it covers pixels
19572      * drawn inside the padding.
19573      *
19574      * Subclasses of this class should override this method if they need
19575      * to draw content inside the padding.
19576      *
19577      * @return True if padding offset must be applied, false otherwise.
19578      *
19579      * @see #getLeftPaddingOffset()
19580      * @see #getRightPaddingOffset()
19581      * @see #getTopPaddingOffset()
19582      * @see #getBottomPaddingOffset()
19583      *
19584      * @since CURRENT
19585      */
isPaddingOffsetRequired()19586     protected boolean isPaddingOffsetRequired() {
19587         return false;
19588     }
19589 
19590     /**
19591      * Amount by which to extend the left fading region. Called only when
19592      * {@link #isPaddingOffsetRequired()} returns true.
19593      *
19594      * @return The left padding offset in pixels.
19595      *
19596      * @see #isPaddingOffsetRequired()
19597      *
19598      * @since CURRENT
19599      */
getLeftPaddingOffset()19600     protected int getLeftPaddingOffset() {
19601         return 0;
19602     }
19603 
19604     /**
19605      * Amount by which to extend the right fading region. Called only when
19606      * {@link #isPaddingOffsetRequired()} returns true.
19607      *
19608      * @return The right padding offset in pixels.
19609      *
19610      * @see #isPaddingOffsetRequired()
19611      *
19612      * @since CURRENT
19613      */
getRightPaddingOffset()19614     protected int getRightPaddingOffset() {
19615         return 0;
19616     }
19617 
19618     /**
19619      * Amount by which to extend the top fading region. Called only when
19620      * {@link #isPaddingOffsetRequired()} returns true.
19621      *
19622      * @return The top padding offset in pixels.
19623      *
19624      * @see #isPaddingOffsetRequired()
19625      *
19626      * @since CURRENT
19627      */
getTopPaddingOffset()19628     protected int getTopPaddingOffset() {
19629         return 0;
19630     }
19631 
19632     /**
19633      * Amount by which to extend the bottom fading region. Called only when
19634      * {@link #isPaddingOffsetRequired()} returns true.
19635      *
19636      * @return The bottom padding offset in pixels.
19637      *
19638      * @see #isPaddingOffsetRequired()
19639      *
19640      * @since CURRENT
19641      */
getBottomPaddingOffset()19642     protected int getBottomPaddingOffset() {
19643         return 0;
19644     }
19645 
19646     /**
19647      * @hide
19648      * @param offsetRequired
19649      */
getFadeTop(boolean offsetRequired)19650     protected int getFadeTop(boolean offsetRequired) {
19651         int top = mPaddingTop;
19652         if (offsetRequired) top += getTopPaddingOffset();
19653         return top;
19654     }
19655 
19656     /**
19657      * @hide
19658      * @param offsetRequired
19659      */
getFadeHeight(boolean offsetRequired)19660     protected int getFadeHeight(boolean offsetRequired) {
19661         int padding = mPaddingTop;
19662         if (offsetRequired) padding += getTopPaddingOffset();
19663         return mBottom - mTop - mPaddingBottom - padding;
19664     }
19665 
19666     /**
19667      * <p>Indicates whether this view is attached to a hardware accelerated
19668      * window or not.</p>
19669      *
19670      * <p>Even if this method returns true, it does not mean that every call
19671      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
19672      * accelerated {@link android.graphics.Canvas}. For instance, if this view
19673      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
19674      * window is hardware accelerated,
19675      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
19676      * return false, and this method will return true.</p>
19677      *
19678      * @return True if the view is attached to a window and the window is
19679      *         hardware accelerated; false in any other case.
19680      */
19681     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()19682     public boolean isHardwareAccelerated() {
19683         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
19684     }
19685 
19686     /**
19687      * Sets a rectangular area on this view to which the view will be clipped
19688      * when it is drawn. Setting the value to null will remove the clip bounds
19689      * and the view will draw normally, using its full bounds.
19690      *
19691      * @param clipBounds The rectangular area, in the local coordinates of
19692      * this view, to which future drawing operations will be clipped.
19693      */
setClipBounds(Rect clipBounds)19694     public void setClipBounds(Rect clipBounds) {
19695         if (clipBounds == mClipBounds
19696                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
19697             return;
19698         }
19699         if (clipBounds != null) {
19700             if (mClipBounds == null) {
19701                 mClipBounds = new Rect(clipBounds);
19702             } else {
19703                 mClipBounds.set(clipBounds);
19704             }
19705         } else {
19706             mClipBounds = null;
19707         }
19708         mRenderNode.setClipBounds(mClipBounds);
19709         invalidateViewProperty(false, false);
19710     }
19711 
19712     /**
19713      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
19714      *
19715      * @return A copy of the current clip bounds if clip bounds are set,
19716      * otherwise null.
19717      */
getClipBounds()19718     public Rect getClipBounds() {
19719         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
19720     }
19721 
19722 
19723     /**
19724      * Populates an output rectangle with the clip bounds of the view,
19725      * returning {@code true} if successful or {@code false} if the view's
19726      * clip bounds are {@code null}.
19727      *
19728      * @param outRect rectangle in which to place the clip bounds of the view
19729      * @return {@code true} if successful or {@code false} if the view's
19730      *         clip bounds are {@code null}
19731      */
getClipBounds(Rect outRect)19732     public boolean getClipBounds(Rect outRect) {
19733         if (mClipBounds != null) {
19734             outRect.set(mClipBounds);
19735             return true;
19736         }
19737         return false;
19738     }
19739 
19740     /**
19741      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
19742      * case of an active Animation being run on the view.
19743      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)19744     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
19745             Animation a, boolean scalingRequired) {
19746         Transformation invalidationTransform;
19747         final int flags = parent.mGroupFlags;
19748         final boolean initialized = a.isInitialized();
19749         if (!initialized) {
19750             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
19751             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
19752             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
19753             onAnimationStart();
19754         }
19755 
19756         final Transformation t = parent.getChildTransformation();
19757         boolean more = a.getTransformation(drawingTime, t, 1f);
19758         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
19759             if (parent.mInvalidationTransformation == null) {
19760                 parent.mInvalidationTransformation = new Transformation();
19761             }
19762             invalidationTransform = parent.mInvalidationTransformation;
19763             a.getTransformation(drawingTime, invalidationTransform, 1f);
19764         } else {
19765             invalidationTransform = t;
19766         }
19767 
19768         if (more) {
19769             if (!a.willChangeBounds()) {
19770                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
19771                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
19772                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
19773                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
19774                     // The child need to draw an animation, potentially offscreen, so
19775                     // make sure we do not cancel invalidate requests
19776                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
19777                     parent.invalidate(mLeft, mTop, mRight, mBottom);
19778                 }
19779             } else {
19780                 if (parent.mInvalidateRegion == null) {
19781                     parent.mInvalidateRegion = new RectF();
19782                 }
19783                 final RectF region = parent.mInvalidateRegion;
19784                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
19785                         invalidationTransform);
19786 
19787                 // The child need to draw an animation, potentially offscreen, so
19788                 // make sure we do not cancel invalidate requests
19789                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
19790 
19791                 final int left = mLeft + (int) region.left;
19792                 final int top = mTop + (int) region.top;
19793                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
19794                         top + (int) (region.height() + .5f));
19795             }
19796         }
19797         return more;
19798     }
19799 
19800     /**
19801      * This method is called by getDisplayList() when a display list is recorded for a View.
19802      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
19803      */
setDisplayListProperties(RenderNode renderNode)19804     void setDisplayListProperties(RenderNode renderNode) {
19805         if (renderNode != null) {
19806             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
19807             renderNode.setClipToBounds(mParent instanceof ViewGroup
19808                     && ((ViewGroup) mParent).getClipChildren());
19809 
19810             float alpha = 1;
19811             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
19812                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
19813                 ViewGroup parentVG = (ViewGroup) mParent;
19814                 final Transformation t = parentVG.getChildTransformation();
19815                 if (parentVG.getChildStaticTransformation(this, t)) {
19816                     final int transformType = t.getTransformationType();
19817                     if (transformType != Transformation.TYPE_IDENTITY) {
19818                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
19819                             alpha = t.getAlpha();
19820                         }
19821                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
19822                             renderNode.setStaticMatrix(t.getMatrix());
19823                         }
19824                     }
19825                 }
19826             }
19827             if (mTransformationInfo != null) {
19828                 alpha *= getFinalAlpha();
19829                 if (alpha < 1) {
19830                     final int multipliedAlpha = (int) (255 * alpha);
19831                     if (onSetAlpha(multipliedAlpha)) {
19832                         alpha = 1;
19833                     }
19834                 }
19835                 renderNode.setAlpha(alpha);
19836             } else if (alpha < 1) {
19837                 renderNode.setAlpha(alpha);
19838             }
19839         }
19840     }
19841 
19842     /**
19843      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
19844      *
19845      * This is where the View specializes rendering behavior based on layer type,
19846      * and hardware acceleration.
19847      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)19848     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
19849         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
19850         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
19851          *
19852          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
19853          * HW accelerated, it can't handle drawing RenderNodes.
19854          */
19855         boolean drawingWithRenderNode = mAttachInfo != null
19856                 && mAttachInfo.mHardwareAccelerated
19857                 && hardwareAcceleratedCanvas;
19858 
19859         boolean more = false;
19860         final boolean childHasIdentityMatrix = hasIdentityMatrix();
19861         final int parentFlags = parent.mGroupFlags;
19862 
19863         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
19864             parent.getChildTransformation().clear();
19865             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
19866         }
19867 
19868         Transformation transformToApply = null;
19869         boolean concatMatrix = false;
19870         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
19871         final Animation a = getAnimation();
19872         if (a != null) {
19873             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
19874             concatMatrix = a.willChangeTransformationMatrix();
19875             if (concatMatrix) {
19876                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
19877             }
19878             transformToApply = parent.getChildTransformation();
19879         } else {
19880             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
19881                 // No longer animating: clear out old animation matrix
19882                 mRenderNode.setAnimationMatrix(null);
19883                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
19884             }
19885             if (!drawingWithRenderNode
19886                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
19887                 final Transformation t = parent.getChildTransformation();
19888                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
19889                 if (hasTransform) {
19890                     final int transformType = t.getTransformationType();
19891                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
19892                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
19893                 }
19894             }
19895         }
19896 
19897         concatMatrix |= !childHasIdentityMatrix;
19898 
19899         // Sets the flag as early as possible to allow draw() implementations
19900         // to call invalidate() successfully when doing animations
19901         mPrivateFlags |= PFLAG_DRAWN;
19902 
19903         if (!concatMatrix &&
19904                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
19905                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
19906                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
19907                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
19908             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
19909             return more;
19910         }
19911         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
19912 
19913         if (hardwareAcceleratedCanvas) {
19914             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
19915             // retain the flag's value temporarily in the mRecreateDisplayList flag
19916             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
19917             mPrivateFlags &= ~PFLAG_INVALIDATED;
19918         }
19919 
19920         RenderNode renderNode = null;
19921         Bitmap cache = null;
19922         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
19923         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
19924              if (layerType != LAYER_TYPE_NONE) {
19925                  // If not drawing with RenderNode, treat HW layers as SW
19926                  layerType = LAYER_TYPE_SOFTWARE;
19927                  buildDrawingCache(true);
19928             }
19929             cache = getDrawingCache(true);
19930         }
19931 
19932         if (drawingWithRenderNode) {
19933             // Delay getting the display list until animation-driven alpha values are
19934             // set up and possibly passed on to the view
19935             renderNode = updateDisplayListIfDirty();
19936             if (!renderNode.isValid()) {
19937                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
19938                 // to getDisplayList(), the display list will be marked invalid and we should not
19939                 // try to use it again.
19940                 renderNode = null;
19941                 drawingWithRenderNode = false;
19942             }
19943         }
19944 
19945         int sx = 0;
19946         int sy = 0;
19947         if (!drawingWithRenderNode) {
19948             computeScroll();
19949             sx = mScrollX;
19950             sy = mScrollY;
19951         }
19952 
19953         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
19954         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
19955 
19956         int restoreTo = -1;
19957         if (!drawingWithRenderNode || transformToApply != null) {
19958             restoreTo = canvas.save();
19959         }
19960         if (offsetForScroll) {
19961             canvas.translate(mLeft - sx, mTop - sy);
19962         } else {
19963             if (!drawingWithRenderNode) {
19964                 canvas.translate(mLeft, mTop);
19965             }
19966             if (scalingRequired) {
19967                 if (drawingWithRenderNode) {
19968                     // TODO: Might not need this if we put everything inside the DL
19969                     restoreTo = canvas.save();
19970                 }
19971                 // mAttachInfo cannot be null, otherwise scalingRequired == false
19972                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
19973                 canvas.scale(scale, scale);
19974             }
19975         }
19976 
19977         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
19978         if (transformToApply != null
19979                 || alpha < 1
19980                 || !hasIdentityMatrix()
19981                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
19982             if (transformToApply != null || !childHasIdentityMatrix) {
19983                 int transX = 0;
19984                 int transY = 0;
19985 
19986                 if (offsetForScroll) {
19987                     transX = -sx;
19988                     transY = -sy;
19989                 }
19990 
19991                 if (transformToApply != null) {
19992                     if (concatMatrix) {
19993                         if (drawingWithRenderNode) {
19994                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
19995                         } else {
19996                             // Undo the scroll translation, apply the transformation matrix,
19997                             // then redo the scroll translate to get the correct result.
19998                             canvas.translate(-transX, -transY);
19999                             canvas.concat(transformToApply.getMatrix());
20000                             canvas.translate(transX, transY);
20001                         }
20002                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
20003                     }
20004 
20005                     float transformAlpha = transformToApply.getAlpha();
20006                     if (transformAlpha < 1) {
20007                         alpha *= transformAlpha;
20008                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
20009                     }
20010                 }
20011 
20012                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
20013                     canvas.translate(-transX, -transY);
20014                     canvas.concat(getMatrix());
20015                     canvas.translate(transX, transY);
20016                 }
20017             }
20018 
20019             // Deal with alpha if it is or used to be <1
20020             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
20021                 if (alpha < 1) {
20022                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
20023                 } else {
20024                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
20025                 }
20026                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
20027                 if (!drawingWithDrawingCache) {
20028                     final int multipliedAlpha = (int) (255 * alpha);
20029                     if (!onSetAlpha(multipliedAlpha)) {
20030                         if (drawingWithRenderNode) {
20031                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
20032                         } else if (layerType == LAYER_TYPE_NONE) {
20033                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
20034                                     multipliedAlpha);
20035                         }
20036                     } else {
20037                         // Alpha is handled by the child directly, clobber the layer's alpha
20038                         mPrivateFlags |= PFLAG_ALPHA_SET;
20039                     }
20040                 }
20041             }
20042         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
20043             onSetAlpha(255);
20044             mPrivateFlags &= ~PFLAG_ALPHA_SET;
20045         }
20046 
20047         if (!drawingWithRenderNode) {
20048             // apply clips directly, since RenderNode won't do it for this draw
20049             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
20050                 if (offsetForScroll) {
20051                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
20052                 } else {
20053                     if (!scalingRequired || cache == null) {
20054                         canvas.clipRect(0, 0, getWidth(), getHeight());
20055                     } else {
20056                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
20057                     }
20058                 }
20059             }
20060 
20061             if (mClipBounds != null) {
20062                 // clip bounds ignore scroll
20063                 canvas.clipRect(mClipBounds);
20064             }
20065         }
20066 
20067         if (!drawingWithDrawingCache) {
20068             if (drawingWithRenderNode) {
20069                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20070                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
20071             } else {
20072                 // Fast path for layouts with no backgrounds
20073                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
20074                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20075                     dispatchDraw(canvas);
20076                 } else {
20077                     draw(canvas);
20078                 }
20079             }
20080         } else if (cache != null) {
20081             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20082             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
20083                 // no layer paint, use temporary paint to draw bitmap
20084                 Paint cachePaint = parent.mCachePaint;
20085                 if (cachePaint == null) {
20086                     cachePaint = new Paint();
20087                     cachePaint.setDither(false);
20088                     parent.mCachePaint = cachePaint;
20089                 }
20090                 cachePaint.setAlpha((int) (alpha * 255));
20091                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
20092             } else {
20093                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
20094                 int layerPaintAlpha = mLayerPaint.getAlpha();
20095                 if (alpha < 1) {
20096                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
20097                 }
20098                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
20099                 if (alpha < 1) {
20100                     mLayerPaint.setAlpha(layerPaintAlpha);
20101                 }
20102             }
20103         }
20104 
20105         if (restoreTo >= 0) {
20106             canvas.restoreToCount(restoreTo);
20107         }
20108 
20109         if (a != null && !more) {
20110             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
20111                 onSetAlpha(255);
20112             }
20113             parent.finishAnimatingView(this, a);
20114         }
20115 
20116         if (more && hardwareAcceleratedCanvas) {
20117             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
20118                 // alpha animations should cause the child to recreate its display list
20119                 invalidate(true);
20120             }
20121         }
20122 
20123         mRecreateDisplayList = false;
20124 
20125         return more;
20126     }
20127 
getDebugPaint()20128     static Paint getDebugPaint() {
20129         if (sDebugPaint == null) {
20130             sDebugPaint = new Paint();
20131             sDebugPaint.setAntiAlias(false);
20132         }
20133         return sDebugPaint;
20134     }
20135 
dipsToPixels(int dips)20136     final int dipsToPixels(int dips) {
20137         float scale = getContext().getResources().getDisplayMetrics().density;
20138         return (int) (dips * scale + 0.5f);
20139     }
20140 
debugDrawFocus(Canvas canvas)20141     final private void debugDrawFocus(Canvas canvas) {
20142         if (isFocused()) {
20143             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
20144             final int l = mScrollX;
20145             final int r = l + mRight - mLeft;
20146             final int t = mScrollY;
20147             final int b = t + mBottom - mTop;
20148 
20149             final Paint paint = getDebugPaint();
20150             paint.setColor(DEBUG_CORNERS_COLOR);
20151 
20152             // Draw squares in corners.
20153             paint.setStyle(Paint.Style.FILL);
20154             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
20155             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
20156             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
20157             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
20158 
20159             // Draw big X across the view.
20160             paint.setStyle(Paint.Style.STROKE);
20161             canvas.drawLine(l, t, r, b, paint);
20162             canvas.drawLine(l, b, r, t, paint);
20163         }
20164     }
20165 
20166     /**
20167      * Manually render this view (and all of its children) to the given Canvas.
20168      * The view must have already done a full layout before this function is
20169      * called.  When implementing a view, implement
20170      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
20171      * If you do need to override this method, call the superclass version.
20172      *
20173      * @param canvas The Canvas to which the View is rendered.
20174      */
20175     @CallSuper
draw(Canvas canvas)20176     public void draw(Canvas canvas) {
20177         final int privateFlags = mPrivateFlags;
20178         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
20179                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
20180         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
20181 
20182         /*
20183          * Draw traversal performs several drawing steps which must be executed
20184          * in the appropriate order:
20185          *
20186          *      1. Draw the background
20187          *      2. If necessary, save the canvas' layers to prepare for fading
20188          *      3. Draw view's content
20189          *      4. Draw children
20190          *      5. If necessary, draw the fading edges and restore layers
20191          *      6. Draw decorations (scrollbars for instance)
20192          */
20193 
20194         // Step 1, draw the background, if needed
20195         int saveCount;
20196 
20197         if (!dirtyOpaque) {
20198             drawBackground(canvas);
20199         }
20200 
20201         // skip step 2 & 5 if possible (common case)
20202         final int viewFlags = mViewFlags;
20203         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
20204         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
20205         if (!verticalEdges && !horizontalEdges) {
20206             // Step 3, draw the content
20207             if (!dirtyOpaque) onDraw(canvas);
20208 
20209             // Step 4, draw the children
20210             dispatchDraw(canvas);
20211 
20212             drawAutofilledHighlight(canvas);
20213 
20214             // Overlay is part of the content and draws beneath Foreground
20215             if (mOverlay != null && !mOverlay.isEmpty()) {
20216                 mOverlay.getOverlayView().dispatchDraw(canvas);
20217             }
20218 
20219             // Step 6, draw decorations (foreground, scrollbars)
20220             onDrawForeground(canvas);
20221 
20222             // Step 7, draw the default focus highlight
20223             drawDefaultFocusHighlight(canvas);
20224 
20225             if (debugDraw()) {
20226                 debugDrawFocus(canvas);
20227             }
20228 
20229             // we're done...
20230             return;
20231         }
20232 
20233         /*
20234          * Here we do the full fledged routine...
20235          * (this is an uncommon case where speed matters less,
20236          * this is why we repeat some of the tests that have been
20237          * done above)
20238          */
20239 
20240         boolean drawTop = false;
20241         boolean drawBottom = false;
20242         boolean drawLeft = false;
20243         boolean drawRight = false;
20244 
20245         float topFadeStrength = 0.0f;
20246         float bottomFadeStrength = 0.0f;
20247         float leftFadeStrength = 0.0f;
20248         float rightFadeStrength = 0.0f;
20249 
20250         // Step 2, save the canvas' layers
20251         int paddingLeft = mPaddingLeft;
20252 
20253         final boolean offsetRequired = isPaddingOffsetRequired();
20254         if (offsetRequired) {
20255             paddingLeft += getLeftPaddingOffset();
20256         }
20257 
20258         int left = mScrollX + paddingLeft;
20259         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
20260         int top = mScrollY + getFadeTop(offsetRequired);
20261         int bottom = top + getFadeHeight(offsetRequired);
20262 
20263         if (offsetRequired) {
20264             right += getRightPaddingOffset();
20265             bottom += getBottomPaddingOffset();
20266         }
20267 
20268         final ScrollabilityCache scrollabilityCache = mScrollCache;
20269         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
20270         int length = (int) fadeHeight;
20271 
20272         // clip the fade length if top and bottom fades overlap
20273         // overlapping fades produce odd-looking artifacts
20274         if (verticalEdges && (top + length > bottom - length)) {
20275             length = (bottom - top) / 2;
20276         }
20277 
20278         // also clip horizontal fades if necessary
20279         if (horizontalEdges && (left + length > right - length)) {
20280             length = (right - left) / 2;
20281         }
20282 
20283         if (verticalEdges) {
20284             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
20285             drawTop = topFadeStrength * fadeHeight > 1.0f;
20286             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
20287             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
20288         }
20289 
20290         if (horizontalEdges) {
20291             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
20292             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
20293             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
20294             drawRight = rightFadeStrength * fadeHeight > 1.0f;
20295         }
20296 
20297         saveCount = canvas.getSaveCount();
20298 
20299         int solidColor = getSolidColor();
20300         if (solidColor == 0) {
20301             if (drawTop) {
20302                 canvas.saveUnclippedLayer(left, top, right, top + length);
20303             }
20304 
20305             if (drawBottom) {
20306                 canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
20307             }
20308 
20309             if (drawLeft) {
20310                 canvas.saveUnclippedLayer(left, top, left + length, bottom);
20311             }
20312 
20313             if (drawRight) {
20314                 canvas.saveUnclippedLayer(right - length, top, right, bottom);
20315             }
20316         } else {
20317             scrollabilityCache.setFadeColor(solidColor);
20318         }
20319 
20320         // Step 3, draw the content
20321         if (!dirtyOpaque) onDraw(canvas);
20322 
20323         // Step 4, draw the children
20324         dispatchDraw(canvas);
20325 
20326         // Step 5, draw the fade effect and restore layers
20327         final Paint p = scrollabilityCache.paint;
20328         final Matrix matrix = scrollabilityCache.matrix;
20329         final Shader fade = scrollabilityCache.shader;
20330 
20331         if (drawTop) {
20332             matrix.setScale(1, fadeHeight * topFadeStrength);
20333             matrix.postTranslate(left, top);
20334             fade.setLocalMatrix(matrix);
20335             p.setShader(fade);
20336             canvas.drawRect(left, top, right, top + length, p);
20337         }
20338 
20339         if (drawBottom) {
20340             matrix.setScale(1, fadeHeight * bottomFadeStrength);
20341             matrix.postRotate(180);
20342             matrix.postTranslate(left, bottom);
20343             fade.setLocalMatrix(matrix);
20344             p.setShader(fade);
20345             canvas.drawRect(left, bottom - length, right, bottom, p);
20346         }
20347 
20348         if (drawLeft) {
20349             matrix.setScale(1, fadeHeight * leftFadeStrength);
20350             matrix.postRotate(-90);
20351             matrix.postTranslate(left, top);
20352             fade.setLocalMatrix(matrix);
20353             p.setShader(fade);
20354             canvas.drawRect(left, top, left + length, bottom, p);
20355         }
20356 
20357         if (drawRight) {
20358             matrix.setScale(1, fadeHeight * rightFadeStrength);
20359             matrix.postRotate(90);
20360             matrix.postTranslate(right, top);
20361             fade.setLocalMatrix(matrix);
20362             p.setShader(fade);
20363             canvas.drawRect(right - length, top, right, bottom, p);
20364         }
20365 
20366         canvas.restoreToCount(saveCount);
20367 
20368         drawAutofilledHighlight(canvas);
20369 
20370         // Overlay is part of the content and draws beneath Foreground
20371         if (mOverlay != null && !mOverlay.isEmpty()) {
20372             mOverlay.getOverlayView().dispatchDraw(canvas);
20373         }
20374 
20375         // Step 6, draw decorations (foreground, scrollbars)
20376         onDrawForeground(canvas);
20377 
20378         if (debugDraw()) {
20379             debugDrawFocus(canvas);
20380         }
20381     }
20382 
20383     /**
20384      * Draws the background onto the specified canvas.
20385      *
20386      * @param canvas Canvas on which to draw the background
20387      */
drawBackground(Canvas canvas)20388     private void drawBackground(Canvas canvas) {
20389         final Drawable background = mBackground;
20390         if (background == null) {
20391             return;
20392         }
20393 
20394         setBackgroundBounds();
20395 
20396         // Attempt to use a display list if requested.
20397         if (canvas.isHardwareAccelerated() && mAttachInfo != null
20398                 && mAttachInfo.mThreadedRenderer != null) {
20399             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
20400 
20401             final RenderNode renderNode = mBackgroundRenderNode;
20402             if (renderNode != null && renderNode.isValid()) {
20403                 setBackgroundRenderNodeProperties(renderNode);
20404                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
20405                 return;
20406             }
20407         }
20408 
20409         final int scrollX = mScrollX;
20410         final int scrollY = mScrollY;
20411         if ((scrollX | scrollY) == 0) {
20412             background.draw(canvas);
20413         } else {
20414             canvas.translate(scrollX, scrollY);
20415             background.draw(canvas);
20416             canvas.translate(-scrollX, -scrollY);
20417         }
20418     }
20419 
20420     /**
20421      * Sets the correct background bounds and rebuilds the outline, if needed.
20422      * <p/>
20423      * This is called by LayoutLib.
20424      */
setBackgroundBounds()20425     void setBackgroundBounds() {
20426         if (mBackgroundSizeChanged && mBackground != null) {
20427             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
20428             mBackgroundSizeChanged = false;
20429             rebuildOutline();
20430         }
20431     }
20432 
setBackgroundRenderNodeProperties(RenderNode renderNode)20433     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
20434         renderNode.setTranslationX(mScrollX);
20435         renderNode.setTranslationY(mScrollY);
20436     }
20437 
20438     /**
20439      * Creates a new display list or updates the existing display list for the
20440      * specified Drawable.
20441      *
20442      * @param drawable Drawable for which to create a display list
20443      * @param renderNode Existing RenderNode, or {@code null}
20444      * @return A valid display list for the specified drawable
20445      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)20446     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
20447         if (renderNode == null) {
20448             renderNode = RenderNode.create(drawable.getClass().getName(), this);
20449         }
20450 
20451         final Rect bounds = drawable.getBounds();
20452         final int width = bounds.width();
20453         final int height = bounds.height();
20454         final DisplayListCanvas canvas = renderNode.start(width, height);
20455 
20456         // Reverse left/top translation done by drawable canvas, which will
20457         // instead be applied by rendernode's LTRB bounds below. This way, the
20458         // drawable's bounds match with its rendernode bounds and its content
20459         // will lie within those bounds in the rendernode tree.
20460         canvas.translate(-bounds.left, -bounds.top);
20461 
20462         try {
20463             drawable.draw(canvas);
20464         } finally {
20465             renderNode.end(canvas);
20466         }
20467 
20468         // Set up drawable properties that are view-independent.
20469         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
20470         renderNode.setProjectBackwards(drawable.isProjected());
20471         renderNode.setProjectionReceiver(true);
20472         renderNode.setClipToBounds(false);
20473         return renderNode;
20474     }
20475 
20476     /**
20477      * Returns the overlay for this view, creating it if it does not yet exist.
20478      * Adding drawables to the overlay will cause them to be displayed whenever
20479      * the view itself is redrawn. Objects in the overlay should be actively
20480      * managed: remove them when they should not be displayed anymore. The
20481      * overlay will always have the same size as its host view.
20482      *
20483      * <p>Note: Overlays do not currently work correctly with {@link
20484      * SurfaceView} or {@link TextureView}; contents in overlays for these
20485      * types of views may not display correctly.</p>
20486      *
20487      * @return The ViewOverlay object for this view.
20488      * @see ViewOverlay
20489      */
getOverlay()20490     public ViewOverlay getOverlay() {
20491         if (mOverlay == null) {
20492             mOverlay = new ViewOverlay(mContext, this);
20493         }
20494         return mOverlay;
20495     }
20496 
20497     /**
20498      * Override this if your view is known to always be drawn on top of a solid color background,
20499      * and needs to draw fading edges. Returning a non-zero color enables the view system to
20500      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
20501      * should be set to 0xFF.
20502      *
20503      * @see #setVerticalFadingEdgeEnabled(boolean)
20504      * @see #setHorizontalFadingEdgeEnabled(boolean)
20505      *
20506      * @return The known solid color background for this view, or 0 if the color may vary
20507      */
20508     @ViewDebug.ExportedProperty(category = "drawing")
20509     @ColorInt
getSolidColor()20510     public int getSolidColor() {
20511         return 0;
20512     }
20513 
20514     /**
20515      * Build a human readable string representation of the specified view flags.
20516      *
20517      * @param flags the view flags to convert to a string
20518      * @return a String representing the supplied flags
20519      */
printFlags(int flags)20520     private static String printFlags(int flags) {
20521         String output = "";
20522         int numFlags = 0;
20523         if ((flags & FOCUSABLE) == FOCUSABLE) {
20524             output += "TAKES_FOCUS";
20525             numFlags++;
20526         }
20527 
20528         switch (flags & VISIBILITY_MASK) {
20529         case INVISIBLE:
20530             if (numFlags > 0) {
20531                 output += " ";
20532             }
20533             output += "INVISIBLE";
20534             // USELESS HERE numFlags++;
20535             break;
20536         case GONE:
20537             if (numFlags > 0) {
20538                 output += " ";
20539             }
20540             output += "GONE";
20541             // USELESS HERE numFlags++;
20542             break;
20543         default:
20544             break;
20545         }
20546         return output;
20547     }
20548 
20549     /**
20550      * Build a human readable string representation of the specified private
20551      * view flags.
20552      *
20553      * @param privateFlags the private view flags to convert to a string
20554      * @return a String representing the supplied flags
20555      */
printPrivateFlags(int privateFlags)20556     private static String printPrivateFlags(int privateFlags) {
20557         String output = "";
20558         int numFlags = 0;
20559 
20560         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
20561             output += "WANTS_FOCUS";
20562             numFlags++;
20563         }
20564 
20565         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
20566             if (numFlags > 0) {
20567                 output += " ";
20568             }
20569             output += "FOCUSED";
20570             numFlags++;
20571         }
20572 
20573         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
20574             if (numFlags > 0) {
20575                 output += " ";
20576             }
20577             output += "SELECTED";
20578             numFlags++;
20579         }
20580 
20581         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
20582             if (numFlags > 0) {
20583                 output += " ";
20584             }
20585             output += "IS_ROOT_NAMESPACE";
20586             numFlags++;
20587         }
20588 
20589         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
20590             if (numFlags > 0) {
20591                 output += " ";
20592             }
20593             output += "HAS_BOUNDS";
20594             numFlags++;
20595         }
20596 
20597         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
20598             if (numFlags > 0) {
20599                 output += " ";
20600             }
20601             output += "DRAWN";
20602             // USELESS HERE numFlags++;
20603         }
20604         return output;
20605     }
20606 
20607     /**
20608      * <p>Indicates whether or not this view's layout will be requested during
20609      * the next hierarchy layout pass.</p>
20610      *
20611      * @return true if the layout will be forced during next layout pass
20612      */
isLayoutRequested()20613     public boolean isLayoutRequested() {
20614         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
20615     }
20616 
20617     /**
20618      * Return true if o is a ViewGroup that is laying out using optical bounds.
20619      * @hide
20620      */
isLayoutModeOptical(Object o)20621     public static boolean isLayoutModeOptical(Object o) {
20622         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
20623     }
20624 
setOpticalFrame(int left, int top, int right, int bottom)20625     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
20626         Insets parentInsets = mParent instanceof View ?
20627                 ((View) mParent).getOpticalInsets() : Insets.NONE;
20628         Insets childInsets = getOpticalInsets();
20629         return setFrame(
20630                 left   + parentInsets.left - childInsets.left,
20631                 top    + parentInsets.top  - childInsets.top,
20632                 right  + parentInsets.left + childInsets.right,
20633                 bottom + parentInsets.top  + childInsets.bottom);
20634     }
20635 
20636     /**
20637      * Assign a size and position to a view and all of its
20638      * descendants
20639      *
20640      * <p>This is the second phase of the layout mechanism.
20641      * (The first is measuring). In this phase, each parent calls
20642      * layout on all of its children to position them.
20643      * This is typically done using the child measurements
20644      * that were stored in the measure pass().</p>
20645      *
20646      * <p>Derived classes should not override this method.
20647      * Derived classes with children should override
20648      * onLayout. In that method, they should
20649      * call layout on each of their children.</p>
20650      *
20651      * @param l Left position, relative to parent
20652      * @param t Top position, relative to parent
20653      * @param r Right position, relative to parent
20654      * @param b Bottom position, relative to parent
20655      */
20656     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)20657     public void layout(int l, int t, int r, int b) {
20658         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
20659             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
20660             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20661         }
20662 
20663         int oldL = mLeft;
20664         int oldT = mTop;
20665         int oldB = mBottom;
20666         int oldR = mRight;
20667 
20668         boolean changed = isLayoutModeOptical(mParent) ?
20669                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
20670 
20671         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
20672             onLayout(changed, l, t, r, b);
20673 
20674             if (shouldDrawRoundScrollbar()) {
20675                 if(mRoundScrollbarRenderer == null) {
20676                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
20677                 }
20678             } else {
20679                 mRoundScrollbarRenderer = null;
20680             }
20681 
20682             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
20683 
20684             ListenerInfo li = mListenerInfo;
20685             if (li != null && li.mOnLayoutChangeListeners != null) {
20686                 ArrayList<OnLayoutChangeListener> listenersCopy =
20687                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
20688                 int numListeners = listenersCopy.size();
20689                 for (int i = 0; i < numListeners; ++i) {
20690                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
20691                 }
20692             }
20693         }
20694 
20695         final boolean wasLayoutValid = isLayoutValid();
20696 
20697         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
20698         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
20699 
20700         if (!wasLayoutValid && isFocused()) {
20701             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
20702             if (canTakeFocus()) {
20703                 // We have a robust focus, so parents should no longer be wanting focus.
20704                 clearParentsWantFocus();
20705             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
20706                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
20707                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
20708                 // and thus the safest action is to clear focus here.
20709                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
20710                 clearParentsWantFocus();
20711             } else if (!hasParentWantsFocus()) {
20712                 // original requestFocus was likely on this view directly, so just clear focus
20713                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
20714             }
20715             // otherwise, we let parents handle re-assigning focus during their layout passes.
20716         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
20717             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
20718             View focused = findFocus();
20719             if (focused != null) {
20720                 // Try to restore focus as close as possible to our starting focus.
20721                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
20722                     // Give up and clear focus once we've reached the top-most parent which wants
20723                     // focus.
20724                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
20725                 }
20726             }
20727         }
20728 
20729         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
20730             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
20731             notifyEnterOrExitForAutoFillIfNeeded(true);
20732         }
20733     }
20734 
hasParentWantsFocus()20735     private boolean hasParentWantsFocus() {
20736         ViewParent parent = mParent;
20737         while (parent instanceof ViewGroup) {
20738             ViewGroup pv = (ViewGroup) parent;
20739             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
20740                 return true;
20741             }
20742             parent = pv.mParent;
20743         }
20744         return false;
20745     }
20746 
20747     /**
20748      * Called from layout when this view should
20749      * assign a size and position to each of its children.
20750      *
20751      * Derived classes with children should override
20752      * this method and call layout on each of
20753      * their children.
20754      * @param changed This is a new size or position for this view
20755      * @param left Left position, relative to parent
20756      * @param top Top position, relative to parent
20757      * @param right Right position, relative to parent
20758      * @param bottom Bottom position, relative to parent
20759      */
onLayout(boolean changed, int left, int top, int right, int bottom)20760     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
20761     }
20762 
20763     /**
20764      * Assign a size and position to this view.
20765      *
20766      * This is called from layout.
20767      *
20768      * @param left Left position, relative to parent
20769      * @param top Top position, relative to parent
20770      * @param right Right position, relative to parent
20771      * @param bottom Bottom position, relative to parent
20772      * @return true if the new size and position are different than the
20773      *         previous ones
20774      * {@hide}
20775      */
setFrame(int left, int top, int right, int bottom)20776     protected boolean setFrame(int left, int top, int right, int bottom) {
20777         boolean changed = false;
20778 
20779         if (DBG) {
20780             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
20781                     + right + "," + bottom + ")");
20782         }
20783 
20784         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
20785             changed = true;
20786 
20787             // Remember our drawn bit
20788             int drawn = mPrivateFlags & PFLAG_DRAWN;
20789 
20790             int oldWidth = mRight - mLeft;
20791             int oldHeight = mBottom - mTop;
20792             int newWidth = right - left;
20793             int newHeight = bottom - top;
20794             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
20795 
20796             // Invalidate our old position
20797             invalidate(sizeChanged);
20798 
20799             mLeft = left;
20800             mTop = top;
20801             mRight = right;
20802             mBottom = bottom;
20803             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
20804 
20805             mPrivateFlags |= PFLAG_HAS_BOUNDS;
20806 
20807 
20808             if (sizeChanged) {
20809                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
20810             }
20811 
20812             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
20813                 // If we are visible, force the DRAWN bit to on so that
20814                 // this invalidate will go through (at least to our parent).
20815                 // This is because someone may have invalidated this view
20816                 // before this call to setFrame came in, thereby clearing
20817                 // the DRAWN bit.
20818                 mPrivateFlags |= PFLAG_DRAWN;
20819                 invalidate(sizeChanged);
20820                 // parent display list may need to be recreated based on a change in the bounds
20821                 // of any child
20822                 invalidateParentCaches();
20823             }
20824 
20825             // Reset drawn bit to original value (invalidate turns it off)
20826             mPrivateFlags |= drawn;
20827 
20828             mBackgroundSizeChanged = true;
20829             mDefaultFocusHighlightSizeChanged = true;
20830             if (mForegroundInfo != null) {
20831                 mForegroundInfo.mBoundsChanged = true;
20832             }
20833 
20834             notifySubtreeAccessibilityStateChangedIfNeeded();
20835         }
20836         return changed;
20837     }
20838 
20839     /**
20840      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
20841      * @hide
20842      */
setLeftTopRightBottom(int left, int top, int right, int bottom)20843     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
20844         setFrame(left, top, right, bottom);
20845     }
20846 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)20847     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
20848         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
20849         if (mOverlay != null) {
20850             mOverlay.getOverlayView().setRight(newWidth);
20851             mOverlay.getOverlayView().setBottom(newHeight);
20852         }
20853         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
20854         // backtracking" of requestFocus during layout, so don't touch focus here.
20855         if (!sCanFocusZeroSized && isLayoutValid()
20856                 // Don't touch focus if animating
20857                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
20858             if (newWidth <= 0 || newHeight <= 0) {
20859                 if (hasFocus()) {
20860                     clearFocus();
20861                     if (mParent instanceof ViewGroup) {
20862                         ((ViewGroup) mParent).clearFocusedInCluster();
20863                     }
20864                 }
20865                 clearAccessibilityFocus();
20866             } else if (oldWidth <= 0 || oldHeight <= 0) {
20867                 if (mParent != null && canTakeFocus()) {
20868                     mParent.focusableViewAvailable(this);
20869                 }
20870             }
20871         }
20872         rebuildOutline();
20873     }
20874 
20875     /**
20876      * Finalize inflating a view from XML.  This is called as the last phase
20877      * of inflation, after all child views have been added.
20878      *
20879      * <p>Even if the subclass overrides onFinishInflate, they should always be
20880      * sure to call the super method, so that we get called.
20881      */
20882     @CallSuper
onFinishInflate()20883     protected void onFinishInflate() {
20884     }
20885 
20886     /**
20887      * Returns the resources associated with this view.
20888      *
20889      * @return Resources object.
20890      */
getResources()20891     public Resources getResources() {
20892         return mResources;
20893     }
20894 
20895     /**
20896      * Invalidates the specified Drawable.
20897      *
20898      * @param drawable the drawable to invalidate
20899      */
20900     @Override
invalidateDrawable(@onNull Drawable drawable)20901     public void invalidateDrawable(@NonNull Drawable drawable) {
20902         if (verifyDrawable(drawable)) {
20903             final Rect dirty = drawable.getDirtyBounds();
20904             final int scrollX = mScrollX;
20905             final int scrollY = mScrollY;
20906 
20907             invalidate(dirty.left + scrollX, dirty.top + scrollY,
20908                     dirty.right + scrollX, dirty.bottom + scrollY);
20909             rebuildOutline();
20910         }
20911     }
20912 
20913     /**
20914      * Schedules an action on a drawable to occur at a specified time.
20915      *
20916      * @param who the recipient of the action
20917      * @param what the action to run on the drawable
20918      * @param when the time at which the action must occur. Uses the
20919      *        {@link SystemClock#uptimeMillis} timebase.
20920      */
20921     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)20922     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
20923         if (verifyDrawable(who) && what != null) {
20924             final long delay = when - SystemClock.uptimeMillis();
20925             if (mAttachInfo != null) {
20926                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
20927                         Choreographer.CALLBACK_ANIMATION, what, who,
20928                         Choreographer.subtractFrameDelay(delay));
20929             } else {
20930                 // Postpone the runnable until we know
20931                 // on which thread it needs to run.
20932                 getRunQueue().postDelayed(what, delay);
20933             }
20934         }
20935     }
20936 
20937     /**
20938      * Cancels a scheduled action on a drawable.
20939      *
20940      * @param who the recipient of the action
20941      * @param what the action to cancel
20942      */
20943     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)20944     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
20945         if (verifyDrawable(who) && what != null) {
20946             if (mAttachInfo != null) {
20947                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
20948                         Choreographer.CALLBACK_ANIMATION, what, who);
20949             }
20950             getRunQueue().removeCallbacks(what);
20951         }
20952     }
20953 
20954     /**
20955      * Unschedule any events associated with the given Drawable.  This can be
20956      * used when selecting a new Drawable into a view, so that the previous
20957      * one is completely unscheduled.
20958      *
20959      * @param who The Drawable to unschedule.
20960      *
20961      * @see #drawableStateChanged
20962      */
unscheduleDrawable(Drawable who)20963     public void unscheduleDrawable(Drawable who) {
20964         if (mAttachInfo != null && who != null) {
20965             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
20966                     Choreographer.CALLBACK_ANIMATION, null, who);
20967         }
20968     }
20969 
20970     /**
20971      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
20972      * that the View directionality can and will be resolved before its Drawables.
20973      *
20974      * Will call {@link View#onResolveDrawables} when resolution is done.
20975      *
20976      * @hide
20977      */
resolveDrawables()20978     protected void resolveDrawables() {
20979         // Drawables resolution may need to happen before resolving the layout direction (which is
20980         // done only during the measure() call).
20981         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
20982         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
20983         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
20984         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
20985         // direction to be resolved as its resolved value will be the same as its raw value.
20986         if (!isLayoutDirectionResolved() &&
20987                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
20988             return;
20989         }
20990 
20991         final int layoutDirection = isLayoutDirectionResolved() ?
20992                 getLayoutDirection() : getRawLayoutDirection();
20993 
20994         if (mBackground != null) {
20995             mBackground.setLayoutDirection(layoutDirection);
20996         }
20997         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20998             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
20999         }
21000         if (mDefaultFocusHighlight != null) {
21001             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
21002         }
21003         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
21004         onResolveDrawables(layoutDirection);
21005     }
21006 
areDrawablesResolved()21007     boolean areDrawablesResolved() {
21008         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
21009     }
21010 
21011     /**
21012      * Called when layout direction has been resolved.
21013      *
21014      * The default implementation does nothing.
21015      *
21016      * @param layoutDirection The resolved layout direction.
21017      *
21018      * @see #LAYOUT_DIRECTION_LTR
21019      * @see #LAYOUT_DIRECTION_RTL
21020      *
21021      * @hide
21022      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)21023     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
21024     }
21025 
21026     /**
21027      * @hide
21028      */
resetResolvedDrawables()21029     protected void resetResolvedDrawables() {
21030         resetResolvedDrawablesInternal();
21031     }
21032 
resetResolvedDrawablesInternal()21033     void resetResolvedDrawablesInternal() {
21034         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
21035     }
21036 
21037     /**
21038      * If your view subclass is displaying its own Drawable objects, it should
21039      * override this function and return true for any Drawable it is
21040      * displaying.  This allows animations for those drawables to be
21041      * scheduled.
21042      *
21043      * <p>Be sure to call through to the super class when overriding this
21044      * function.
21045      *
21046      * @param who The Drawable to verify.  Return true if it is one you are
21047      *            displaying, else return the result of calling through to the
21048      *            super class.
21049      *
21050      * @return boolean If true than the Drawable is being displayed in the
21051      *         view; else false and it is not allowed to animate.
21052      *
21053      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
21054      * @see #drawableStateChanged()
21055      */
21056     @CallSuper
verifyDrawable(@onNull Drawable who)21057     protected boolean verifyDrawable(@NonNull Drawable who) {
21058         // Avoid verifying the scroll bar drawable so that we don't end up in
21059         // an invalidation loop. This effectively prevents the scroll bar
21060         // drawable from triggering invalidations and scheduling runnables.
21061         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
21062                 || (mDefaultFocusHighlight == who);
21063     }
21064 
21065     /**
21066      * This function is called whenever the state of the view changes in such
21067      * a way that it impacts the state of drawables being shown.
21068      * <p>
21069      * If the View has a StateListAnimator, it will also be called to run necessary state
21070      * change animations.
21071      * <p>
21072      * Be sure to call through to the superclass when overriding this function.
21073      *
21074      * @see Drawable#setState(int[])
21075      */
21076     @CallSuper
drawableStateChanged()21077     protected void drawableStateChanged() {
21078         final int[] state = getDrawableState();
21079         boolean changed = false;
21080 
21081         final Drawable bg = mBackground;
21082         if (bg != null && bg.isStateful()) {
21083             changed |= bg.setState(state);
21084         }
21085 
21086         final Drawable hl = mDefaultFocusHighlight;
21087         if (hl != null && hl.isStateful()) {
21088             changed |= hl.setState(state);
21089         }
21090 
21091         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
21092         if (fg != null && fg.isStateful()) {
21093             changed |= fg.setState(state);
21094         }
21095 
21096         if (mScrollCache != null) {
21097             final Drawable scrollBar = mScrollCache.scrollBar;
21098             if (scrollBar != null && scrollBar.isStateful()) {
21099                 changed |= scrollBar.setState(state)
21100                         && mScrollCache.state != ScrollabilityCache.OFF;
21101             }
21102         }
21103 
21104         if (mStateListAnimator != null) {
21105             mStateListAnimator.setState(state);
21106         }
21107 
21108         if (changed) {
21109             invalidate();
21110         }
21111     }
21112 
21113     /**
21114      * This function is called whenever the view hotspot changes and needs to
21115      * be propagated to drawables or child views managed by the view.
21116      * <p>
21117      * Dispatching to child views is handled by
21118      * {@link #dispatchDrawableHotspotChanged(float, float)}.
21119      * <p>
21120      * Be sure to call through to the superclass when overriding this function.
21121      *
21122      * @param x hotspot x coordinate
21123      * @param y hotspot y coordinate
21124      */
21125     @CallSuper
drawableHotspotChanged(float x, float y)21126     public void drawableHotspotChanged(float x, float y) {
21127         if (mBackground != null) {
21128             mBackground.setHotspot(x, y);
21129         }
21130         if (mDefaultFocusHighlight != null) {
21131             mDefaultFocusHighlight.setHotspot(x, y);
21132         }
21133         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
21134             mForegroundInfo.mDrawable.setHotspot(x, y);
21135         }
21136 
21137         dispatchDrawableHotspotChanged(x, y);
21138     }
21139 
21140     /**
21141      * Dispatches drawableHotspotChanged to all of this View's children.
21142      *
21143      * @param x hotspot x coordinate
21144      * @param y hotspot y coordinate
21145      * @see #drawableHotspotChanged(float, float)
21146      */
dispatchDrawableHotspotChanged(float x, float y)21147     public void dispatchDrawableHotspotChanged(float x, float y) {
21148     }
21149 
21150     /**
21151      * Call this to force a view to update its drawable state. This will cause
21152      * drawableStateChanged to be called on this view. Views that are interested
21153      * in the new state should call getDrawableState.
21154      *
21155      * @see #drawableStateChanged
21156      * @see #getDrawableState
21157      */
refreshDrawableState()21158     public void refreshDrawableState() {
21159         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
21160         drawableStateChanged();
21161 
21162         ViewParent parent = mParent;
21163         if (parent != null) {
21164             parent.childDrawableStateChanged(this);
21165         }
21166     }
21167 
21168     /**
21169      * Create a default focus highlight if it doesn't exist.
21170      * @return a default focus highlight.
21171      */
getDefaultFocusHighlightDrawable()21172     private Drawable getDefaultFocusHighlightDrawable() {
21173         if (mDefaultFocusHighlightCache == null) {
21174             if (mContext != null) {
21175                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
21176                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
21177                 mDefaultFocusHighlightCache = ta.getDrawable(0);
21178                 ta.recycle();
21179             }
21180         }
21181         return mDefaultFocusHighlightCache;
21182     }
21183 
21184     /**
21185      * Set the current default focus highlight.
21186      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
21187      */
setDefaultFocusHighlight(Drawable highlight)21188     private void setDefaultFocusHighlight(Drawable highlight) {
21189         mDefaultFocusHighlight = highlight;
21190         mDefaultFocusHighlightSizeChanged = true;
21191         if (highlight != null) {
21192             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
21193                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
21194             }
21195             highlight.setLayoutDirection(getLayoutDirection());
21196             if (highlight.isStateful()) {
21197                 highlight.setState(getDrawableState());
21198             }
21199             if (isAttachedToWindow()) {
21200                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
21201             }
21202             // Set callback last, since the view may still be initializing.
21203             highlight.setCallback(this);
21204         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
21205                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
21206             mPrivateFlags |= PFLAG_SKIP_DRAW;
21207         }
21208         invalidate();
21209     }
21210 
21211     /**
21212      * Check whether we need to draw a default focus highlight when this view gets focused,
21213      * which requires:
21214      * <ul>
21215      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
21216      *         is not defined.</li>
21217      *     <li>This view is not in touch mode.</li>
21218      *     <li>This view doesn't opt out for a default focus highlight, via
21219      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
21220      *     <li>This view is attached to window.</li>
21221      * </ul>
21222      * @return {@code true} if a default focus highlight is needed.
21223      * @hide
21224      */
21225     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)21226     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
21227         final boolean lackFocusState = (background == null || !background.isStateful()
21228                 || !background.hasFocusStateSpecified())
21229                 && (foreground == null || !foreground.isStateful()
21230                 || !foreground.hasFocusStateSpecified());
21231         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
21232                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
21233     }
21234 
21235     /**
21236      * When this view is focused, switches on/off the default focused highlight.
21237      * <p>
21238      * This always happens when this view is focused, and only at this moment the default focus
21239      * highlight can be visible.
21240      */
switchDefaultFocusHighlight()21241     private void switchDefaultFocusHighlight() {
21242         if (isFocused()) {
21243             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
21244                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
21245             final boolean active = mDefaultFocusHighlight != null;
21246             if (needed && !active) {
21247                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
21248             } else if (!needed && active) {
21249                 // The highlight is no longer needed, so tear it down.
21250                 setDefaultFocusHighlight(null);
21251             }
21252         }
21253     }
21254 
21255     /**
21256      * Draw the default focus highlight onto the canvas.
21257      * @param canvas the canvas where we're drawing the highlight.
21258      */
drawDefaultFocusHighlight(Canvas canvas)21259     private void drawDefaultFocusHighlight(Canvas canvas) {
21260         if (mDefaultFocusHighlight != null) {
21261             if (mDefaultFocusHighlightSizeChanged) {
21262                 mDefaultFocusHighlightSizeChanged = false;
21263                 final int l = mScrollX;
21264                 final int r = l + mRight - mLeft;
21265                 final int t = mScrollY;
21266                 final int b = t + mBottom - mTop;
21267                 mDefaultFocusHighlight.setBounds(l, t, r, b);
21268             }
21269             mDefaultFocusHighlight.draw(canvas);
21270         }
21271     }
21272 
21273     /**
21274      * Return an array of resource IDs of the drawable states representing the
21275      * current state of the view.
21276      *
21277      * @return The current drawable state
21278      *
21279      * @see Drawable#setState(int[])
21280      * @see #drawableStateChanged()
21281      * @see #onCreateDrawableState(int)
21282      */
getDrawableState()21283     public final int[] getDrawableState() {
21284         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
21285             return mDrawableState;
21286         } else {
21287             mDrawableState = onCreateDrawableState(0);
21288             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
21289             return mDrawableState;
21290         }
21291     }
21292 
21293     /**
21294      * Generate the new {@link android.graphics.drawable.Drawable} state for
21295      * this view. This is called by the view
21296      * system when the cached Drawable state is determined to be invalid.  To
21297      * retrieve the current state, you should use {@link #getDrawableState}.
21298      *
21299      * @param extraSpace if non-zero, this is the number of extra entries you
21300      * would like in the returned array in which you can place your own
21301      * states.
21302      *
21303      * @return Returns an array holding the current {@link Drawable} state of
21304      * the view.
21305      *
21306      * @see #mergeDrawableStates(int[], int[])
21307      */
onCreateDrawableState(int extraSpace)21308     protected int[] onCreateDrawableState(int extraSpace) {
21309         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
21310                 mParent instanceof View) {
21311             return ((View) mParent).onCreateDrawableState(extraSpace);
21312         }
21313 
21314         int[] drawableState;
21315 
21316         int privateFlags = mPrivateFlags;
21317 
21318         int viewStateIndex = 0;
21319         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
21320         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
21321         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
21322         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
21323         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
21324         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
21325         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
21326                 ThreadedRenderer.isAvailable()) {
21327             // This is set if HW acceleration is requested, even if the current
21328             // process doesn't allow it.  This is just to allow app preview
21329             // windows to better match their app.
21330             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
21331         }
21332         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
21333 
21334         final int privateFlags2 = mPrivateFlags2;
21335         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
21336             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
21337         }
21338         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
21339             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
21340         }
21341 
21342         drawableState = StateSet.get(viewStateIndex);
21343 
21344         //noinspection ConstantIfStatement
21345         if (false) {
21346             Log.i("View", "drawableStateIndex=" + viewStateIndex);
21347             Log.i("View", toString()
21348                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
21349                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
21350                     + " fo=" + hasFocus()
21351                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
21352                     + " wf=" + hasWindowFocus()
21353                     + ": " + Arrays.toString(drawableState));
21354         }
21355 
21356         if (extraSpace == 0) {
21357             return drawableState;
21358         }
21359 
21360         final int[] fullState;
21361         if (drawableState != null) {
21362             fullState = new int[drawableState.length + extraSpace];
21363             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
21364         } else {
21365             fullState = new int[extraSpace];
21366         }
21367 
21368         return fullState;
21369     }
21370 
21371     /**
21372      * Merge your own state values in <var>additionalState</var> into the base
21373      * state values <var>baseState</var> that were returned by
21374      * {@link #onCreateDrawableState(int)}.
21375      *
21376      * @param baseState The base state values returned by
21377      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
21378      * own additional state values.
21379      *
21380      * @param additionalState The additional state values you would like
21381      * added to <var>baseState</var>; this array is not modified.
21382      *
21383      * @return As a convenience, the <var>baseState</var> array you originally
21384      * passed into the function is returned.
21385      *
21386      * @see #onCreateDrawableState(int)
21387      */
mergeDrawableStates(int[] baseState, int[] additionalState)21388     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
21389         final int N = baseState.length;
21390         int i = N - 1;
21391         while (i >= 0 && baseState[i] == 0) {
21392             i--;
21393         }
21394         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
21395         return baseState;
21396     }
21397 
21398     /**
21399      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
21400      * on all Drawable objects associated with this view.
21401      * <p>
21402      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
21403      * attached to this view.
21404      */
21405     @CallSuper
jumpDrawablesToCurrentState()21406     public void jumpDrawablesToCurrentState() {
21407         if (mBackground != null) {
21408             mBackground.jumpToCurrentState();
21409         }
21410         if (mStateListAnimator != null) {
21411             mStateListAnimator.jumpToCurrentState();
21412         }
21413         if (mDefaultFocusHighlight != null) {
21414             mDefaultFocusHighlight.jumpToCurrentState();
21415         }
21416         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
21417             mForegroundInfo.mDrawable.jumpToCurrentState();
21418         }
21419     }
21420 
21421     /**
21422      * Sets the background color for this view.
21423      * @param color the color of the background
21424      */
21425     @RemotableViewMethod
setBackgroundColor(@olorInt int color)21426     public void setBackgroundColor(@ColorInt int color) {
21427         if (mBackground instanceof ColorDrawable) {
21428             ((ColorDrawable) mBackground.mutate()).setColor(color);
21429             computeOpaqueFlags();
21430             mBackgroundResource = 0;
21431         } else {
21432             setBackground(new ColorDrawable(color));
21433         }
21434     }
21435 
21436     /**
21437      * Set the background to a given resource. The resource should refer to
21438      * a Drawable object or 0 to remove the background.
21439      * @param resid The identifier of the resource.
21440      *
21441      * @attr ref android.R.styleable#View_background
21442      */
21443     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)21444     public void setBackgroundResource(@DrawableRes int resid) {
21445         if (resid != 0 && resid == mBackgroundResource) {
21446             return;
21447         }
21448 
21449         Drawable d = null;
21450         if (resid != 0) {
21451             d = mContext.getDrawable(resid);
21452         }
21453         setBackground(d);
21454 
21455         mBackgroundResource = resid;
21456     }
21457 
21458     /**
21459      * Set the background to a given Drawable, or remove the background. If the
21460      * background has padding, this View's padding is set to the background's
21461      * padding. However, when a background is removed, this View's padding isn't
21462      * touched. If setting the padding is desired, please use
21463      * {@link #setPadding(int, int, int, int)}.
21464      *
21465      * @param background The Drawable to use as the background, or null to remove the
21466      *        background
21467      */
setBackground(Drawable background)21468     public void setBackground(Drawable background) {
21469         //noinspection deprecation
21470         setBackgroundDrawable(background);
21471     }
21472 
21473     /**
21474      * @deprecated use {@link #setBackground(Drawable)} instead
21475      */
21476     @Deprecated
setBackgroundDrawable(Drawable background)21477     public void setBackgroundDrawable(Drawable background) {
21478         computeOpaqueFlags();
21479 
21480         if (background == mBackground) {
21481             return;
21482         }
21483 
21484         boolean requestLayout = false;
21485 
21486         mBackgroundResource = 0;
21487 
21488         /*
21489          * Regardless of whether we're setting a new background or not, we want
21490          * to clear the previous drawable. setVisible first while we still have the callback set.
21491          */
21492         if (mBackground != null) {
21493             if (isAttachedToWindow()) {
21494                 mBackground.setVisible(false, false);
21495             }
21496             mBackground.setCallback(null);
21497             unscheduleDrawable(mBackground);
21498         }
21499 
21500         if (background != null) {
21501             Rect padding = sThreadLocal.get();
21502             if (padding == null) {
21503                 padding = new Rect();
21504                 sThreadLocal.set(padding);
21505             }
21506             resetResolvedDrawablesInternal();
21507             background.setLayoutDirection(getLayoutDirection());
21508             if (background.getPadding(padding)) {
21509                 resetResolvedPaddingInternal();
21510                 switch (background.getLayoutDirection()) {
21511                     case LAYOUT_DIRECTION_RTL:
21512                         mUserPaddingLeftInitial = padding.right;
21513                         mUserPaddingRightInitial = padding.left;
21514                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
21515                         break;
21516                     case LAYOUT_DIRECTION_LTR:
21517                     default:
21518                         mUserPaddingLeftInitial = padding.left;
21519                         mUserPaddingRightInitial = padding.right;
21520                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
21521                 }
21522                 mLeftPaddingDefined = false;
21523                 mRightPaddingDefined = false;
21524             }
21525 
21526             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
21527             // if it has a different minimum size, we should layout again
21528             if (mBackground == null
21529                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
21530                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
21531                 requestLayout = true;
21532             }
21533 
21534             // Set mBackground before we set this as the callback and start making other
21535             // background drawable state change calls. In particular, the setVisible call below
21536             // can result in drawables attempting to start animations or otherwise invalidate,
21537             // which requires the view set as the callback (us) to recognize the drawable as
21538             // belonging to it as per verifyDrawable.
21539             mBackground = background;
21540             if (background.isStateful()) {
21541                 background.setState(getDrawableState());
21542             }
21543             if (isAttachedToWindow()) {
21544                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
21545             }
21546 
21547             applyBackgroundTint();
21548 
21549             // Set callback last, since the view may still be initializing.
21550             background.setCallback(this);
21551 
21552             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
21553                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
21554                 requestLayout = true;
21555             }
21556         } else {
21557             /* Remove the background */
21558             mBackground = null;
21559             if ((mViewFlags & WILL_NOT_DRAW) != 0
21560                     && (mDefaultFocusHighlight == null)
21561                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
21562                 mPrivateFlags |= PFLAG_SKIP_DRAW;
21563             }
21564 
21565             /*
21566              * When the background is set, we try to apply its padding to this
21567              * View. When the background is removed, we don't touch this View's
21568              * padding. This is noted in the Javadocs. Hence, we don't need to
21569              * requestLayout(), the invalidate() below is sufficient.
21570              */
21571 
21572             // The old background's minimum size could have affected this
21573             // View's layout, so let's requestLayout
21574             requestLayout = true;
21575         }
21576 
21577         computeOpaqueFlags();
21578 
21579         if (requestLayout) {
21580             requestLayout();
21581         }
21582 
21583         mBackgroundSizeChanged = true;
21584         invalidate(true);
21585         invalidateOutline();
21586     }
21587 
21588     /**
21589      * Gets the background drawable
21590      *
21591      * @return The drawable used as the background for this view, if any.
21592      *
21593      * @see #setBackground(Drawable)
21594      *
21595      * @attr ref android.R.styleable#View_background
21596      */
getBackground()21597     public Drawable getBackground() {
21598         return mBackground;
21599     }
21600 
21601     /**
21602      * Applies a tint to the background drawable. Does not modify the current tint
21603      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
21604      * <p>
21605      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
21606      * mutate the drawable and apply the specified tint and tint mode using
21607      * {@link Drawable#setTintList(ColorStateList)}.
21608      *
21609      * @param tint the tint to apply, may be {@code null} to clear tint
21610      *
21611      * @attr ref android.R.styleable#View_backgroundTint
21612      * @see #getBackgroundTintList()
21613      * @see Drawable#setTintList(ColorStateList)
21614      */
setBackgroundTintList(@ullable ColorStateList tint)21615     public void setBackgroundTintList(@Nullable ColorStateList tint) {
21616         if (mBackgroundTint == null) {
21617             mBackgroundTint = new TintInfo();
21618         }
21619         mBackgroundTint.mTintList = tint;
21620         mBackgroundTint.mHasTintList = true;
21621 
21622         applyBackgroundTint();
21623     }
21624 
21625     /**
21626      * Return the tint applied to the background drawable, if specified.
21627      *
21628      * @return the tint applied to the background drawable
21629      * @attr ref android.R.styleable#View_backgroundTint
21630      * @see #setBackgroundTintList(ColorStateList)
21631      */
21632     @Nullable
getBackgroundTintList()21633     public ColorStateList getBackgroundTintList() {
21634         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
21635     }
21636 
21637     /**
21638      * Specifies the blending mode used to apply the tint specified by
21639      * {@link #setBackgroundTintList(ColorStateList)}} to the background
21640      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
21641      *
21642      * @param tintMode the blending mode used to apply the tint, may be
21643      *                 {@code null} to clear tint
21644      * @attr ref android.R.styleable#View_backgroundTintMode
21645      * @see #getBackgroundTintMode()
21646      * @see Drawable#setTintMode(PorterDuff.Mode)
21647      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)21648     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
21649         if (mBackgroundTint == null) {
21650             mBackgroundTint = new TintInfo();
21651         }
21652         mBackgroundTint.mTintMode = tintMode;
21653         mBackgroundTint.mHasTintMode = true;
21654 
21655         applyBackgroundTint();
21656     }
21657 
21658     /**
21659      * Return the blending mode used to apply the tint to the background
21660      * drawable, if specified.
21661      *
21662      * @return the blending mode used to apply the tint to the background
21663      *         drawable
21664      * @attr ref android.R.styleable#View_backgroundTintMode
21665      * @see #setBackgroundTintMode(PorterDuff.Mode)
21666      */
21667     @Nullable
getBackgroundTintMode()21668     public PorterDuff.Mode getBackgroundTintMode() {
21669         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
21670     }
21671 
applyBackgroundTint()21672     private void applyBackgroundTint() {
21673         if (mBackground != null && mBackgroundTint != null) {
21674             final TintInfo tintInfo = mBackgroundTint;
21675             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
21676                 mBackground = mBackground.mutate();
21677 
21678                 if (tintInfo.mHasTintList) {
21679                     mBackground.setTintList(tintInfo.mTintList);
21680                 }
21681 
21682                 if (tintInfo.mHasTintMode) {
21683                     mBackground.setTintMode(tintInfo.mTintMode);
21684                 }
21685 
21686                 // The drawable (or one of its children) may not have been
21687                 // stateful before applying the tint, so let's try again.
21688                 if (mBackground.isStateful()) {
21689                     mBackground.setState(getDrawableState());
21690                 }
21691             }
21692         }
21693     }
21694 
21695     /**
21696      * Returns the drawable used as the foreground of this View. The
21697      * foreground drawable, if non-null, is always drawn on top of the view's content.
21698      *
21699      * @return a Drawable or null if no foreground was set
21700      *
21701      * @see #onDrawForeground(Canvas)
21702      */
getForeground()21703     public Drawable getForeground() {
21704         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
21705     }
21706 
21707     /**
21708      * Supply a Drawable that is to be rendered on top of all of the content in the view.
21709      *
21710      * @param foreground the Drawable to be drawn on top of the children
21711      *
21712      * @attr ref android.R.styleable#View_foreground
21713      */
setForeground(Drawable foreground)21714     public void setForeground(Drawable foreground) {
21715         if (mForegroundInfo == null) {
21716             if (foreground == null) {
21717                 // Nothing to do.
21718                 return;
21719             }
21720             mForegroundInfo = new ForegroundInfo();
21721         }
21722 
21723         if (foreground == mForegroundInfo.mDrawable) {
21724             // Nothing to do
21725             return;
21726         }
21727 
21728         if (mForegroundInfo.mDrawable != null) {
21729             if (isAttachedToWindow()) {
21730                 mForegroundInfo.mDrawable.setVisible(false, false);
21731             }
21732             mForegroundInfo.mDrawable.setCallback(null);
21733             unscheduleDrawable(mForegroundInfo.mDrawable);
21734         }
21735 
21736         mForegroundInfo.mDrawable = foreground;
21737         mForegroundInfo.mBoundsChanged = true;
21738         if (foreground != null) {
21739             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
21740                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
21741             }
21742             foreground.setLayoutDirection(getLayoutDirection());
21743             if (foreground.isStateful()) {
21744                 foreground.setState(getDrawableState());
21745             }
21746             applyForegroundTint();
21747             if (isAttachedToWindow()) {
21748                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
21749             }
21750             // Set callback last, since the view may still be initializing.
21751             foreground.setCallback(this);
21752         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
21753                 && (mDefaultFocusHighlight == null)) {
21754             mPrivateFlags |= PFLAG_SKIP_DRAW;
21755         }
21756         requestLayout();
21757         invalidate();
21758     }
21759 
21760     /**
21761      * Magic bit used to support features of framework-internal window decor implementation details.
21762      * This used to live exclusively in FrameLayout.
21763      *
21764      * @return true if the foreground should draw inside the padding region or false
21765      *         if it should draw inset by the view's padding
21766      * @hide internal use only; only used by FrameLayout and internal screen layouts.
21767      */
isForegroundInsidePadding()21768     public boolean isForegroundInsidePadding() {
21769         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
21770     }
21771 
21772     /**
21773      * Describes how the foreground is positioned.
21774      *
21775      * @return foreground gravity.
21776      *
21777      * @see #setForegroundGravity(int)
21778      *
21779      * @attr ref android.R.styleable#View_foregroundGravity
21780      */
getForegroundGravity()21781     public int getForegroundGravity() {
21782         return mForegroundInfo != null ? mForegroundInfo.mGravity
21783                 : Gravity.START | Gravity.TOP;
21784     }
21785 
21786     /**
21787      * Describes how the foreground is positioned. Defaults to START and TOP.
21788      *
21789      * @param gravity see {@link android.view.Gravity}
21790      *
21791      * @see #getForegroundGravity()
21792      *
21793      * @attr ref android.R.styleable#View_foregroundGravity
21794      */
setForegroundGravity(int gravity)21795     public void setForegroundGravity(int gravity) {
21796         if (mForegroundInfo == null) {
21797             mForegroundInfo = new ForegroundInfo();
21798         }
21799 
21800         if (mForegroundInfo.mGravity != gravity) {
21801             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
21802                 gravity |= Gravity.START;
21803             }
21804 
21805             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
21806                 gravity |= Gravity.TOP;
21807             }
21808 
21809             mForegroundInfo.mGravity = gravity;
21810             requestLayout();
21811         }
21812     }
21813 
21814     /**
21815      * Applies a tint to the foreground drawable. Does not modify the current tint
21816      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
21817      * <p>
21818      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
21819      * mutate the drawable and apply the specified tint and tint mode using
21820      * {@link Drawable#setTintList(ColorStateList)}.
21821      *
21822      * @param tint the tint to apply, may be {@code null} to clear tint
21823      *
21824      * @attr ref android.R.styleable#View_foregroundTint
21825      * @see #getForegroundTintList()
21826      * @see Drawable#setTintList(ColorStateList)
21827      */
setForegroundTintList(@ullable ColorStateList tint)21828     public void setForegroundTintList(@Nullable ColorStateList tint) {
21829         if (mForegroundInfo == null) {
21830             mForegroundInfo = new ForegroundInfo();
21831         }
21832         if (mForegroundInfo.mTintInfo == null) {
21833             mForegroundInfo.mTintInfo = new TintInfo();
21834         }
21835         mForegroundInfo.mTintInfo.mTintList = tint;
21836         mForegroundInfo.mTintInfo.mHasTintList = true;
21837 
21838         applyForegroundTint();
21839     }
21840 
21841     /**
21842      * Return the tint applied to the foreground drawable, if specified.
21843      *
21844      * @return the tint applied to the foreground drawable
21845      * @attr ref android.R.styleable#View_foregroundTint
21846      * @see #setForegroundTintList(ColorStateList)
21847      */
21848     @Nullable
getForegroundTintList()21849     public ColorStateList getForegroundTintList() {
21850         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
21851                 ? mForegroundInfo.mTintInfo.mTintList : null;
21852     }
21853 
21854     /**
21855      * Specifies the blending mode used to apply the tint specified by
21856      * {@link #setForegroundTintList(ColorStateList)}} to the background
21857      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
21858      *
21859      * @param tintMode the blending mode used to apply the tint, may be
21860      *                 {@code null} to clear tint
21861      * @attr ref android.R.styleable#View_foregroundTintMode
21862      * @see #getForegroundTintMode()
21863      * @see Drawable#setTintMode(PorterDuff.Mode)
21864      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)21865     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
21866         if (mForegroundInfo == null) {
21867             mForegroundInfo = new ForegroundInfo();
21868         }
21869         if (mForegroundInfo.mTintInfo == null) {
21870             mForegroundInfo.mTintInfo = new TintInfo();
21871         }
21872         mForegroundInfo.mTintInfo.mTintMode = tintMode;
21873         mForegroundInfo.mTintInfo.mHasTintMode = true;
21874 
21875         applyForegroundTint();
21876     }
21877 
21878     /**
21879      * Return the blending mode used to apply the tint to the foreground
21880      * drawable, if specified.
21881      *
21882      * @return the blending mode used to apply the tint to the foreground
21883      *         drawable
21884      * @attr ref android.R.styleable#View_foregroundTintMode
21885      * @see #setForegroundTintMode(PorterDuff.Mode)
21886      */
21887     @Nullable
getForegroundTintMode()21888     public PorterDuff.Mode getForegroundTintMode() {
21889         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
21890                 ? mForegroundInfo.mTintInfo.mTintMode : null;
21891     }
21892 
applyForegroundTint()21893     private void applyForegroundTint() {
21894         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
21895                 && mForegroundInfo.mTintInfo != null) {
21896             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
21897             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
21898                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
21899 
21900                 if (tintInfo.mHasTintList) {
21901                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
21902                 }
21903 
21904                 if (tintInfo.mHasTintMode) {
21905                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
21906                 }
21907 
21908                 // The drawable (or one of its children) may not have been
21909                 // stateful before applying the tint, so let's try again.
21910                 if (mForegroundInfo.mDrawable.isStateful()) {
21911                     mForegroundInfo.mDrawable.setState(getDrawableState());
21912                 }
21913             }
21914         }
21915     }
21916 
21917     /**
21918      * Get the drawable to be overlayed when a view is autofilled
21919      *
21920      * @return The drawable
21921      *
21922      * @throws IllegalStateException if the drawable could not be found.
21923      */
getAutofilledDrawable()21924     @Nullable private Drawable getAutofilledDrawable() {
21925         if (mAttachInfo == null) {
21926             return null;
21927         }
21928         // Lazily load the isAutofilled drawable.
21929         if (mAttachInfo.mAutofilledDrawable == null) {
21930             Context rootContext = getRootView().getContext();
21931             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
21932             int attributeResourceId = a.getResourceId(0, 0);
21933             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
21934             a.recycle();
21935         }
21936 
21937         return mAttachInfo.mAutofilledDrawable;
21938     }
21939 
21940     /**
21941      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
21942      *
21943      * @param canvas The canvas to draw on
21944      */
drawAutofilledHighlight(@onNull Canvas canvas)21945     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
21946         if (isAutofilled()) {
21947             Drawable autofilledHighlight = getAutofilledDrawable();
21948 
21949             if (autofilledHighlight != null) {
21950                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
21951                 autofilledHighlight.draw(canvas);
21952             }
21953         }
21954     }
21955 
21956     /**
21957      * Draw any foreground content for this view.
21958      *
21959      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
21960      * drawable or other view-specific decorations. The foreground is drawn on top of the
21961      * primary view content.</p>
21962      *
21963      * @param canvas canvas to draw into
21964      */
onDrawForeground(Canvas canvas)21965     public void onDrawForeground(Canvas canvas) {
21966         onDrawScrollIndicators(canvas);
21967         onDrawScrollBars(canvas);
21968 
21969         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
21970         if (foreground != null) {
21971             if (mForegroundInfo.mBoundsChanged) {
21972                 mForegroundInfo.mBoundsChanged = false;
21973                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
21974                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
21975 
21976                 if (mForegroundInfo.mInsidePadding) {
21977                     selfBounds.set(0, 0, getWidth(), getHeight());
21978                 } else {
21979                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
21980                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
21981                 }
21982 
21983                 final int ld = getLayoutDirection();
21984                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
21985                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
21986                 foreground.setBounds(overlayBounds);
21987             }
21988 
21989             foreground.draw(canvas);
21990         }
21991     }
21992 
21993     /**
21994      * Sets the padding. The view may add on the space required to display
21995      * the scrollbars, depending on the style and visibility of the scrollbars.
21996      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
21997      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
21998      * from the values set in this call.
21999      *
22000      * @attr ref android.R.styleable#View_padding
22001      * @attr ref android.R.styleable#View_paddingBottom
22002      * @attr ref android.R.styleable#View_paddingLeft
22003      * @attr ref android.R.styleable#View_paddingRight
22004      * @attr ref android.R.styleable#View_paddingTop
22005      * @param left the left padding in pixels
22006      * @param top the top padding in pixels
22007      * @param right the right padding in pixels
22008      * @param bottom the bottom padding in pixels
22009      */
setPadding(int left, int top, int right, int bottom)22010     public void setPadding(int left, int top, int right, int bottom) {
22011         resetResolvedPaddingInternal();
22012 
22013         mUserPaddingStart = UNDEFINED_PADDING;
22014         mUserPaddingEnd = UNDEFINED_PADDING;
22015 
22016         mUserPaddingLeftInitial = left;
22017         mUserPaddingRightInitial = right;
22018 
22019         mLeftPaddingDefined = true;
22020         mRightPaddingDefined = true;
22021 
22022         internalSetPadding(left, top, right, bottom);
22023     }
22024 
22025     /**
22026      * @hide
22027      */
internalSetPadding(int left, int top, int right, int bottom)22028     protected void internalSetPadding(int left, int top, int right, int bottom) {
22029         mUserPaddingLeft = left;
22030         mUserPaddingRight = right;
22031         mUserPaddingBottom = bottom;
22032 
22033         final int viewFlags = mViewFlags;
22034         boolean changed = false;
22035 
22036         // Common case is there are no scroll bars.
22037         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
22038             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
22039                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
22040                         ? 0 : getVerticalScrollbarWidth();
22041                 switch (mVerticalScrollbarPosition) {
22042                     case SCROLLBAR_POSITION_DEFAULT:
22043                         if (isLayoutRtl()) {
22044                             left += offset;
22045                         } else {
22046                             right += offset;
22047                         }
22048                         break;
22049                     case SCROLLBAR_POSITION_RIGHT:
22050                         right += offset;
22051                         break;
22052                     case SCROLLBAR_POSITION_LEFT:
22053                         left += offset;
22054                         break;
22055                 }
22056             }
22057             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
22058                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
22059                         ? 0 : getHorizontalScrollbarHeight();
22060             }
22061         }
22062 
22063         if (mPaddingLeft != left) {
22064             changed = true;
22065             mPaddingLeft = left;
22066         }
22067         if (mPaddingTop != top) {
22068             changed = true;
22069             mPaddingTop = top;
22070         }
22071         if (mPaddingRight != right) {
22072             changed = true;
22073             mPaddingRight = right;
22074         }
22075         if (mPaddingBottom != bottom) {
22076             changed = true;
22077             mPaddingBottom = bottom;
22078         }
22079 
22080         if (changed) {
22081             requestLayout();
22082             invalidateOutline();
22083         }
22084     }
22085 
22086     /**
22087      * Sets the relative padding. The view may add on the space required to display
22088      * the scrollbars, depending on the style and visibility of the scrollbars.
22089      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
22090      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
22091      * from the values set in this call.
22092      *
22093      * @attr ref android.R.styleable#View_padding
22094      * @attr ref android.R.styleable#View_paddingBottom
22095      * @attr ref android.R.styleable#View_paddingStart
22096      * @attr ref android.R.styleable#View_paddingEnd
22097      * @attr ref android.R.styleable#View_paddingTop
22098      * @param start the start padding in pixels
22099      * @param top the top padding in pixels
22100      * @param end the end padding in pixels
22101      * @param bottom the bottom padding in pixels
22102      */
setPaddingRelative(int start, int top, int end, int bottom)22103     public void setPaddingRelative(int start, int top, int end, int bottom) {
22104         resetResolvedPaddingInternal();
22105 
22106         mUserPaddingStart = start;
22107         mUserPaddingEnd = end;
22108         mLeftPaddingDefined = true;
22109         mRightPaddingDefined = true;
22110 
22111         switch(getLayoutDirection()) {
22112             case LAYOUT_DIRECTION_RTL:
22113                 mUserPaddingLeftInitial = end;
22114                 mUserPaddingRightInitial = start;
22115                 internalSetPadding(end, top, start, bottom);
22116                 break;
22117             case LAYOUT_DIRECTION_LTR:
22118             default:
22119                 mUserPaddingLeftInitial = start;
22120                 mUserPaddingRightInitial = end;
22121                 internalSetPadding(start, top, end, bottom);
22122         }
22123     }
22124 
22125     /**
22126      * Returns the top padding of this view.
22127      *
22128      * @return the top padding in pixels
22129      */
getPaddingTop()22130     public int getPaddingTop() {
22131         return mPaddingTop;
22132     }
22133 
22134     /**
22135      * Returns the bottom padding of this view. If there are inset and enabled
22136      * scrollbars, this value may include the space required to display the
22137      * scrollbars as well.
22138      *
22139      * @return the bottom padding in pixels
22140      */
getPaddingBottom()22141     public int getPaddingBottom() {
22142         return mPaddingBottom;
22143     }
22144 
22145     /**
22146      * Returns the left padding of this view. If there are inset and enabled
22147      * scrollbars, this value may include the space required to display the
22148      * scrollbars as well.
22149      *
22150      * @return the left padding in pixels
22151      */
getPaddingLeft()22152     public int getPaddingLeft() {
22153         if (!isPaddingResolved()) {
22154             resolvePadding();
22155         }
22156         return mPaddingLeft;
22157     }
22158 
22159     /**
22160      * Returns the start padding of this view depending on its resolved layout direction.
22161      * If there are inset and enabled scrollbars, this value may include the space
22162      * required to display the scrollbars as well.
22163      *
22164      * @return the start padding in pixels
22165      */
getPaddingStart()22166     public int getPaddingStart() {
22167         if (!isPaddingResolved()) {
22168             resolvePadding();
22169         }
22170         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
22171                 mPaddingRight : mPaddingLeft;
22172     }
22173 
22174     /**
22175      * Returns the right padding of this view. If there are inset and enabled
22176      * scrollbars, this value may include the space required to display the
22177      * scrollbars as well.
22178      *
22179      * @return the right padding in pixels
22180      */
getPaddingRight()22181     public int getPaddingRight() {
22182         if (!isPaddingResolved()) {
22183             resolvePadding();
22184         }
22185         return mPaddingRight;
22186     }
22187 
22188     /**
22189      * Returns the end padding of this view depending on its resolved layout direction.
22190      * If there are inset and enabled scrollbars, this value may include the space
22191      * required to display the scrollbars as well.
22192      *
22193      * @return the end padding in pixels
22194      */
getPaddingEnd()22195     public int getPaddingEnd() {
22196         if (!isPaddingResolved()) {
22197             resolvePadding();
22198         }
22199         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
22200                 mPaddingLeft : mPaddingRight;
22201     }
22202 
22203     /**
22204      * Return if the padding has been set through relative values
22205      * {@link #setPaddingRelative(int, int, int, int)} or through
22206      * @attr ref android.R.styleable#View_paddingStart or
22207      * @attr ref android.R.styleable#View_paddingEnd
22208      *
22209      * @return true if the padding is relative or false if it is not.
22210      */
isPaddingRelative()22211     public boolean isPaddingRelative() {
22212         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
22213     }
22214 
computeOpticalInsets()22215     Insets computeOpticalInsets() {
22216         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
22217     }
22218 
22219     /**
22220      * @hide
22221      */
resetPaddingToInitialValues()22222     public void resetPaddingToInitialValues() {
22223         if (isRtlCompatibilityMode()) {
22224             mPaddingLeft = mUserPaddingLeftInitial;
22225             mPaddingRight = mUserPaddingRightInitial;
22226             return;
22227         }
22228         if (isLayoutRtl()) {
22229             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
22230             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
22231         } else {
22232             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
22233             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
22234         }
22235     }
22236 
22237     /**
22238      * @hide
22239      */
getOpticalInsets()22240     public Insets getOpticalInsets() {
22241         if (mLayoutInsets == null) {
22242             mLayoutInsets = computeOpticalInsets();
22243         }
22244         return mLayoutInsets;
22245     }
22246 
22247     /**
22248      * Set this view's optical insets.
22249      *
22250      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
22251      * property. Views that compute their own optical insets should call it as part of measurement.
22252      * This method does not request layout. If you are setting optical insets outside of
22253      * measure/layout itself you will want to call requestLayout() yourself.
22254      * </p>
22255      * @hide
22256      */
setOpticalInsets(Insets insets)22257     public void setOpticalInsets(Insets insets) {
22258         mLayoutInsets = insets;
22259     }
22260 
22261     /**
22262      * Changes the selection state of this view. A view can be selected or not.
22263      * Note that selection is not the same as focus. Views are typically
22264      * selected in the context of an AdapterView like ListView or GridView;
22265      * the selected view is the view that is highlighted.
22266      *
22267      * @param selected true if the view must be selected, false otherwise
22268      */
setSelected(boolean selected)22269     public void setSelected(boolean selected) {
22270         //noinspection DoubleNegation
22271         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
22272             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
22273             if (!selected) resetPressedState();
22274             invalidate(true);
22275             refreshDrawableState();
22276             dispatchSetSelected(selected);
22277             if (selected) {
22278                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
22279             } else {
22280                 notifyViewAccessibilityStateChangedIfNeeded(
22281                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
22282             }
22283         }
22284     }
22285 
22286     /**
22287      * Dispatch setSelected to all of this View's children.
22288      *
22289      * @see #setSelected(boolean)
22290      *
22291      * @param selected The new selected state
22292      */
dispatchSetSelected(boolean selected)22293     protected void dispatchSetSelected(boolean selected) {
22294     }
22295 
22296     /**
22297      * Indicates the selection state of this view.
22298      *
22299      * @return true if the view is selected, false otherwise
22300      */
22301     @ViewDebug.ExportedProperty
isSelected()22302     public boolean isSelected() {
22303         return (mPrivateFlags & PFLAG_SELECTED) != 0;
22304     }
22305 
22306     /**
22307      * Changes the activated state of this view. A view can be activated or not.
22308      * Note that activation is not the same as selection.  Selection is
22309      * a transient property, representing the view (hierarchy) the user is
22310      * currently interacting with.  Activation is a longer-term state that the
22311      * user can move views in and out of.  For example, in a list view with
22312      * single or multiple selection enabled, the views in the current selection
22313      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
22314      * here.)  The activated state is propagated down to children of the view it
22315      * is set on.
22316      *
22317      * @param activated true if the view must be activated, false otherwise
22318      */
setActivated(boolean activated)22319     public void setActivated(boolean activated) {
22320         //noinspection DoubleNegation
22321         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
22322             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
22323             invalidate(true);
22324             refreshDrawableState();
22325             dispatchSetActivated(activated);
22326         }
22327     }
22328 
22329     /**
22330      * Dispatch setActivated to all of this View's children.
22331      *
22332      * @see #setActivated(boolean)
22333      *
22334      * @param activated The new activated state
22335      */
dispatchSetActivated(boolean activated)22336     protected void dispatchSetActivated(boolean activated) {
22337     }
22338 
22339     /**
22340      * Indicates the activation state of this view.
22341      *
22342      * @return true if the view is activated, false otherwise
22343      */
22344     @ViewDebug.ExportedProperty
isActivated()22345     public boolean isActivated() {
22346         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
22347     }
22348 
22349     /**
22350      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
22351      * observer can be used to get notifications when global events, like
22352      * layout, happen.
22353      *
22354      * The returned ViewTreeObserver observer is not guaranteed to remain
22355      * valid for the lifetime of this View. If the caller of this method keeps
22356      * a long-lived reference to ViewTreeObserver, it should always check for
22357      * the return value of {@link ViewTreeObserver#isAlive()}.
22358      *
22359      * @return The ViewTreeObserver for this view's hierarchy.
22360      */
getViewTreeObserver()22361     public ViewTreeObserver getViewTreeObserver() {
22362         if (mAttachInfo != null) {
22363             return mAttachInfo.mTreeObserver;
22364         }
22365         if (mFloatingTreeObserver == null) {
22366             mFloatingTreeObserver = new ViewTreeObserver(mContext);
22367         }
22368         return mFloatingTreeObserver;
22369     }
22370 
22371     /**
22372      * <p>Finds the topmost view in the current view hierarchy.</p>
22373      *
22374      * @return the topmost view containing this view
22375      */
getRootView()22376     public View getRootView() {
22377         if (mAttachInfo != null) {
22378             final View v = mAttachInfo.mRootView;
22379             if (v != null) {
22380                 return v;
22381             }
22382         }
22383 
22384         View parent = this;
22385 
22386         while (parent.mParent != null && parent.mParent instanceof View) {
22387             parent = (View) parent.mParent;
22388         }
22389 
22390         return parent;
22391     }
22392 
22393     /**
22394      * Transforms a motion event from view-local coordinates to on-screen
22395      * coordinates.
22396      *
22397      * @param ev the view-local motion event
22398      * @return false if the transformation could not be applied
22399      * @hide
22400      */
toGlobalMotionEvent(MotionEvent ev)22401     public boolean toGlobalMotionEvent(MotionEvent ev) {
22402         final AttachInfo info = mAttachInfo;
22403         if (info == null) {
22404             return false;
22405         }
22406 
22407         final Matrix m = info.mTmpMatrix;
22408         m.set(Matrix.IDENTITY_MATRIX);
22409         transformMatrixToGlobal(m);
22410         ev.transform(m);
22411         return true;
22412     }
22413 
22414     /**
22415      * Transforms a motion event from on-screen coordinates to view-local
22416      * coordinates.
22417      *
22418      * @param ev the on-screen motion event
22419      * @return false if the transformation could not be applied
22420      * @hide
22421      */
toLocalMotionEvent(MotionEvent ev)22422     public boolean toLocalMotionEvent(MotionEvent ev) {
22423         final AttachInfo info = mAttachInfo;
22424         if (info == null) {
22425             return false;
22426         }
22427 
22428         final Matrix m = info.mTmpMatrix;
22429         m.set(Matrix.IDENTITY_MATRIX);
22430         transformMatrixToLocal(m);
22431         ev.transform(m);
22432         return true;
22433     }
22434 
22435     /**
22436      * Modifies the input matrix such that it maps view-local coordinates to
22437      * on-screen coordinates.
22438      *
22439      * @param m input matrix to modify
22440      * @hide
22441      */
transformMatrixToGlobal(Matrix m)22442     public void transformMatrixToGlobal(Matrix m) {
22443         final ViewParent parent = mParent;
22444         if (parent instanceof View) {
22445             final View vp = (View) parent;
22446             vp.transformMatrixToGlobal(m);
22447             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
22448         } else if (parent instanceof ViewRootImpl) {
22449             final ViewRootImpl vr = (ViewRootImpl) parent;
22450             vr.transformMatrixToGlobal(m);
22451             m.preTranslate(0, -vr.mCurScrollY);
22452         }
22453 
22454         m.preTranslate(mLeft, mTop);
22455 
22456         if (!hasIdentityMatrix()) {
22457             m.preConcat(getMatrix());
22458         }
22459     }
22460 
22461     /**
22462      * Modifies the input matrix such that it maps on-screen coordinates to
22463      * view-local coordinates.
22464      *
22465      * @param m input matrix to modify
22466      * @hide
22467      */
transformMatrixToLocal(Matrix m)22468     public void transformMatrixToLocal(Matrix m) {
22469         final ViewParent parent = mParent;
22470         if (parent instanceof View) {
22471             final View vp = (View) parent;
22472             vp.transformMatrixToLocal(m);
22473             m.postTranslate(vp.mScrollX, vp.mScrollY);
22474         } else if (parent instanceof ViewRootImpl) {
22475             final ViewRootImpl vr = (ViewRootImpl) parent;
22476             vr.transformMatrixToLocal(m);
22477             m.postTranslate(0, vr.mCurScrollY);
22478         }
22479 
22480         m.postTranslate(-mLeft, -mTop);
22481 
22482         if (!hasIdentityMatrix()) {
22483             m.postConcat(getInverseMatrix());
22484         }
22485     }
22486 
22487     /**
22488      * @hide
22489      */
22490     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
22491             @ViewDebug.IntToString(from = 0, to = "x"),
22492             @ViewDebug.IntToString(from = 1, to = "y")
22493     })
getLocationOnScreen()22494     public int[] getLocationOnScreen() {
22495         int[] location = new int[2];
22496         getLocationOnScreen(location);
22497         return location;
22498     }
22499 
22500     /**
22501      * <p>Computes the coordinates of this view on the screen. The argument
22502      * must be an array of two integers. After the method returns, the array
22503      * contains the x and y location in that order.</p>
22504      *
22505      * @param outLocation an array of two integers in which to hold the coordinates
22506      */
getLocationOnScreen(@ize2) int[] outLocation)22507     public void getLocationOnScreen(@Size(2) int[] outLocation) {
22508         getLocationInWindow(outLocation);
22509 
22510         final AttachInfo info = mAttachInfo;
22511         if (info != null) {
22512             outLocation[0] += info.mWindowLeft;
22513             outLocation[1] += info.mWindowTop;
22514         }
22515     }
22516 
22517     /**
22518      * <p>Computes the coordinates of this view in its window. The argument
22519      * must be an array of two integers. After the method returns, the array
22520      * contains the x and y location in that order.</p>
22521      *
22522      * @param outLocation an array of two integers in which to hold the coordinates
22523      */
getLocationInWindow(@ize2) int[] outLocation)22524     public void getLocationInWindow(@Size(2) int[] outLocation) {
22525         if (outLocation == null || outLocation.length < 2) {
22526             throw new IllegalArgumentException("outLocation must be an array of two integers");
22527         }
22528 
22529         outLocation[0] = 0;
22530         outLocation[1] = 0;
22531 
22532         transformFromViewToWindowSpace(outLocation);
22533     }
22534 
22535     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)22536     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
22537         if (inOutLocation == null || inOutLocation.length < 2) {
22538             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
22539         }
22540 
22541         if (mAttachInfo == null) {
22542             // When the view is not attached to a window, this method does not make sense
22543             inOutLocation[0] = inOutLocation[1] = 0;
22544             return;
22545         }
22546 
22547         float position[] = mAttachInfo.mTmpTransformLocation;
22548         position[0] = inOutLocation[0];
22549         position[1] = inOutLocation[1];
22550 
22551         if (!hasIdentityMatrix()) {
22552             getMatrix().mapPoints(position);
22553         }
22554 
22555         position[0] += mLeft;
22556         position[1] += mTop;
22557 
22558         ViewParent viewParent = mParent;
22559         while (viewParent instanceof View) {
22560             final View view = (View) viewParent;
22561 
22562             position[0] -= view.mScrollX;
22563             position[1] -= view.mScrollY;
22564 
22565             if (!view.hasIdentityMatrix()) {
22566                 view.getMatrix().mapPoints(position);
22567             }
22568 
22569             position[0] += view.mLeft;
22570             position[1] += view.mTop;
22571 
22572             viewParent = view.mParent;
22573          }
22574 
22575         if (viewParent instanceof ViewRootImpl) {
22576             // *cough*
22577             final ViewRootImpl vr = (ViewRootImpl) viewParent;
22578             position[1] -= vr.mCurScrollY;
22579         }
22580 
22581         inOutLocation[0] = Math.round(position[0]);
22582         inOutLocation[1] = Math.round(position[1]);
22583     }
22584 
22585     /**
22586      * @param id the id of the view to be found
22587      * @return the view of the specified id, null if cannot be found
22588      * @hide
22589      */
findViewTraversal(@dRes int id)22590     protected <T extends View> T findViewTraversal(@IdRes int id) {
22591         if (id == mID) {
22592             return (T) this;
22593         }
22594         return null;
22595     }
22596 
22597     /**
22598      * @param tag the tag of the view to be found
22599      * @return the view of specified tag, null if cannot be found
22600      * @hide
22601      */
findViewWithTagTraversal(Object tag)22602     protected <T extends View> T findViewWithTagTraversal(Object tag) {
22603         if (tag != null && tag.equals(mTag)) {
22604             return (T) this;
22605         }
22606         return null;
22607     }
22608 
22609     /**
22610      * @param predicate The predicate to evaluate.
22611      * @param childToSkip If not null, ignores this child during the recursive traversal.
22612      * @return The first view that matches the predicate or null.
22613      * @hide
22614      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)22615     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
22616             View childToSkip) {
22617         if (predicate.test(this)) {
22618             return (T) this;
22619         }
22620         return null;
22621     }
22622 
22623     /**
22624      * Finds the first descendant view with the given ID, the view itself if
22625      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
22626      * (< 0) or there is no matching view in the hierarchy.
22627      * <p>
22628      * <strong>Note:</strong> In most cases -- depending on compiler support --
22629      * the resulting view is automatically cast to the target class type. If
22630      * the target class type is unconstrained, an explicit cast may be
22631      * necessary.
22632      *
22633      * @param id the ID to search for
22634      * @return a view with given ID if found, or {@code null} otherwise
22635      * @see View#requireViewById(int)
22636      */
22637     @Nullable
findViewById(@dRes int id)22638     public final <T extends View> T findViewById(@IdRes int id) {
22639         if (id == NO_ID) {
22640             return null;
22641         }
22642         return findViewTraversal(id);
22643     }
22644 
22645     /**
22646      * Finds the first descendant view with the given ID, the view itself if the ID matches
22647      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
22648      * matching view in the hierarchy.
22649      * <p>
22650      * <strong>Note:</strong> In most cases -- depending on compiler support --
22651      * the resulting view is automatically cast to the target class type. If
22652      * the target class type is unconstrained, an explicit cast may be
22653      * necessary.
22654      *
22655      * @param id the ID to search for
22656      * @return a view with given ID
22657      * @see View#findViewById(int)
22658      */
22659     @NonNull
requireViewById(@dRes int id)22660     public final <T extends View> T requireViewById(@IdRes int id) {
22661         T view = findViewById(id);
22662         if (view == null) {
22663             throw new IllegalArgumentException("ID does not reference a View inside this View");
22664         }
22665         return view;
22666     }
22667 
22668     /**
22669      * Finds a view by its unuque and stable accessibility id.
22670      *
22671      * @param accessibilityId The searched accessibility id.
22672      * @return The found view.
22673      */
findViewByAccessibilityId(int accessibilityId)22674     final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
22675         if (accessibilityId < 0) {
22676             return null;
22677         }
22678         T view = findViewByAccessibilityIdTraversal(accessibilityId);
22679         if (view != null) {
22680             return view.includeForAccessibility() ? view : null;
22681         }
22682         return null;
22683     }
22684 
22685     /**
22686      * Performs the traversal to find a view by its unique and stable accessibility id.
22687      *
22688      * <strong>Note:</strong>This method does not stop at the root namespace
22689      * boundary since the user can touch the screen at an arbitrary location
22690      * potentially crossing the root namespace boundary which will send an
22691      * accessibility event to accessibility services and they should be able
22692      * to obtain the event source. Also accessibility ids are guaranteed to be
22693      * unique in the window.
22694      *
22695      * @param accessibilityId The accessibility id.
22696      * @return The found view.
22697      * @hide
22698      */
findViewByAccessibilityIdTraversal(int accessibilityId)22699     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
22700         if (getAccessibilityViewId() == accessibilityId) {
22701             return (T) this;
22702         }
22703         return null;
22704     }
22705 
22706     /**
22707      * Performs the traversal to find a view by its autofill id.
22708      *
22709      * <strong>Note:</strong>This method does not stop at the root namespace
22710      * boundary.
22711      *
22712      * @param autofillId The autofill id.
22713      * @return The found view.
22714      * @hide
22715      */
findViewByAutofillIdTraversal(int autofillId)22716     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
22717         if (getAutofillViewId() == autofillId) {
22718             return (T) this;
22719         }
22720         return null;
22721     }
22722 
22723     /**
22724      * Look for a child view with the given tag.  If this view has the given
22725      * tag, return this view.
22726      *
22727      * @param tag The tag to search for, using "tag.equals(getTag())".
22728      * @return The View that has the given tag in the hierarchy or null
22729      */
findViewWithTag(Object tag)22730     public final <T extends View> T findViewWithTag(Object tag) {
22731         if (tag == null) {
22732             return null;
22733         }
22734         return findViewWithTagTraversal(tag);
22735     }
22736 
22737     /**
22738      * Look for a child view that matches the specified predicate.
22739      * If this view matches the predicate, return this view.
22740      *
22741      * @param predicate The predicate to evaluate.
22742      * @return The first view that matches the predicate or null.
22743      * @hide
22744      */
findViewByPredicate(Predicate<View> predicate)22745     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
22746         return findViewByPredicateTraversal(predicate, null);
22747     }
22748 
22749     /**
22750      * Look for a child view that matches the specified predicate,
22751      * starting with the specified view and its descendents and then
22752      * recusively searching the ancestors and siblings of that view
22753      * until this view is reached.
22754      *
22755      * This method is useful in cases where the predicate does not match
22756      * a single unique view (perhaps multiple views use the same id)
22757      * and we are trying to find the view that is "closest" in scope to the
22758      * starting view.
22759      *
22760      * @param start The view to start from.
22761      * @param predicate The predicate to evaluate.
22762      * @return The first view that matches the predicate or null.
22763      * @hide
22764      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)22765     public final <T extends View> T findViewByPredicateInsideOut(
22766             View start, Predicate<View> predicate) {
22767         View childToSkip = null;
22768         for (;;) {
22769             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
22770             if (view != null || start == this) {
22771                 return view;
22772             }
22773 
22774             ViewParent parent = start.getParent();
22775             if (parent == null || !(parent instanceof View)) {
22776                 return null;
22777             }
22778 
22779             childToSkip = start;
22780             start = (View) parent;
22781         }
22782     }
22783 
22784     /**
22785      * Sets the identifier for this view. The identifier does not have to be
22786      * unique in this view's hierarchy. The identifier should be a positive
22787      * number.
22788      *
22789      * @see #NO_ID
22790      * @see #getId()
22791      * @see #findViewById(int)
22792      *
22793      * @param id a number used to identify the view
22794      *
22795      * @attr ref android.R.styleable#View_id
22796      */
setId(@dRes int id)22797     public void setId(@IdRes int id) {
22798         mID = id;
22799         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
22800             mID = generateViewId();
22801         }
22802     }
22803 
22804     /**
22805      * {@hide}
22806      *
22807      * @param isRoot true if the view belongs to the root namespace, false
22808      *        otherwise
22809      */
setIsRootNamespace(boolean isRoot)22810     public void setIsRootNamespace(boolean isRoot) {
22811         if (isRoot) {
22812             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
22813         } else {
22814             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
22815         }
22816     }
22817 
22818     /**
22819      * {@hide}
22820      *
22821      * @return true if the view belongs to the root namespace, false otherwise
22822      */
isRootNamespace()22823     public boolean isRootNamespace() {
22824         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
22825     }
22826 
22827     /**
22828      * Returns this view's identifier.
22829      *
22830      * @return a positive integer used to identify the view or {@link #NO_ID}
22831      *         if the view has no ID
22832      *
22833      * @see #setId(int)
22834      * @see #findViewById(int)
22835      * @attr ref android.R.styleable#View_id
22836      */
22837     @IdRes
22838     @ViewDebug.CapturedViewProperty
getId()22839     public int getId() {
22840         return mID;
22841     }
22842 
22843     /**
22844      * Returns this view's tag.
22845      *
22846      * @return the Object stored in this view as a tag, or {@code null} if not
22847      *         set
22848      *
22849      * @see #setTag(Object)
22850      * @see #getTag(int)
22851      */
22852     @ViewDebug.ExportedProperty
getTag()22853     public Object getTag() {
22854         return mTag;
22855     }
22856 
22857     /**
22858      * Sets the tag associated with this view. A tag can be used to mark
22859      * a view in its hierarchy and does not have to be unique within the
22860      * hierarchy. Tags can also be used to store data within a view without
22861      * resorting to another data structure.
22862      *
22863      * @param tag an Object to tag the view with
22864      *
22865      * @see #getTag()
22866      * @see #setTag(int, Object)
22867      */
setTag(final Object tag)22868     public void setTag(final Object tag) {
22869         mTag = tag;
22870     }
22871 
22872     /**
22873      * Returns the tag associated with this view and the specified key.
22874      *
22875      * @param key The key identifying the tag
22876      *
22877      * @return the Object stored in this view as a tag, or {@code null} if not
22878      *         set
22879      *
22880      * @see #setTag(int, Object)
22881      * @see #getTag()
22882      */
getTag(int key)22883     public Object getTag(int key) {
22884         if (mKeyedTags != null) return mKeyedTags.get(key);
22885         return null;
22886     }
22887 
22888     /**
22889      * Sets a tag associated with this view and a key. A tag can be used
22890      * to mark a view in its hierarchy and does not have to be unique within
22891      * the hierarchy. Tags can also be used to store data within a view
22892      * without resorting to another data structure.
22893      *
22894      * The specified key should be an id declared in the resources of the
22895      * application to ensure it is unique (see the <a
22896      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
22897      * Keys identified as belonging to
22898      * the Android framework or not associated with any package will cause
22899      * an {@link IllegalArgumentException} to be thrown.
22900      *
22901      * @param key The key identifying the tag
22902      * @param tag An Object to tag the view with
22903      *
22904      * @throws IllegalArgumentException If they specified key is not valid
22905      *
22906      * @see #setTag(Object)
22907      * @see #getTag(int)
22908      */
setTag(int key, final Object tag)22909     public void setTag(int key, final Object tag) {
22910         // If the package id is 0x00 or 0x01, it's either an undefined package
22911         // or a framework id
22912         if ((key >>> 24) < 2) {
22913             throw new IllegalArgumentException("The key must be an application-specific "
22914                     + "resource id.");
22915         }
22916 
22917         setKeyedTag(key, tag);
22918     }
22919 
22920     /**
22921      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
22922      * framework id.
22923      *
22924      * @hide
22925      */
setTagInternal(int key, Object tag)22926     public void setTagInternal(int key, Object tag) {
22927         if ((key >>> 24) != 0x1) {
22928             throw new IllegalArgumentException("The key must be a framework-specific "
22929                     + "resource id.");
22930         }
22931 
22932         setKeyedTag(key, tag);
22933     }
22934 
setKeyedTag(int key, Object tag)22935     private void setKeyedTag(int key, Object tag) {
22936         if (mKeyedTags == null) {
22937             mKeyedTags = new SparseArray<Object>(2);
22938         }
22939 
22940         mKeyedTags.put(key, tag);
22941     }
22942 
22943     /**
22944      * Prints information about this view in the log output, with the tag
22945      * {@link #VIEW_LOG_TAG}.
22946      *
22947      * @hide
22948      */
debug()22949     public void debug() {
22950         debug(0);
22951     }
22952 
22953     /**
22954      * Prints information about this view in the log output, with the tag
22955      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
22956      * indentation defined by the <code>depth</code>.
22957      *
22958      * @param depth the indentation level
22959      *
22960      * @hide
22961      */
debug(int depth)22962     protected void debug(int depth) {
22963         String output = debugIndent(depth - 1);
22964 
22965         output += "+ " + this;
22966         int id = getId();
22967         if (id != -1) {
22968             output += " (id=" + id + ")";
22969         }
22970         Object tag = getTag();
22971         if (tag != null) {
22972             output += " (tag=" + tag + ")";
22973         }
22974         Log.d(VIEW_LOG_TAG, output);
22975 
22976         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
22977             output = debugIndent(depth) + " FOCUSED";
22978             Log.d(VIEW_LOG_TAG, output);
22979         }
22980 
22981         output = debugIndent(depth);
22982         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
22983                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
22984                 + "} ";
22985         Log.d(VIEW_LOG_TAG, output);
22986 
22987         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
22988                 || mPaddingBottom != 0) {
22989             output = debugIndent(depth);
22990             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
22991                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
22992             Log.d(VIEW_LOG_TAG, output);
22993         }
22994 
22995         output = debugIndent(depth);
22996         output += "mMeasureWidth=" + mMeasuredWidth +
22997                 " mMeasureHeight=" + mMeasuredHeight;
22998         Log.d(VIEW_LOG_TAG, output);
22999 
23000         output = debugIndent(depth);
23001         if (mLayoutParams == null) {
23002             output += "BAD! no layout params";
23003         } else {
23004             output = mLayoutParams.debug(output);
23005         }
23006         Log.d(VIEW_LOG_TAG, output);
23007 
23008         output = debugIndent(depth);
23009         output += "flags={";
23010         output += View.printFlags(mViewFlags);
23011         output += "}";
23012         Log.d(VIEW_LOG_TAG, output);
23013 
23014         output = debugIndent(depth);
23015         output += "privateFlags={";
23016         output += View.printPrivateFlags(mPrivateFlags);
23017         output += "}";
23018         Log.d(VIEW_LOG_TAG, output);
23019     }
23020 
23021     /**
23022      * Creates a string of whitespaces used for indentation.
23023      *
23024      * @param depth the indentation level
23025      * @return a String containing (depth * 2 + 3) * 2 white spaces
23026      *
23027      * @hide
23028      */
debugIndent(int depth)23029     protected static String debugIndent(int depth) {
23030         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
23031         for (int i = 0; i < (depth * 2) + 3; i++) {
23032             spaces.append(' ').append(' ');
23033         }
23034         return spaces.toString();
23035     }
23036 
23037     /**
23038      * <p>Return the offset of the widget's text baseline from the widget's top
23039      * boundary. If this widget does not support baseline alignment, this
23040      * method returns -1. </p>
23041      *
23042      * @return the offset of the baseline within the widget's bounds or -1
23043      *         if baseline alignment is not supported
23044      */
23045     @ViewDebug.ExportedProperty(category = "layout")
getBaseline()23046     public int getBaseline() {
23047         return -1;
23048     }
23049 
23050     /**
23051      * Returns whether the view hierarchy is currently undergoing a layout pass. This
23052      * information is useful to avoid situations such as calling {@link #requestLayout()} during
23053      * a layout pass.
23054      *
23055      * @return whether the view hierarchy is currently undergoing a layout pass
23056      */
isInLayout()23057     public boolean isInLayout() {
23058         ViewRootImpl viewRoot = getViewRootImpl();
23059         return (viewRoot != null && viewRoot.isInLayout());
23060     }
23061 
23062     /**
23063      * Call this when something has changed which has invalidated the
23064      * layout of this view. This will schedule a layout pass of the view
23065      * tree. This should not be called while the view hierarchy is currently in a layout
23066      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
23067      * end of the current layout pass (and then layout will run again) or after the current
23068      * frame is drawn and the next layout occurs.
23069      *
23070      * <p>Subclasses which override this method should call the superclass method to
23071      * handle possible request-during-layout errors correctly.</p>
23072      */
23073     @CallSuper
requestLayout()23074     public void requestLayout() {
23075         if (mMeasureCache != null) mMeasureCache.clear();
23076 
23077         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
23078             // Only trigger request-during-layout logic if this is the view requesting it,
23079             // not the views in its parent hierarchy
23080             ViewRootImpl viewRoot = getViewRootImpl();
23081             if (viewRoot != null && viewRoot.isInLayout()) {
23082                 if (!viewRoot.requestLayoutDuringLayout(this)) {
23083                     return;
23084                 }
23085             }
23086             mAttachInfo.mViewRequestingLayout = this;
23087         }
23088 
23089         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
23090         mPrivateFlags |= PFLAG_INVALIDATED;
23091 
23092         if (mParent != null && !mParent.isLayoutRequested()) {
23093             mParent.requestLayout();
23094         }
23095         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
23096             mAttachInfo.mViewRequestingLayout = null;
23097         }
23098     }
23099 
23100     /**
23101      * Forces this view to be laid out during the next layout pass.
23102      * This method does not call requestLayout() or forceLayout()
23103      * on the parent.
23104      */
forceLayout()23105     public void forceLayout() {
23106         if (mMeasureCache != null) mMeasureCache.clear();
23107 
23108         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
23109         mPrivateFlags |= PFLAG_INVALIDATED;
23110     }
23111 
23112     /**
23113      * <p>
23114      * This is called to find out how big a view should be. The parent
23115      * supplies constraint information in the width and height parameters.
23116      * </p>
23117      *
23118      * <p>
23119      * The actual measurement work of a view is performed in
23120      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
23121      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
23122      * </p>
23123      *
23124      *
23125      * @param widthMeasureSpec Horizontal space requirements as imposed by the
23126      *        parent
23127      * @param heightMeasureSpec Vertical space requirements as imposed by the
23128      *        parent
23129      *
23130      * @see #onMeasure(int, int)
23131      */
measure(int widthMeasureSpec, int heightMeasureSpec)23132     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
23133         boolean optical = isLayoutModeOptical(this);
23134         if (optical != isLayoutModeOptical(mParent)) {
23135             Insets insets = getOpticalInsets();
23136             int oWidth  = insets.left + insets.right;
23137             int oHeight = insets.top  + insets.bottom;
23138             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
23139             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
23140         }
23141 
23142         // Suppress sign extension for the low bytes
23143         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
23144         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
23145 
23146         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
23147 
23148         // Optimize layout by avoiding an extra EXACTLY pass when the view is
23149         // already measured as the correct size. In API 23 and below, this
23150         // extra pass is required to make LinearLayout re-distribute weight.
23151         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
23152                 || heightMeasureSpec != mOldHeightMeasureSpec;
23153         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
23154                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
23155         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
23156                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
23157         final boolean needsLayout = specChanged
23158                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
23159 
23160         if (forceLayout || needsLayout) {
23161             // first clears the measured dimension flag
23162             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
23163 
23164             resolveRtlPropertiesIfNeeded();
23165 
23166             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
23167             if (cacheIndex < 0 || sIgnoreMeasureCache) {
23168                 // measure ourselves, this should set the measured dimension flag back
23169                 onMeasure(widthMeasureSpec, heightMeasureSpec);
23170                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
23171             } else {
23172                 long value = mMeasureCache.valueAt(cacheIndex);
23173                 // Casting a long to int drops the high 32 bits, no mask needed
23174                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
23175                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
23176             }
23177 
23178             // flag not set, setMeasuredDimension() was not invoked, we raise
23179             // an exception to warn the developer
23180             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
23181                 throw new IllegalStateException("View with id " + getId() + ": "
23182                         + getClass().getName() + "#onMeasure() did not set the"
23183                         + " measured dimension by calling"
23184                         + " setMeasuredDimension()");
23185             }
23186 
23187             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
23188         }
23189 
23190         mOldWidthMeasureSpec = widthMeasureSpec;
23191         mOldHeightMeasureSpec = heightMeasureSpec;
23192 
23193         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
23194                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
23195     }
23196 
23197     /**
23198      * <p>
23199      * Measure the view and its content to determine the measured width and the
23200      * measured height. This method is invoked by {@link #measure(int, int)} and
23201      * should be overridden by subclasses to provide accurate and efficient
23202      * measurement of their contents.
23203      * </p>
23204      *
23205      * <p>
23206      * <strong>CONTRACT:</strong> When overriding this method, you
23207      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
23208      * measured width and height of this view. Failure to do so will trigger an
23209      * <code>IllegalStateException</code>, thrown by
23210      * {@link #measure(int, int)}. Calling the superclass'
23211      * {@link #onMeasure(int, int)} is a valid use.
23212      * </p>
23213      *
23214      * <p>
23215      * The base class implementation of measure defaults to the background size,
23216      * unless a larger size is allowed by the MeasureSpec. Subclasses should
23217      * override {@link #onMeasure(int, int)} to provide better measurements of
23218      * their content.
23219      * </p>
23220      *
23221      * <p>
23222      * If this method is overridden, it is the subclass's responsibility to make
23223      * sure the measured height and width are at least the view's minimum height
23224      * and width ({@link #getSuggestedMinimumHeight()} and
23225      * {@link #getSuggestedMinimumWidth()}).
23226      * </p>
23227      *
23228      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
23229      *                         The requirements are encoded with
23230      *                         {@link android.view.View.MeasureSpec}.
23231      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
23232      *                         The requirements are encoded with
23233      *                         {@link android.view.View.MeasureSpec}.
23234      *
23235      * @see #getMeasuredWidth()
23236      * @see #getMeasuredHeight()
23237      * @see #setMeasuredDimension(int, int)
23238      * @see #getSuggestedMinimumHeight()
23239      * @see #getSuggestedMinimumWidth()
23240      * @see android.view.View.MeasureSpec#getMode(int)
23241      * @see android.view.View.MeasureSpec#getSize(int)
23242      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)23243     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
23244         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
23245                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
23246     }
23247 
23248     /**
23249      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
23250      * measured width and measured height. Failing to do so will trigger an
23251      * exception at measurement time.</p>
23252      *
23253      * @param measuredWidth The measured width of this view.  May be a complex
23254      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
23255      * {@link #MEASURED_STATE_TOO_SMALL}.
23256      * @param measuredHeight The measured height of this view.  May be a complex
23257      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
23258      * {@link #MEASURED_STATE_TOO_SMALL}.
23259      */
setMeasuredDimension(int measuredWidth, int measuredHeight)23260     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
23261         boolean optical = isLayoutModeOptical(this);
23262         if (optical != isLayoutModeOptical(mParent)) {
23263             Insets insets = getOpticalInsets();
23264             int opticalWidth  = insets.left + insets.right;
23265             int opticalHeight = insets.top  + insets.bottom;
23266 
23267             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
23268             measuredHeight += optical ? opticalHeight : -opticalHeight;
23269         }
23270         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
23271     }
23272 
23273     /**
23274      * Sets the measured dimension without extra processing for things like optical bounds.
23275      * Useful for reapplying consistent values that have already been cooked with adjustments
23276      * for optical bounds, etc. such as those from the measurement cache.
23277      *
23278      * @param measuredWidth The measured width of this view.  May be a complex
23279      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
23280      * {@link #MEASURED_STATE_TOO_SMALL}.
23281      * @param measuredHeight The measured height of this view.  May be a complex
23282      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
23283      * {@link #MEASURED_STATE_TOO_SMALL}.
23284      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)23285     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
23286         mMeasuredWidth = measuredWidth;
23287         mMeasuredHeight = measuredHeight;
23288 
23289         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
23290     }
23291 
23292     /**
23293      * Merge two states as returned by {@link #getMeasuredState()}.
23294      * @param curState The current state as returned from a view or the result
23295      * of combining multiple views.
23296      * @param newState The new view state to combine.
23297      * @return Returns a new integer reflecting the combination of the two
23298      * states.
23299      */
combineMeasuredStates(int curState, int newState)23300     public static int combineMeasuredStates(int curState, int newState) {
23301         return curState | newState;
23302     }
23303 
23304     /**
23305      * Version of {@link #resolveSizeAndState(int, int, int)}
23306      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
23307      */
resolveSize(int size, int measureSpec)23308     public static int resolveSize(int size, int measureSpec) {
23309         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
23310     }
23311 
23312     /**
23313      * Utility to reconcile a desired size and state, with constraints imposed
23314      * by a MeasureSpec. Will take the desired size, unless a different size
23315      * is imposed by the constraints. The returned value is a compound integer,
23316      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
23317      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
23318      * resulting size is smaller than the size the view wants to be.
23319      *
23320      * @param size How big the view wants to be.
23321      * @param measureSpec Constraints imposed by the parent.
23322      * @param childMeasuredState Size information bit mask for the view's
23323      *                           children.
23324      * @return Size information bit mask as defined by
23325      *         {@link #MEASURED_SIZE_MASK} and
23326      *         {@link #MEASURED_STATE_TOO_SMALL}.
23327      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)23328     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
23329         final int specMode = MeasureSpec.getMode(measureSpec);
23330         final int specSize = MeasureSpec.getSize(measureSpec);
23331         final int result;
23332         switch (specMode) {
23333             case MeasureSpec.AT_MOST:
23334                 if (specSize < size) {
23335                     result = specSize | MEASURED_STATE_TOO_SMALL;
23336                 } else {
23337                     result = size;
23338                 }
23339                 break;
23340             case MeasureSpec.EXACTLY:
23341                 result = specSize;
23342                 break;
23343             case MeasureSpec.UNSPECIFIED:
23344             default:
23345                 result = size;
23346         }
23347         return result | (childMeasuredState & MEASURED_STATE_MASK);
23348     }
23349 
23350     /**
23351      * Utility to return a default size. Uses the supplied size if the
23352      * MeasureSpec imposed no constraints. Will get larger if allowed
23353      * by the MeasureSpec.
23354      *
23355      * @param size Default size for this view
23356      * @param measureSpec Constraints imposed by the parent
23357      * @return The size this view should be.
23358      */
getDefaultSize(int size, int measureSpec)23359     public static int getDefaultSize(int size, int measureSpec) {
23360         int result = size;
23361         int specMode = MeasureSpec.getMode(measureSpec);
23362         int specSize = MeasureSpec.getSize(measureSpec);
23363 
23364         switch (specMode) {
23365         case MeasureSpec.UNSPECIFIED:
23366             result = size;
23367             break;
23368         case MeasureSpec.AT_MOST:
23369         case MeasureSpec.EXACTLY:
23370             result = specSize;
23371             break;
23372         }
23373         return result;
23374     }
23375 
23376     /**
23377      * Returns the suggested minimum height that the view should use. This
23378      * returns the maximum of the view's minimum height
23379      * and the background's minimum height
23380      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
23381      * <p>
23382      * When being used in {@link #onMeasure(int, int)}, the caller should still
23383      * ensure the returned height is within the requirements of the parent.
23384      *
23385      * @return The suggested minimum height of the view.
23386      */
getSuggestedMinimumHeight()23387     protected int getSuggestedMinimumHeight() {
23388         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
23389 
23390     }
23391 
23392     /**
23393      * Returns the suggested minimum width that the view should use. This
23394      * returns the maximum of the view's minimum width
23395      * and the background's minimum width
23396      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
23397      * <p>
23398      * When being used in {@link #onMeasure(int, int)}, the caller should still
23399      * ensure the returned width is within the requirements of the parent.
23400      *
23401      * @return The suggested minimum width of the view.
23402      */
getSuggestedMinimumWidth()23403     protected int getSuggestedMinimumWidth() {
23404         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
23405     }
23406 
23407     /**
23408      * Returns the minimum height of the view.
23409      *
23410      * @return the minimum height the view will try to be, in pixels
23411      *
23412      * @see #setMinimumHeight(int)
23413      *
23414      * @attr ref android.R.styleable#View_minHeight
23415      */
getMinimumHeight()23416     public int getMinimumHeight() {
23417         return mMinHeight;
23418     }
23419 
23420     /**
23421      * Sets the minimum height of the view. It is not guaranteed the view will
23422      * be able to achieve this minimum height (for example, if its parent layout
23423      * constrains it with less available height).
23424      *
23425      * @param minHeight The minimum height the view will try to be, in pixels
23426      *
23427      * @see #getMinimumHeight()
23428      *
23429      * @attr ref android.R.styleable#View_minHeight
23430      */
23431     @RemotableViewMethod
setMinimumHeight(int minHeight)23432     public void setMinimumHeight(int minHeight) {
23433         mMinHeight = minHeight;
23434         requestLayout();
23435     }
23436 
23437     /**
23438      * Returns the minimum width of the view.
23439      *
23440      * @return the minimum width the view will try to be, in pixels
23441      *
23442      * @see #setMinimumWidth(int)
23443      *
23444      * @attr ref android.R.styleable#View_minWidth
23445      */
getMinimumWidth()23446     public int getMinimumWidth() {
23447         return mMinWidth;
23448     }
23449 
23450     /**
23451      * Sets the minimum width of the view. It is not guaranteed the view will
23452      * be able to achieve this minimum width (for example, if its parent layout
23453      * constrains it with less available width).
23454      *
23455      * @param minWidth The minimum width the view will try to be, in pixels
23456      *
23457      * @see #getMinimumWidth()
23458      *
23459      * @attr ref android.R.styleable#View_minWidth
23460      */
setMinimumWidth(int minWidth)23461     public void setMinimumWidth(int minWidth) {
23462         mMinWidth = minWidth;
23463         requestLayout();
23464 
23465     }
23466 
23467     /**
23468      * Get the animation currently associated with this view.
23469      *
23470      * @return The animation that is currently playing or
23471      *         scheduled to play for this view.
23472      */
getAnimation()23473     public Animation getAnimation() {
23474         return mCurrentAnimation;
23475     }
23476 
23477     /**
23478      * Start the specified animation now.
23479      *
23480      * @param animation the animation to start now
23481      */
startAnimation(Animation animation)23482     public void startAnimation(Animation animation) {
23483         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
23484         setAnimation(animation);
23485         invalidateParentCaches();
23486         invalidate(true);
23487     }
23488 
23489     /**
23490      * Cancels any animations for this view.
23491      */
clearAnimation()23492     public void clearAnimation() {
23493         if (mCurrentAnimation != null) {
23494             mCurrentAnimation.detach();
23495         }
23496         mCurrentAnimation = null;
23497         invalidateParentIfNeeded();
23498     }
23499 
23500     /**
23501      * Sets the next animation to play for this view.
23502      * If you want the animation to play immediately, use
23503      * {@link #startAnimation(android.view.animation.Animation)} instead.
23504      * This method provides allows fine-grained
23505      * control over the start time and invalidation, but you
23506      * must make sure that 1) the animation has a start time set, and
23507      * 2) the view's parent (which controls animations on its children)
23508      * will be invalidated when the animation is supposed to
23509      * start.
23510      *
23511      * @param animation The next animation, or null.
23512      */
setAnimation(Animation animation)23513     public void setAnimation(Animation animation) {
23514         mCurrentAnimation = animation;
23515 
23516         if (animation != null) {
23517             // If the screen is off assume the animation start time is now instead of
23518             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
23519             // would cause the animation to start when the screen turns back on
23520             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
23521                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
23522                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
23523             }
23524             animation.reset();
23525         }
23526     }
23527 
23528     /**
23529      * Invoked by a parent ViewGroup to notify the start of the animation
23530      * currently associated with this view. If you override this method,
23531      * always call super.onAnimationStart();
23532      *
23533      * @see #setAnimation(android.view.animation.Animation)
23534      * @see #getAnimation()
23535      */
23536     @CallSuper
onAnimationStart()23537     protected void onAnimationStart() {
23538         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
23539     }
23540 
23541     /**
23542      * Invoked by a parent ViewGroup to notify the end of the animation
23543      * currently associated with this view. If you override this method,
23544      * always call super.onAnimationEnd();
23545      *
23546      * @see #setAnimation(android.view.animation.Animation)
23547      * @see #getAnimation()
23548      */
23549     @CallSuper
onAnimationEnd()23550     protected void onAnimationEnd() {
23551         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
23552     }
23553 
23554     /**
23555      * Invoked if there is a Transform that involves alpha. Subclass that can
23556      * draw themselves with the specified alpha should return true, and then
23557      * respect that alpha when their onDraw() is called. If this returns false
23558      * then the view may be redirected to draw into an offscreen buffer to
23559      * fulfill the request, which will look fine, but may be slower than if the
23560      * subclass handles it internally. The default implementation returns false.
23561      *
23562      * @param alpha The alpha (0..255) to apply to the view's drawing
23563      * @return true if the view can draw with the specified alpha.
23564      */
onSetAlpha(int alpha)23565     protected boolean onSetAlpha(int alpha) {
23566         return false;
23567     }
23568 
23569     /**
23570      * This is used by the RootView to perform an optimization when
23571      * the view hierarchy contains one or several SurfaceView.
23572      * SurfaceView is always considered transparent, but its children are not,
23573      * therefore all View objects remove themselves from the global transparent
23574      * region (passed as a parameter to this function).
23575      *
23576      * @param region The transparent region for this ViewAncestor (window).
23577      *
23578      * @return Returns true if the effective visibility of the view at this
23579      * point is opaque, regardless of the transparent region; returns false
23580      * if it is possible for underlying windows to be seen behind the view.
23581      *
23582      * {@hide}
23583      */
gatherTransparentRegion(Region region)23584     public boolean gatherTransparentRegion(Region region) {
23585         final AttachInfo attachInfo = mAttachInfo;
23586         if (region != null && attachInfo != null) {
23587             final int pflags = mPrivateFlags;
23588             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
23589                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
23590                 // remove it from the transparent region.
23591                 final int[] location = attachInfo.mTransparentLocation;
23592                 getLocationInWindow(location);
23593                 // When a view has Z value, then it will be better to leave some area below the view
23594                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
23595                 // the bottom part needs more offset than the left, top and right parts due to the
23596                 // spot light effects.
23597                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
23598                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
23599                         location[0] + mRight - mLeft + shadowOffset,
23600                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
23601             } else {
23602                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
23603                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
23604                     // the background drawable's non-transparent parts from this transparent region.
23605                     applyDrawableToTransparentRegion(mBackground, region);
23606                 }
23607                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
23608                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
23609                     // Similarly, we remove the foreground drawable's non-transparent parts.
23610                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
23611                 }
23612                 if (mDefaultFocusHighlight != null
23613                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
23614                     // Similarly, we remove the default focus highlight's non-transparent parts.
23615                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
23616                 }
23617             }
23618         }
23619         return true;
23620     }
23621 
23622     /**
23623      * Play a sound effect for this view.
23624      *
23625      * <p>The framework will play sound effects for some built in actions, such as
23626      * clicking, but you may wish to play these effects in your widget,
23627      * for instance, for internal navigation.
23628      *
23629      * <p>The sound effect will only be played if sound effects are enabled by the user, and
23630      * {@link #isSoundEffectsEnabled()} is true.
23631      *
23632      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
23633      */
playSoundEffect(int soundConstant)23634     public void playSoundEffect(int soundConstant) {
23635         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
23636             return;
23637         }
23638         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
23639     }
23640 
23641     /**
23642      * BZZZTT!!1!
23643      *
23644      * <p>Provide haptic feedback to the user for this view.
23645      *
23646      * <p>The framework will provide haptic feedback for some built in actions,
23647      * such as long presses, but you may wish to provide feedback for your
23648      * own widget.
23649      *
23650      * <p>The feedback will only be performed if
23651      * {@link #isHapticFeedbackEnabled()} is true.
23652      *
23653      * @param feedbackConstant One of the constants defined in
23654      * {@link HapticFeedbackConstants}
23655      */
performHapticFeedback(int feedbackConstant)23656     public boolean performHapticFeedback(int feedbackConstant) {
23657         return performHapticFeedback(feedbackConstant, 0);
23658     }
23659 
23660     /**
23661      * BZZZTT!!1!
23662      *
23663      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
23664      *
23665      * @param feedbackConstant One of the constants defined in
23666      * {@link HapticFeedbackConstants}
23667      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
23668      */
performHapticFeedback(int feedbackConstant, int flags)23669     public boolean performHapticFeedback(int feedbackConstant, int flags) {
23670         if (mAttachInfo == null) {
23671             return false;
23672         }
23673         //noinspection SimplifiableIfStatement
23674         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
23675                 && !isHapticFeedbackEnabled()) {
23676             return false;
23677         }
23678         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
23679                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
23680     }
23681 
23682     /**
23683      * Request that the visibility of the status bar or other screen/window
23684      * decorations be changed.
23685      *
23686      * <p>This method is used to put the over device UI into temporary modes
23687      * where the user's attention is focused more on the application content,
23688      * by dimming or hiding surrounding system affordances.  This is typically
23689      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
23690      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
23691      * to be placed behind the action bar (and with these flags other system
23692      * affordances) so that smooth transitions between hiding and showing them
23693      * can be done.
23694      *
23695      * <p>Two representative examples of the use of system UI visibility is
23696      * implementing a content browsing application (like a magazine reader)
23697      * and a video playing application.
23698      *
23699      * <p>The first code shows a typical implementation of a View in a content
23700      * browsing application.  In this implementation, the application goes
23701      * into a content-oriented mode by hiding the status bar and action bar,
23702      * and putting the navigation elements into lights out mode.  The user can
23703      * then interact with content while in this mode.  Such an application should
23704      * provide an easy way for the user to toggle out of the mode (such as to
23705      * check information in the status bar or access notifications).  In the
23706      * implementation here, this is done simply by tapping on the content.
23707      *
23708      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
23709      *      content}
23710      *
23711      * <p>This second code sample shows a typical implementation of a View
23712      * in a video playing application.  In this situation, while the video is
23713      * playing the application would like to go into a complete full-screen mode,
23714      * to use as much of the display as possible for the video.  When in this state
23715      * the user can not interact with the application; the system intercepts
23716      * touching on the screen to pop the UI out of full screen mode.  See
23717      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
23718      *
23719      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
23720      *      content}
23721      *
23722      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
23723      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
23724      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
23725      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
23726      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
23727      */
setSystemUiVisibility(int visibility)23728     public void setSystemUiVisibility(int visibility) {
23729         if (visibility != mSystemUiVisibility) {
23730             mSystemUiVisibility = visibility;
23731             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
23732                 mParent.recomputeViewAttributes(this);
23733             }
23734         }
23735     }
23736 
23737     /**
23738      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
23739      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
23740      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
23741      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
23742      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
23743      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
23744      */
getSystemUiVisibility()23745     public int getSystemUiVisibility() {
23746         return mSystemUiVisibility;
23747     }
23748 
23749     /**
23750      * Returns the current system UI visibility that is currently set for
23751      * the entire window.  This is the combination of the
23752      * {@link #setSystemUiVisibility(int)} values supplied by all of the
23753      * views in the window.
23754      */
getWindowSystemUiVisibility()23755     public int getWindowSystemUiVisibility() {
23756         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
23757     }
23758 
23759     /**
23760      * Override to find out when the window's requested system UI visibility
23761      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
23762      * This is different from the callbacks received through
23763      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
23764      * in that this is only telling you about the local request of the window,
23765      * not the actual values applied by the system.
23766      */
onWindowSystemUiVisibilityChanged(int visible)23767     public void onWindowSystemUiVisibilityChanged(int visible) {
23768     }
23769 
23770     /**
23771      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
23772      * the view hierarchy.
23773      */
dispatchWindowSystemUiVisiblityChanged(int visible)23774     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
23775         onWindowSystemUiVisibilityChanged(visible);
23776     }
23777 
23778     /**
23779      * Set a listener to receive callbacks when the visibility of the system bar changes.
23780      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
23781      */
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)23782     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
23783         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
23784         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
23785             mParent.recomputeViewAttributes(this);
23786         }
23787     }
23788 
23789     /**
23790      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
23791      * the view hierarchy.
23792      */
dispatchSystemUiVisibilityChanged(int visibility)23793     public void dispatchSystemUiVisibilityChanged(int visibility) {
23794         ListenerInfo li = mListenerInfo;
23795         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
23796             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
23797                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
23798         }
23799     }
23800 
updateLocalSystemUiVisibility(int localValue, int localChanges)23801     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
23802         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
23803         if (val != mSystemUiVisibility) {
23804             setSystemUiVisibility(val);
23805             return true;
23806         }
23807         return false;
23808     }
23809 
23810     /** @hide */
setDisabledSystemUiVisibility(int flags)23811     public void setDisabledSystemUiVisibility(int flags) {
23812         if (mAttachInfo != null) {
23813             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
23814                 mAttachInfo.mDisabledSystemUiVisibility = flags;
23815                 if (mParent != null) {
23816                     mParent.recomputeViewAttributes(this);
23817                 }
23818             }
23819         }
23820     }
23821 
23822     /**
23823      * Creates an image that the system displays during the drag and drop
23824      * operation. This is called a &quot;drag shadow&quot;. The default implementation
23825      * for a DragShadowBuilder based on a View returns an image that has exactly the same
23826      * appearance as the given View. The default also positions the center of the drag shadow
23827      * directly under the touch point. If no View is provided (the constructor with no parameters
23828      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
23829      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
23830      * default is an invisible drag shadow.
23831      * <p>
23832      * You are not required to use the View you provide to the constructor as the basis of the
23833      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
23834      * anything you want as the drag shadow.
23835      * </p>
23836      * <p>
23837      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
23838      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
23839      *  size and position of the drag shadow. It uses this data to construct a
23840      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
23841      *  so that your application can draw the shadow image in the Canvas.
23842      * </p>
23843      *
23844      * <div class="special reference">
23845      * <h3>Developer Guides</h3>
23846      * <p>For a guide to implementing drag and drop features, read the
23847      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
23848      * </div>
23849      */
23850     public static class DragShadowBuilder {
23851         private final WeakReference<View> mView;
23852 
23853         /**
23854          * Constructs a shadow image builder based on a View. By default, the resulting drag
23855          * shadow will have the same appearance and dimensions as the View, with the touch point
23856          * over the center of the View.
23857          * @param view A View. Any View in scope can be used.
23858          */
DragShadowBuilder(View view)23859         public DragShadowBuilder(View view) {
23860             mView = new WeakReference<View>(view);
23861         }
23862 
23863         /**
23864          * Construct a shadow builder object with no associated View.  This
23865          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
23866          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
23867          * to supply the drag shadow's dimensions and appearance without
23868          * reference to any View object.
23869          */
DragShadowBuilder()23870         public DragShadowBuilder() {
23871             mView = new WeakReference<View>(null);
23872         }
23873 
23874         /**
23875          * Returns the View object that had been passed to the
23876          * {@link #View.DragShadowBuilder(View)}
23877          * constructor.  If that View parameter was {@code null} or if the
23878          * {@link #View.DragShadowBuilder()}
23879          * constructor was used to instantiate the builder object, this method will return
23880          * null.
23881          *
23882          * @return The View object associate with this builder object.
23883          */
23884         @SuppressWarnings({"JavadocReference"})
getView()23885         final public View getView() {
23886             return mView.get();
23887         }
23888 
23889         /**
23890          * Provides the metrics for the shadow image. These include the dimensions of
23891          * the shadow image, and the point within that shadow that should
23892          * be centered under the touch location while dragging.
23893          * <p>
23894          * The default implementation sets the dimensions of the shadow to be the
23895          * same as the dimensions of the View itself and centers the shadow under
23896          * the touch point.
23897          * </p>
23898          *
23899          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
23900          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
23901          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
23902          * image.
23903          *
23904          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
23905          * shadow image that should be underneath the touch point during the drag and drop
23906          * operation. Your application must set {@link android.graphics.Point#x} to the
23907          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
23908          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)23909         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
23910             final View view = mView.get();
23911             if (view != null) {
23912                 outShadowSize.set(view.getWidth(), view.getHeight());
23913                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
23914             } else {
23915                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
23916             }
23917         }
23918 
23919         /**
23920          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
23921          * based on the dimensions it received from the
23922          * {@link #onProvideShadowMetrics(Point, Point)} callback.
23923          *
23924          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
23925          */
onDrawShadow(Canvas canvas)23926         public void onDrawShadow(Canvas canvas) {
23927             final View view = mView.get();
23928             if (view != null) {
23929                 view.draw(canvas);
23930             } else {
23931                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
23932             }
23933         }
23934     }
23935 
23936     /**
23937      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
23938      * startDragAndDrop()} for newer platform versions.
23939      */
23940     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)23941     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
23942                                    Object myLocalState, int flags) {
23943         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
23944     }
23945 
23946     /**
23947      * Starts a drag and drop operation. When your application calls this method, it passes a
23948      * {@link android.view.View.DragShadowBuilder} object to the system. The
23949      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
23950      * to get metrics for the drag shadow, and then calls the object's
23951      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
23952      * <p>
23953      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
23954      *  drag events to all the View objects in your application that are currently visible. It does
23955      *  this either by calling the View object's drag listener (an implementation of
23956      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
23957      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
23958      *  Both are passed a {@link android.view.DragEvent} object that has a
23959      *  {@link android.view.DragEvent#getAction()} value of
23960      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
23961      * </p>
23962      * <p>
23963      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
23964      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
23965      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
23966      * to the View the user selected for dragging.
23967      * </p>
23968      * @param data A {@link android.content.ClipData} object pointing to the data to be
23969      * transferred by the drag and drop operation.
23970      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
23971      * drag shadow.
23972      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
23973      * drop operation. When dispatching drag events to views in the same activity this object
23974      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
23975      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
23976      * will return null).
23977      * <p>
23978      * myLocalState is a lightweight mechanism for the sending information from the dragged View
23979      * to the target Views. For example, it can contain flags that differentiate between a
23980      * a copy operation and a move operation.
23981      * </p>
23982      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
23983      * flags, or any combination of the following:
23984      *     <ul>
23985      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
23986      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
23987      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
23988      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
23989      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
23990      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
23991      *     </ul>
23992      * @return {@code true} if the method completes successfully, or
23993      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
23994      * do a drag, and so no drag operation is in progress.
23995      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)23996     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
23997             Object myLocalState, int flags) {
23998         if (ViewDebug.DEBUG_DRAG) {
23999             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
24000         }
24001         if (mAttachInfo == null) {
24002             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
24003             return false;
24004         }
24005 
24006         if (data != null) {
24007             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
24008         }
24009 
24010         Point shadowSize = new Point();
24011         Point shadowTouchPoint = new Point();
24012         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
24013 
24014         if ((shadowSize.x < 0) || (shadowSize.y < 0)
24015                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
24016             throw new IllegalStateException("Drag shadow dimensions must not be negative");
24017         }
24018 
24019         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
24020         // does not accept zero size surface.
24021         if (shadowSize.x == 0  || shadowSize.y == 0) {
24022             if (!sAcceptZeroSizeDragShadow) {
24023                 throw new IllegalStateException("Drag shadow dimensions must be positive");
24024             }
24025             shadowSize.x = 1;
24026             shadowSize.y = 1;
24027         }
24028 
24029         if (ViewDebug.DEBUG_DRAG) {
24030             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
24031                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
24032         }
24033         if (mAttachInfo.mDragSurface != null) {
24034             mAttachInfo.mDragSurface.release();
24035         }
24036         mAttachInfo.mDragSurface = new Surface();
24037         mAttachInfo.mDragToken = null;
24038 
24039         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
24040         final SurfaceSession session = new SurfaceSession(root.mSurface);
24041         final SurfaceControl surface = new SurfaceControl.Builder(session)
24042                 .setName("drag surface")
24043                 .setSize(shadowSize.x, shadowSize.y)
24044                 .setFormat(PixelFormat.TRANSLUCENT)
24045                 .build();
24046         try {
24047             mAttachInfo.mDragSurface.copyFrom(surface);
24048             final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
24049             try {
24050                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
24051                 shadowBuilder.onDrawShadow(canvas);
24052             } finally {
24053                 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
24054             }
24055 
24056             // Cache the local state object for delivery with DragEvents
24057             root.setLocalDragState(myLocalState);
24058 
24059             // repurpose 'shadowSize' for the last touch point
24060             root.getLastTouchPoint(shadowSize);
24061 
24062             mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag(
24063                     mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(),
24064                     shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
24065             if (ViewDebug.DEBUG_DRAG) {
24066                 Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken);
24067             }
24068 
24069             return mAttachInfo.mDragToken != null;
24070         } catch (Exception e) {
24071             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
24072             return false;
24073         } finally {
24074             if (mAttachInfo.mDragToken == null) {
24075                 mAttachInfo.mDragSurface.destroy();
24076                 mAttachInfo.mDragSurface = null;
24077                 root.setLocalDragState(null);
24078             }
24079             session.kill();
24080         }
24081     }
24082 
24083     /**
24084      * Cancels an ongoing drag and drop operation.
24085      * <p>
24086      * A {@link android.view.DragEvent} object with
24087      * {@link android.view.DragEvent#getAction()} value of
24088      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
24089      * {@link android.view.DragEvent#getResult()} value of {@code false}
24090      * will be sent to every
24091      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
24092      * even if they are not currently visible.
24093      * </p>
24094      * <p>
24095      * This method can be called on any View in the same window as the View on which
24096      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
24097      * was called.
24098      * </p>
24099      */
cancelDragAndDrop()24100     public final void cancelDragAndDrop() {
24101         if (ViewDebug.DEBUG_DRAG) {
24102             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
24103         }
24104         if (mAttachInfo == null) {
24105             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
24106             return;
24107         }
24108         if (mAttachInfo.mDragToken != null) {
24109             try {
24110                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
24111             } catch (Exception e) {
24112                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
24113             }
24114             mAttachInfo.mDragToken = null;
24115         } else {
24116             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
24117         }
24118     }
24119 
24120     /**
24121      * Updates the drag shadow for the ongoing drag and drop operation.
24122      *
24123      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
24124      * new drag shadow.
24125      */
updateDragShadow(DragShadowBuilder shadowBuilder)24126     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
24127         if (ViewDebug.DEBUG_DRAG) {
24128             Log.d(VIEW_LOG_TAG, "updateDragShadow");
24129         }
24130         if (mAttachInfo == null) {
24131             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
24132             return;
24133         }
24134         if (mAttachInfo.mDragToken != null) {
24135             try {
24136                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
24137                 try {
24138                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
24139                     shadowBuilder.onDrawShadow(canvas);
24140                 } finally {
24141                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
24142                 }
24143             } catch (Exception e) {
24144                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
24145             }
24146         } else {
24147             Log.e(VIEW_LOG_TAG, "No active drag");
24148         }
24149     }
24150 
24151     /**
24152      * Starts a move from {startX, startY}, the amount of the movement will be the offset
24153      * between {startX, startY} and the new cursor positon.
24154      * @param startX horizontal coordinate where the move started.
24155      * @param startY vertical coordinate where the move started.
24156      * @return whether moving was started successfully.
24157      * @hide
24158      */
startMovingTask(float startX, float startY)24159     public final boolean startMovingTask(float startX, float startY) {
24160         if (ViewDebug.DEBUG_POSITIONING) {
24161             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
24162         }
24163         try {
24164             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
24165         } catch (RemoteException e) {
24166             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
24167         }
24168         return false;
24169     }
24170 
24171     /**
24172      * Handles drag events sent by the system following a call to
24173      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
24174      * startDragAndDrop()}.
24175      *<p>
24176      * When the system calls this method, it passes a
24177      * {@link android.view.DragEvent} object. A call to
24178      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
24179      * in DragEvent. The method uses these to determine what is happening in the drag and drop
24180      * operation.
24181      * @param event The {@link android.view.DragEvent} sent by the system.
24182      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
24183      * in DragEvent, indicating the type of drag event represented by this object.
24184      * @return {@code true} if the method was successful, otherwise {@code false}.
24185      * <p>
24186      *  The method should return {@code true} in response to an action type of
24187      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
24188      *  operation.
24189      * </p>
24190      * <p>
24191      *  The method should also return {@code true} in response to an action type of
24192      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
24193      *  {@code false} if it didn't.
24194      * </p>
24195      * <p>
24196      *  For all other events, the return value is ignored.
24197      * </p>
24198      */
onDragEvent(DragEvent event)24199     public boolean onDragEvent(DragEvent event) {
24200         return false;
24201     }
24202 
24203     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)24204     boolean dispatchDragEnterExitInPreN(DragEvent event) {
24205         return callDragEventHandler(event);
24206     }
24207 
24208     /**
24209      * Detects if this View is enabled and has a drag event listener.
24210      * If both are true, then it calls the drag event listener with the
24211      * {@link android.view.DragEvent} it received. If the drag event listener returns
24212      * {@code true}, then dispatchDragEvent() returns {@code true}.
24213      * <p>
24214      * For all other cases, the method calls the
24215      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
24216      * method and returns its result.
24217      * </p>
24218      * <p>
24219      * This ensures that a drag event is always consumed, even if the View does not have a drag
24220      * event listener. However, if the View has a listener and the listener returns true, then
24221      * onDragEvent() is not called.
24222      * </p>
24223      */
dispatchDragEvent(DragEvent event)24224     public boolean dispatchDragEvent(DragEvent event) {
24225         event.mEventHandlerWasCalled = true;
24226         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
24227             event.mAction == DragEvent.ACTION_DROP) {
24228             // About to deliver an event with coordinates to this view. Notify that now this view
24229             // has drag focus. This will send exit/enter events as needed.
24230             getViewRootImpl().setDragFocus(this, event);
24231         }
24232         return callDragEventHandler(event);
24233     }
24234 
callDragEventHandler(DragEvent event)24235     final boolean callDragEventHandler(DragEvent event) {
24236         final boolean result;
24237 
24238         ListenerInfo li = mListenerInfo;
24239         //noinspection SimplifiableIfStatement
24240         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
24241                 && li.mOnDragListener.onDrag(this, event)) {
24242             result = true;
24243         } else {
24244             result = onDragEvent(event);
24245         }
24246 
24247         switch (event.mAction) {
24248             case DragEvent.ACTION_DRAG_ENTERED: {
24249                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
24250                 refreshDrawableState();
24251             } break;
24252             case DragEvent.ACTION_DRAG_EXITED: {
24253                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
24254                 refreshDrawableState();
24255             } break;
24256             case DragEvent.ACTION_DRAG_ENDED: {
24257                 mPrivateFlags2 &= ~View.DRAG_MASK;
24258                 refreshDrawableState();
24259             } break;
24260         }
24261 
24262         return result;
24263     }
24264 
canAcceptDrag()24265     boolean canAcceptDrag() {
24266         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
24267     }
24268 
24269     /**
24270      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
24271      * it is ever exposed at all.
24272      * @hide
24273      */
onCloseSystemDialogs(String reason)24274     public void onCloseSystemDialogs(String reason) {
24275     }
24276 
24277     /**
24278      * Given a Drawable whose bounds have been set to draw into this view,
24279      * update a Region being computed for
24280      * {@link #gatherTransparentRegion(android.graphics.Region)} so
24281      * that any non-transparent parts of the Drawable are removed from the
24282      * given transparent region.
24283      *
24284      * @param dr The Drawable whose transparency is to be applied to the region.
24285      * @param region A Region holding the current transparency information,
24286      * where any parts of the region that are set are considered to be
24287      * transparent.  On return, this region will be modified to have the
24288      * transparency information reduced by the corresponding parts of the
24289      * Drawable that are not transparent.
24290      * {@hide}
24291      */
applyDrawableToTransparentRegion(Drawable dr, Region region)24292     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
24293         if (DBG) {
24294             Log.i("View", "Getting transparent region for: " + this);
24295         }
24296         final Region r = dr.getTransparentRegion();
24297         final Rect db = dr.getBounds();
24298         final AttachInfo attachInfo = mAttachInfo;
24299         if (r != null && attachInfo != null) {
24300             final int w = getRight()-getLeft();
24301             final int h = getBottom()-getTop();
24302             if (db.left > 0) {
24303                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
24304                 r.op(0, 0, db.left, h, Region.Op.UNION);
24305             }
24306             if (db.right < w) {
24307                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
24308                 r.op(db.right, 0, w, h, Region.Op.UNION);
24309             }
24310             if (db.top > 0) {
24311                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
24312                 r.op(0, 0, w, db.top, Region.Op.UNION);
24313             }
24314             if (db.bottom < h) {
24315                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
24316                 r.op(0, db.bottom, w, h, Region.Op.UNION);
24317             }
24318             final int[] location = attachInfo.mTransparentLocation;
24319             getLocationInWindow(location);
24320             r.translate(location[0], location[1]);
24321             region.op(r, Region.Op.INTERSECT);
24322         } else {
24323             region.op(db, Region.Op.DIFFERENCE);
24324         }
24325     }
24326 
checkForLongClick(int delayOffset, float x, float y)24327     private void checkForLongClick(int delayOffset, float x, float y) {
24328         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
24329             mHasPerformedLongPress = false;
24330 
24331             if (mPendingCheckForLongPress == null) {
24332                 mPendingCheckForLongPress = new CheckForLongPress();
24333             }
24334             mPendingCheckForLongPress.setAnchor(x, y);
24335             mPendingCheckForLongPress.rememberWindowAttachCount();
24336             mPendingCheckForLongPress.rememberPressedState();
24337             postDelayed(mPendingCheckForLongPress,
24338                     ViewConfiguration.getLongPressTimeout() - delayOffset);
24339         }
24340     }
24341 
24342     /**
24343      * Inflate a view from an XML resource.  This convenience method wraps the {@link
24344      * LayoutInflater} class, which provides a full range of options for view inflation.
24345      *
24346      * @param context The Context object for your activity or application.
24347      * @param resource The resource ID to inflate
24348      * @param root A view group that will be the parent.  Used to properly inflate the
24349      * layout_* parameters.
24350      * @see LayoutInflater
24351      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)24352     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
24353         LayoutInflater factory = LayoutInflater.from(context);
24354         return factory.inflate(resource, root);
24355     }
24356 
24357     /**
24358      * Scroll the view with standard behavior for scrolling beyond the normal
24359      * content boundaries. Views that call this method should override
24360      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
24361      * results of an over-scroll operation.
24362      *
24363      * Views can use this method to handle any touch or fling-based scrolling.
24364      *
24365      * @param deltaX Change in X in pixels
24366      * @param deltaY Change in Y in pixels
24367      * @param scrollX Current X scroll value in pixels before applying deltaX
24368      * @param scrollY Current Y scroll value in pixels before applying deltaY
24369      * @param scrollRangeX Maximum content scroll range along the X axis
24370      * @param scrollRangeY Maximum content scroll range along the Y axis
24371      * @param maxOverScrollX Number of pixels to overscroll by in either direction
24372      *          along the X axis.
24373      * @param maxOverScrollY Number of pixels to overscroll by in either direction
24374      *          along the Y axis.
24375      * @param isTouchEvent true if this scroll operation is the result of a touch event.
24376      * @return true if scrolling was clamped to an over-scroll boundary along either
24377      *          axis, false otherwise.
24378      */
24379     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)24380     protected boolean overScrollBy(int deltaX, int deltaY,
24381             int scrollX, int scrollY,
24382             int scrollRangeX, int scrollRangeY,
24383             int maxOverScrollX, int maxOverScrollY,
24384             boolean isTouchEvent) {
24385         final int overScrollMode = mOverScrollMode;
24386         final boolean canScrollHorizontal =
24387                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
24388         final boolean canScrollVertical =
24389                 computeVerticalScrollRange() > computeVerticalScrollExtent();
24390         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
24391                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
24392         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
24393                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
24394 
24395         int newScrollX = scrollX + deltaX;
24396         if (!overScrollHorizontal) {
24397             maxOverScrollX = 0;
24398         }
24399 
24400         int newScrollY = scrollY + deltaY;
24401         if (!overScrollVertical) {
24402             maxOverScrollY = 0;
24403         }
24404 
24405         // Clamp values if at the limits and record
24406         final int left = -maxOverScrollX;
24407         final int right = maxOverScrollX + scrollRangeX;
24408         final int top = -maxOverScrollY;
24409         final int bottom = maxOverScrollY + scrollRangeY;
24410 
24411         boolean clampedX = false;
24412         if (newScrollX > right) {
24413             newScrollX = right;
24414             clampedX = true;
24415         } else if (newScrollX < left) {
24416             newScrollX = left;
24417             clampedX = true;
24418         }
24419 
24420         boolean clampedY = false;
24421         if (newScrollY > bottom) {
24422             newScrollY = bottom;
24423             clampedY = true;
24424         } else if (newScrollY < top) {
24425             newScrollY = top;
24426             clampedY = true;
24427         }
24428 
24429         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
24430 
24431         return clampedX || clampedY;
24432     }
24433 
24434     /**
24435      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
24436      * respond to the results of an over-scroll operation.
24437      *
24438      * @param scrollX New X scroll value in pixels
24439      * @param scrollY New Y scroll value in pixels
24440      * @param clampedX True if scrollX was clamped to an over-scroll boundary
24441      * @param clampedY True if scrollY was clamped to an over-scroll boundary
24442      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)24443     protected void onOverScrolled(int scrollX, int scrollY,
24444             boolean clampedX, boolean clampedY) {
24445         // Intentionally empty.
24446     }
24447 
24448     /**
24449      * Returns the over-scroll mode for this view. The result will be
24450      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
24451      * (allow over-scrolling only if the view content is larger than the container),
24452      * or {@link #OVER_SCROLL_NEVER}.
24453      *
24454      * @return This view's over-scroll mode.
24455      */
getOverScrollMode()24456     public int getOverScrollMode() {
24457         return mOverScrollMode;
24458     }
24459 
24460     /**
24461      * Set the over-scroll mode for this view. Valid over-scroll modes are
24462      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
24463      * (allow over-scrolling only if the view content is larger than the container),
24464      * or {@link #OVER_SCROLL_NEVER}.
24465      *
24466      * Setting the over-scroll mode of a view will have an effect only if the
24467      * view is capable of scrolling.
24468      *
24469      * @param overScrollMode The new over-scroll mode for this view.
24470      */
setOverScrollMode(int overScrollMode)24471     public void setOverScrollMode(int overScrollMode) {
24472         if (overScrollMode != OVER_SCROLL_ALWAYS &&
24473                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
24474                 overScrollMode != OVER_SCROLL_NEVER) {
24475             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
24476         }
24477         mOverScrollMode = overScrollMode;
24478     }
24479 
24480     /**
24481      * Enable or disable nested scrolling for this view.
24482      *
24483      * <p>If this property is set to true the view will be permitted to initiate nested
24484      * scrolling operations with a compatible parent view in the current hierarchy. If this
24485      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
24486      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
24487      * the nested scroll.</p>
24488      *
24489      * @param enabled true to enable nested scrolling, false to disable
24490      *
24491      * @see #isNestedScrollingEnabled()
24492      */
setNestedScrollingEnabled(boolean enabled)24493     public void setNestedScrollingEnabled(boolean enabled) {
24494         if (enabled) {
24495             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
24496         } else {
24497             stopNestedScroll();
24498             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
24499         }
24500     }
24501 
24502     /**
24503      * Returns true if nested scrolling is enabled for this view.
24504      *
24505      * <p>If nested scrolling is enabled and this View class implementation supports it,
24506      * this view will act as a nested scrolling child view when applicable, forwarding data
24507      * about the scroll operation in progress to a compatible and cooperating nested scrolling
24508      * parent.</p>
24509      *
24510      * @return true if nested scrolling is enabled
24511      *
24512      * @see #setNestedScrollingEnabled(boolean)
24513      */
isNestedScrollingEnabled()24514     public boolean isNestedScrollingEnabled() {
24515         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
24516                 PFLAG3_NESTED_SCROLLING_ENABLED;
24517     }
24518 
24519     /**
24520      * Begin a nestable scroll operation along the given axes.
24521      *
24522      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
24523      *
24524      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
24525      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
24526      * In the case of touch scrolling the nested scroll will be terminated automatically in
24527      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
24528      * In the event of programmatic scrolling the caller must explicitly call
24529      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
24530      *
24531      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
24532      * If it returns false the caller may ignore the rest of this contract until the next scroll.
24533      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
24534      *
24535      * <p>At each incremental step of the scroll the caller should invoke
24536      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
24537      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
24538      * parent at least partially consumed the scroll and the caller should adjust the amount it
24539      * scrolls by.</p>
24540      *
24541      * <p>After applying the remainder of the scroll delta the caller should invoke
24542      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
24543      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
24544      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
24545      * </p>
24546      *
24547      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
24548      *             {@link #SCROLL_AXIS_VERTICAL}.
24549      * @return true if a cooperative parent was found and nested scrolling has been enabled for
24550      *         the current gesture.
24551      *
24552      * @see #stopNestedScroll()
24553      * @see #dispatchNestedPreScroll(int, int, int[], int[])
24554      * @see #dispatchNestedScroll(int, int, int, int, int[])
24555      */
startNestedScroll(int axes)24556     public boolean startNestedScroll(int axes) {
24557         if (hasNestedScrollingParent()) {
24558             // Already in progress
24559             return true;
24560         }
24561         if (isNestedScrollingEnabled()) {
24562             ViewParent p = getParent();
24563             View child = this;
24564             while (p != null) {
24565                 try {
24566                     if (p.onStartNestedScroll(child, this, axes)) {
24567                         mNestedScrollingParent = p;
24568                         p.onNestedScrollAccepted(child, this, axes);
24569                         return true;
24570                     }
24571                 } catch (AbstractMethodError e) {
24572                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
24573                             "method onStartNestedScroll", e);
24574                     // Allow the search upward to continue
24575                 }
24576                 if (p instanceof View) {
24577                     child = (View) p;
24578                 }
24579                 p = p.getParent();
24580             }
24581         }
24582         return false;
24583     }
24584 
24585     /**
24586      * Stop a nested scroll in progress.
24587      *
24588      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
24589      *
24590      * @see #startNestedScroll(int)
24591      */
stopNestedScroll()24592     public void stopNestedScroll() {
24593         if (mNestedScrollingParent != null) {
24594             mNestedScrollingParent.onStopNestedScroll(this);
24595             mNestedScrollingParent = null;
24596         }
24597     }
24598 
24599     /**
24600      * Returns true if this view has a nested scrolling parent.
24601      *
24602      * <p>The presence of a nested scrolling parent indicates that this view has initiated
24603      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
24604      *
24605      * @return whether this view has a nested scrolling parent
24606      */
hasNestedScrollingParent()24607     public boolean hasNestedScrollingParent() {
24608         return mNestedScrollingParent != null;
24609     }
24610 
24611     /**
24612      * Dispatch one step of a nested scroll in progress.
24613      *
24614      * <p>Implementations of views that support nested scrolling should call this to report
24615      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
24616      * is not currently in progress or nested scrolling is not
24617      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
24618      *
24619      * <p>Compatible View implementations should also call
24620      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
24621      * consuming a component of the scroll event themselves.</p>
24622      *
24623      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
24624      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
24625      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
24626      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
24627      * @param offsetInWindow Optional. If not null, on return this will contain the offset
24628      *                       in local view coordinates of this view from before this operation
24629      *                       to after it completes. View implementations may use this to adjust
24630      *                       expected input coordinate tracking.
24631      * @return true if the event was dispatched, false if it could not be dispatched.
24632      * @see #dispatchNestedPreScroll(int, int, int[], int[])
24633      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)24634     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
24635             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
24636         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
24637             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
24638                 int startX = 0;
24639                 int startY = 0;
24640                 if (offsetInWindow != null) {
24641                     getLocationInWindow(offsetInWindow);
24642                     startX = offsetInWindow[0];
24643                     startY = offsetInWindow[1];
24644                 }
24645 
24646                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
24647                         dxUnconsumed, dyUnconsumed);
24648 
24649                 if (offsetInWindow != null) {
24650                     getLocationInWindow(offsetInWindow);
24651                     offsetInWindow[0] -= startX;
24652                     offsetInWindow[1] -= startY;
24653                 }
24654                 return true;
24655             } else if (offsetInWindow != null) {
24656                 // No motion, no dispatch. Keep offsetInWindow up to date.
24657                 offsetInWindow[0] = 0;
24658                 offsetInWindow[1] = 0;
24659             }
24660         }
24661         return false;
24662     }
24663 
24664     /**
24665      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
24666      *
24667      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
24668      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
24669      * scrolling operation to consume some or all of the scroll operation before the child view
24670      * consumes it.</p>
24671      *
24672      * @param dx Horizontal scroll distance in pixels
24673      * @param dy Vertical scroll distance in pixels
24674      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
24675      *                 and consumed[1] the consumed dy.
24676      * @param offsetInWindow Optional. If not null, on return this will contain the offset
24677      *                       in local view coordinates of this view from before this operation
24678      *                       to after it completes. View implementations may use this to adjust
24679      *                       expected input coordinate tracking.
24680      * @return true if the parent consumed some or all of the scroll delta
24681      * @see #dispatchNestedScroll(int, int, int, int, int[])
24682      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)24683     public boolean dispatchNestedPreScroll(int dx, int dy,
24684             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
24685         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
24686             if (dx != 0 || dy != 0) {
24687                 int startX = 0;
24688                 int startY = 0;
24689                 if (offsetInWindow != null) {
24690                     getLocationInWindow(offsetInWindow);
24691                     startX = offsetInWindow[0];
24692                     startY = offsetInWindow[1];
24693                 }
24694 
24695                 if (consumed == null) {
24696                     if (mTempNestedScrollConsumed == null) {
24697                         mTempNestedScrollConsumed = new int[2];
24698                     }
24699                     consumed = mTempNestedScrollConsumed;
24700                 }
24701                 consumed[0] = 0;
24702                 consumed[1] = 0;
24703                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
24704 
24705                 if (offsetInWindow != null) {
24706                     getLocationInWindow(offsetInWindow);
24707                     offsetInWindow[0] -= startX;
24708                     offsetInWindow[1] -= startY;
24709                 }
24710                 return consumed[0] != 0 || consumed[1] != 0;
24711             } else if (offsetInWindow != null) {
24712                 offsetInWindow[0] = 0;
24713                 offsetInWindow[1] = 0;
24714             }
24715         }
24716         return false;
24717     }
24718 
24719     /**
24720      * Dispatch a fling to a nested scrolling parent.
24721      *
24722      * <p>This method should be used to indicate that a nested scrolling child has detected
24723      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
24724      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
24725      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
24726      * along a scrollable axis.</p>
24727      *
24728      * <p>If a nested scrolling child view would normally fling but it is at the edge of
24729      * its own content, it can use this method to delegate the fling to its nested scrolling
24730      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
24731      *
24732      * @param velocityX Horizontal fling velocity in pixels per second
24733      * @param velocityY Vertical fling velocity in pixels per second
24734      * @param consumed true if the child consumed the fling, false otherwise
24735      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
24736      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)24737     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
24738         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
24739             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
24740         }
24741         return false;
24742     }
24743 
24744     /**
24745      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
24746      *
24747      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
24748      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
24749      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
24750      * before the child view consumes it. If this method returns <code>true</code>, a nested
24751      * parent view consumed the fling and this view should not scroll as a result.</p>
24752      *
24753      * <p>For a better user experience, only one view in a nested scrolling chain should consume
24754      * the fling at a time. If a parent view consumed the fling this method will return false.
24755      * Custom view implementations should account for this in two ways:</p>
24756      *
24757      * <ul>
24758      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
24759      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
24760      *     position regardless.</li>
24761      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
24762      *     even to settle back to a valid idle position.</li>
24763      * </ul>
24764      *
24765      * <p>Views should also not offer fling velocities to nested parent views along an axis
24766      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
24767      * should not offer a horizontal fling velocity to its parents since scrolling along that
24768      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
24769      *
24770      * @param velocityX Horizontal fling velocity in pixels per second
24771      * @param velocityY Vertical fling velocity in pixels per second
24772      * @return true if a nested scrolling parent consumed the fling
24773      */
dispatchNestedPreFling(float velocityX, float velocityY)24774     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
24775         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
24776             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
24777         }
24778         return false;
24779     }
24780 
24781     /**
24782      * Gets a scale factor that determines the distance the view should scroll
24783      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
24784      * @return The vertical scroll scale factor.
24785      * @hide
24786      */
getVerticalScrollFactor()24787     protected float getVerticalScrollFactor() {
24788         if (mVerticalScrollFactor == 0) {
24789             TypedValue outValue = new TypedValue();
24790             if (!mContext.getTheme().resolveAttribute(
24791                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
24792                 throw new IllegalStateException(
24793                         "Expected theme to define listPreferredItemHeight.");
24794             }
24795             mVerticalScrollFactor = outValue.getDimension(
24796                     mContext.getResources().getDisplayMetrics());
24797         }
24798         return mVerticalScrollFactor;
24799     }
24800 
24801     /**
24802      * Gets a scale factor that determines the distance the view should scroll
24803      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
24804      * @return The horizontal scroll scale factor.
24805      * @hide
24806      */
getHorizontalScrollFactor()24807     protected float getHorizontalScrollFactor() {
24808         // TODO: Should use something else.
24809         return getVerticalScrollFactor();
24810     }
24811 
24812     /**
24813      * Return the value specifying the text direction or policy that was set with
24814      * {@link #setTextDirection(int)}.
24815      *
24816      * @return the defined text direction. It can be one of:
24817      *
24818      * {@link #TEXT_DIRECTION_INHERIT},
24819      * {@link #TEXT_DIRECTION_FIRST_STRONG},
24820      * {@link #TEXT_DIRECTION_ANY_RTL},
24821      * {@link #TEXT_DIRECTION_LTR},
24822      * {@link #TEXT_DIRECTION_RTL},
24823      * {@link #TEXT_DIRECTION_LOCALE},
24824      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
24825      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
24826      *
24827      * @attr ref android.R.styleable#View_textDirection
24828      *
24829      * @hide
24830      */
24831     @ViewDebug.ExportedProperty(category = "text", mapping = {
24832             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
24833             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
24834             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
24835             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
24836             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
24837             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
24838             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
24839             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
24840     })
getRawTextDirection()24841     public int getRawTextDirection() {
24842         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
24843     }
24844 
24845     /**
24846      * Set the text direction.
24847      *
24848      * @param textDirection the direction to set. Should be one of:
24849      *
24850      * {@link #TEXT_DIRECTION_INHERIT},
24851      * {@link #TEXT_DIRECTION_FIRST_STRONG},
24852      * {@link #TEXT_DIRECTION_ANY_RTL},
24853      * {@link #TEXT_DIRECTION_LTR},
24854      * {@link #TEXT_DIRECTION_RTL},
24855      * {@link #TEXT_DIRECTION_LOCALE}
24856      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
24857      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
24858      *
24859      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
24860      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
24861      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
24862      *
24863      * @attr ref android.R.styleable#View_textDirection
24864      */
setTextDirection(int textDirection)24865     public void setTextDirection(int textDirection) {
24866         if (getRawTextDirection() != textDirection) {
24867             // Reset the current text direction and the resolved one
24868             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
24869             resetResolvedTextDirection();
24870             // Set the new text direction
24871             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
24872             // Do resolution
24873             resolveTextDirection();
24874             // Notify change
24875             onRtlPropertiesChanged(getLayoutDirection());
24876             // Refresh
24877             requestLayout();
24878             invalidate(true);
24879         }
24880     }
24881 
24882     /**
24883      * Return the resolved text direction.
24884      *
24885      * @return the resolved text direction. Returns one of:
24886      *
24887      * {@link #TEXT_DIRECTION_FIRST_STRONG},
24888      * {@link #TEXT_DIRECTION_ANY_RTL},
24889      * {@link #TEXT_DIRECTION_LTR},
24890      * {@link #TEXT_DIRECTION_RTL},
24891      * {@link #TEXT_DIRECTION_LOCALE},
24892      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
24893      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
24894      *
24895      * @attr ref android.R.styleable#View_textDirection
24896      */
24897     @ViewDebug.ExportedProperty(category = "text", mapping = {
24898             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
24899             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
24900             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
24901             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
24902             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
24903             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
24904             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
24905             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
24906     })
getTextDirection()24907     public int getTextDirection() {
24908         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
24909     }
24910 
24911     /**
24912      * Resolve the text direction.
24913      *
24914      * @return true if resolution has been done, false otherwise.
24915      *
24916      * @hide
24917      */
resolveTextDirection()24918     public boolean resolveTextDirection() {
24919         // Reset any previous text direction resolution
24920         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
24921 
24922         if (hasRtlSupport()) {
24923             // Set resolved text direction flag depending on text direction flag
24924             final int textDirection = getRawTextDirection();
24925             switch(textDirection) {
24926                 case TEXT_DIRECTION_INHERIT:
24927                     if (!canResolveTextDirection()) {
24928                         // We cannot do the resolution if there is no parent, so use the default one
24929                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
24930                         // Resolution will need to happen again later
24931                         return false;
24932                     }
24933 
24934                     // Parent has not yet resolved, so we still return the default
24935                     try {
24936                         if (!mParent.isTextDirectionResolved()) {
24937                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
24938                             // Resolution will need to happen again later
24939                             return false;
24940                         }
24941                     } catch (AbstractMethodError e) {
24942                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24943                                 " does not fully implement ViewParent", e);
24944                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
24945                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
24946                         return true;
24947                     }
24948 
24949                     // Set current resolved direction to the same value as the parent's one
24950                     int parentResolvedDirection;
24951                     try {
24952                         parentResolvedDirection = mParent.getTextDirection();
24953                     } catch (AbstractMethodError e) {
24954                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24955                                 " does not fully implement ViewParent", e);
24956                         parentResolvedDirection = TEXT_DIRECTION_LTR;
24957                     }
24958                     switch (parentResolvedDirection) {
24959                         case TEXT_DIRECTION_FIRST_STRONG:
24960                         case TEXT_DIRECTION_ANY_RTL:
24961                         case TEXT_DIRECTION_LTR:
24962                         case TEXT_DIRECTION_RTL:
24963                         case TEXT_DIRECTION_LOCALE:
24964                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
24965                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
24966                             mPrivateFlags2 |=
24967                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
24968                             break;
24969                         default:
24970                             // Default resolved direction is "first strong" heuristic
24971                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
24972                     }
24973                     break;
24974                 case TEXT_DIRECTION_FIRST_STRONG:
24975                 case TEXT_DIRECTION_ANY_RTL:
24976                 case TEXT_DIRECTION_LTR:
24977                 case TEXT_DIRECTION_RTL:
24978                 case TEXT_DIRECTION_LOCALE:
24979                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
24980                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
24981                     // Resolved direction is the same as text direction
24982                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
24983                     break;
24984                 default:
24985                     // Default resolved direction is "first strong" heuristic
24986                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
24987             }
24988         } else {
24989             // Default resolved direction is "first strong" heuristic
24990             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
24991         }
24992 
24993         // Set to resolved
24994         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
24995         return true;
24996     }
24997 
24998     /**
24999      * Check if text direction resolution can be done.
25000      *
25001      * @return true if text direction resolution can be done otherwise return false.
25002      */
canResolveTextDirection()25003     public boolean canResolveTextDirection() {
25004         switch (getRawTextDirection()) {
25005             case TEXT_DIRECTION_INHERIT:
25006                 if (mParent != null) {
25007                     try {
25008                         return mParent.canResolveTextDirection();
25009                     } catch (AbstractMethodError e) {
25010                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
25011                                 " does not fully implement ViewParent", e);
25012                     }
25013                 }
25014                 return false;
25015 
25016             default:
25017                 return true;
25018         }
25019     }
25020 
25021     /**
25022      * Reset resolved text direction. Text direction will be resolved during a call to
25023      * {@link #onMeasure(int, int)}.
25024      *
25025      * @hide
25026      */
resetResolvedTextDirection()25027     public void resetResolvedTextDirection() {
25028         // Reset any previous text direction resolution
25029         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
25030         // Set to default value
25031         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
25032     }
25033 
25034     /**
25035      * @return true if text direction is inherited.
25036      *
25037      * @hide
25038      */
isTextDirectionInherited()25039     public boolean isTextDirectionInherited() {
25040         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
25041     }
25042 
25043     /**
25044      * @return true if text direction is resolved.
25045      */
isTextDirectionResolved()25046     public boolean isTextDirectionResolved() {
25047         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
25048     }
25049 
25050     /**
25051      * Return the value specifying the text alignment or policy that was set with
25052      * {@link #setTextAlignment(int)}.
25053      *
25054      * @return the defined text alignment. It can be one of:
25055      *
25056      * {@link #TEXT_ALIGNMENT_INHERIT},
25057      * {@link #TEXT_ALIGNMENT_GRAVITY},
25058      * {@link #TEXT_ALIGNMENT_CENTER},
25059      * {@link #TEXT_ALIGNMENT_TEXT_START},
25060      * {@link #TEXT_ALIGNMENT_TEXT_END},
25061      * {@link #TEXT_ALIGNMENT_VIEW_START},
25062      * {@link #TEXT_ALIGNMENT_VIEW_END}
25063      *
25064      * @attr ref android.R.styleable#View_textAlignment
25065      *
25066      * @hide
25067      */
25068     @ViewDebug.ExportedProperty(category = "text", mapping = {
25069             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
25070             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
25071             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
25072             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
25073             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
25074             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
25075             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
25076     })
25077     @TextAlignment
getRawTextAlignment()25078     public int getRawTextAlignment() {
25079         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
25080     }
25081 
25082     /**
25083      * Set the text alignment.
25084      *
25085      * @param textAlignment The text alignment to set. Should be one of
25086      *
25087      * {@link #TEXT_ALIGNMENT_INHERIT},
25088      * {@link #TEXT_ALIGNMENT_GRAVITY},
25089      * {@link #TEXT_ALIGNMENT_CENTER},
25090      * {@link #TEXT_ALIGNMENT_TEXT_START},
25091      * {@link #TEXT_ALIGNMENT_TEXT_END},
25092      * {@link #TEXT_ALIGNMENT_VIEW_START},
25093      * {@link #TEXT_ALIGNMENT_VIEW_END}
25094      *
25095      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
25096      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
25097      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
25098      *
25099      * @attr ref android.R.styleable#View_textAlignment
25100      */
setTextAlignment(@extAlignment int textAlignment)25101     public void setTextAlignment(@TextAlignment int textAlignment) {
25102         if (textAlignment != getRawTextAlignment()) {
25103             // Reset the current and resolved text alignment
25104             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
25105             resetResolvedTextAlignment();
25106             // Set the new text alignment
25107             mPrivateFlags2 |=
25108                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
25109             // Do resolution
25110             resolveTextAlignment();
25111             // Notify change
25112             onRtlPropertiesChanged(getLayoutDirection());
25113             // Refresh
25114             requestLayout();
25115             invalidate(true);
25116         }
25117     }
25118 
25119     /**
25120      * Return the resolved text alignment.
25121      *
25122      * @return the resolved text alignment. Returns one of:
25123      *
25124      * {@link #TEXT_ALIGNMENT_GRAVITY},
25125      * {@link #TEXT_ALIGNMENT_CENTER},
25126      * {@link #TEXT_ALIGNMENT_TEXT_START},
25127      * {@link #TEXT_ALIGNMENT_TEXT_END},
25128      * {@link #TEXT_ALIGNMENT_VIEW_START},
25129      * {@link #TEXT_ALIGNMENT_VIEW_END}
25130      *
25131      * @attr ref android.R.styleable#View_textAlignment
25132      */
25133     @ViewDebug.ExportedProperty(category = "text", mapping = {
25134             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
25135             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
25136             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
25137             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
25138             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
25139             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
25140             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
25141     })
25142     @TextAlignment
getTextAlignment()25143     public int getTextAlignment() {
25144         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
25145                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
25146     }
25147 
25148     /**
25149      * Resolve the text alignment.
25150      *
25151      * @return true if resolution has been done, false otherwise.
25152      *
25153      * @hide
25154      */
resolveTextAlignment()25155     public boolean resolveTextAlignment() {
25156         // Reset any previous text alignment resolution
25157         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
25158 
25159         if (hasRtlSupport()) {
25160             // Set resolved text alignment flag depending on text alignment flag
25161             final int textAlignment = getRawTextAlignment();
25162             switch (textAlignment) {
25163                 case TEXT_ALIGNMENT_INHERIT:
25164                     // Check if we can resolve the text alignment
25165                     if (!canResolveTextAlignment()) {
25166                         // We cannot do the resolution if there is no parent so use the default
25167                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
25168                         // Resolution will need to happen again later
25169                         return false;
25170                     }
25171 
25172                     // Parent has not yet resolved, so we still return the default
25173                     try {
25174                         if (!mParent.isTextAlignmentResolved()) {
25175                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
25176                             // Resolution will need to happen again later
25177                             return false;
25178                         }
25179                     } catch (AbstractMethodError e) {
25180                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
25181                                 " does not fully implement ViewParent", e);
25182                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
25183                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
25184                         return true;
25185                     }
25186 
25187                     int parentResolvedTextAlignment;
25188                     try {
25189                         parentResolvedTextAlignment = mParent.getTextAlignment();
25190                     } catch (AbstractMethodError e) {
25191                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
25192                                 " does not fully implement ViewParent", e);
25193                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
25194                     }
25195                     switch (parentResolvedTextAlignment) {
25196                         case TEXT_ALIGNMENT_GRAVITY:
25197                         case TEXT_ALIGNMENT_TEXT_START:
25198                         case TEXT_ALIGNMENT_TEXT_END:
25199                         case TEXT_ALIGNMENT_CENTER:
25200                         case TEXT_ALIGNMENT_VIEW_START:
25201                         case TEXT_ALIGNMENT_VIEW_END:
25202                             // Resolved text alignment is the same as the parent resolved
25203                             // text alignment
25204                             mPrivateFlags2 |=
25205                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
25206                             break;
25207                         default:
25208                             // Use default resolved text alignment
25209                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
25210                     }
25211                     break;
25212                 case TEXT_ALIGNMENT_GRAVITY:
25213                 case TEXT_ALIGNMENT_TEXT_START:
25214                 case TEXT_ALIGNMENT_TEXT_END:
25215                 case TEXT_ALIGNMENT_CENTER:
25216                 case TEXT_ALIGNMENT_VIEW_START:
25217                 case TEXT_ALIGNMENT_VIEW_END:
25218                     // Resolved text alignment is the same as text alignment
25219                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
25220                     break;
25221                 default:
25222                     // Use default resolved text alignment
25223                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
25224             }
25225         } else {
25226             // Use default resolved text alignment
25227             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
25228         }
25229 
25230         // Set the resolved
25231         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
25232         return true;
25233     }
25234 
25235     /**
25236      * Check if text alignment resolution can be done.
25237      *
25238      * @return true if text alignment resolution can be done otherwise return false.
25239      */
canResolveTextAlignment()25240     public boolean canResolveTextAlignment() {
25241         switch (getRawTextAlignment()) {
25242             case TEXT_DIRECTION_INHERIT:
25243                 if (mParent != null) {
25244                     try {
25245                         return mParent.canResolveTextAlignment();
25246                     } catch (AbstractMethodError e) {
25247                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
25248                                 " does not fully implement ViewParent", e);
25249                     }
25250                 }
25251                 return false;
25252 
25253             default:
25254                 return true;
25255         }
25256     }
25257 
25258     /**
25259      * Reset resolved text alignment. Text alignment will be resolved during a call to
25260      * {@link #onMeasure(int, int)}.
25261      *
25262      * @hide
25263      */
resetResolvedTextAlignment()25264     public void resetResolvedTextAlignment() {
25265         // Reset any previous text alignment resolution
25266         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
25267         // Set to default
25268         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
25269     }
25270 
25271     /**
25272      * @return true if text alignment is inherited.
25273      *
25274      * @hide
25275      */
isTextAlignmentInherited()25276     public boolean isTextAlignmentInherited() {
25277         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
25278     }
25279 
25280     /**
25281      * @return true if text alignment is resolved.
25282      */
isTextAlignmentResolved()25283     public boolean isTextAlignmentResolved() {
25284         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
25285     }
25286 
25287     /**
25288      * Generate a value suitable for use in {@link #setId(int)}.
25289      * This value will not collide with ID values generated at build time by aapt for R.id.
25290      *
25291      * @return a generated ID value
25292      */
generateViewId()25293     public static int generateViewId() {
25294         for (;;) {
25295             final int result = sNextGeneratedId.get();
25296             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
25297             int newValue = result + 1;
25298             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
25299             if (sNextGeneratedId.compareAndSet(result, newValue)) {
25300                 return result;
25301             }
25302         }
25303     }
25304 
isViewIdGenerated(int id)25305     private static boolean isViewIdGenerated(int id) {
25306         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
25307     }
25308 
25309     /**
25310      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
25311      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
25312      *                           a normal View or a ViewGroup with
25313      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
25314      * @hide
25315      */
captureTransitioningViews(List<View> transitioningViews)25316     public void captureTransitioningViews(List<View> transitioningViews) {
25317         if (getVisibility() == View.VISIBLE) {
25318             transitioningViews.add(this);
25319         }
25320     }
25321 
25322     /**
25323      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
25324      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
25325      * @hide
25326      */
findNamedViews(Map<String, View> namedElements)25327     public void findNamedViews(Map<String, View> namedElements) {
25328         if (getVisibility() == VISIBLE || mGhostView != null) {
25329             String transitionName = getTransitionName();
25330             if (transitionName != null) {
25331                 namedElements.put(transitionName, this);
25332             }
25333         }
25334     }
25335 
25336     /**
25337      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
25338      * The default implementation does not care the location or event types, but some subclasses
25339      * may use it (such as WebViews).
25340      * @param event The MotionEvent from a mouse
25341      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
25342      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
25343      * @see PointerIcon
25344      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)25345     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
25346         final float x = event.getX(pointerIndex);
25347         final float y = event.getY(pointerIndex);
25348         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
25349             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
25350         }
25351         return mPointerIcon;
25352     }
25353 
25354     /**
25355      * Set the pointer icon for the current view.
25356      * Passing {@code null} will restore the pointer icon to its default value.
25357      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
25358      */
setPointerIcon(PointerIcon pointerIcon)25359     public void setPointerIcon(PointerIcon pointerIcon) {
25360         mPointerIcon = pointerIcon;
25361         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
25362             return;
25363         }
25364         try {
25365             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
25366         } catch (RemoteException e) {
25367         }
25368     }
25369 
25370     /**
25371      * Gets the pointer icon for the current view.
25372      */
getPointerIcon()25373     public PointerIcon getPointerIcon() {
25374         return mPointerIcon;
25375     }
25376 
25377     /**
25378      * Checks pointer capture status.
25379      *
25380      * @return true if the view has pointer capture.
25381      * @see #requestPointerCapture()
25382      * @see #hasPointerCapture()
25383      */
hasPointerCapture()25384     public boolean hasPointerCapture() {
25385         final ViewRootImpl viewRootImpl = getViewRootImpl();
25386         if (viewRootImpl == null) {
25387             return false;
25388         }
25389         return viewRootImpl.hasPointerCapture();
25390     }
25391 
25392     /**
25393      * Requests pointer capture mode.
25394      * <p>
25395      * When the window has pointer capture, the mouse pointer icon will disappear and will not
25396      * change its position. Further mouse will be dispatched with the source
25397      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
25398      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
25399      * (touchscreens, or stylus) will not be affected.
25400      * <p>
25401      * If the window already has pointer capture, this call does nothing.
25402      * <p>
25403      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
25404      * automatically when the window loses focus.
25405      *
25406      * @see #releasePointerCapture()
25407      * @see #hasPointerCapture()
25408      */
requestPointerCapture()25409     public void requestPointerCapture() {
25410         final ViewRootImpl viewRootImpl = getViewRootImpl();
25411         if (viewRootImpl != null) {
25412             viewRootImpl.requestPointerCapture(true);
25413         }
25414     }
25415 
25416 
25417     /**
25418      * Releases the pointer capture.
25419      * <p>
25420      * If the window does not have pointer capture, this call will do nothing.
25421      * @see #requestPointerCapture()
25422      * @see #hasPointerCapture()
25423      */
releasePointerCapture()25424     public void releasePointerCapture() {
25425         final ViewRootImpl viewRootImpl = getViewRootImpl();
25426         if (viewRootImpl != null) {
25427             viewRootImpl.requestPointerCapture(false);
25428         }
25429     }
25430 
25431     /**
25432      * Called when the window has just acquired or lost pointer capture.
25433      *
25434      * @param hasCapture True if the view now has pointerCapture, false otherwise.
25435      */
25436     @CallSuper
onPointerCaptureChange(boolean hasCapture)25437     public void onPointerCaptureChange(boolean hasCapture) {
25438     }
25439 
25440     /**
25441      * @see #onPointerCaptureChange
25442      */
dispatchPointerCaptureChanged(boolean hasCapture)25443     public void dispatchPointerCaptureChanged(boolean hasCapture) {
25444         onPointerCaptureChange(hasCapture);
25445     }
25446 
25447     /**
25448      * Implement this method to handle captured pointer events
25449      *
25450      * @param event The captured pointer event.
25451      * @return True if the event was handled, false otherwise.
25452      * @see #requestPointerCapture()
25453      */
onCapturedPointerEvent(MotionEvent event)25454     public boolean onCapturedPointerEvent(MotionEvent event) {
25455         return false;
25456     }
25457 
25458     /**
25459      * Interface definition for a callback to be invoked when a captured pointer event
25460      * is being dispatched this view. The callback will be invoked before the event is
25461      * given to the view.
25462      */
25463     public interface OnCapturedPointerListener {
25464         /**
25465          * Called when a captured pointer event is dispatched to a view.
25466          * @param view The view this event has been dispatched to.
25467          * @param event The captured event.
25468          * @return True if the listener has consumed the event, false otherwise.
25469          */
onCapturedPointer(View view, MotionEvent event)25470         boolean onCapturedPointer(View view, MotionEvent event);
25471     }
25472 
25473     /**
25474      * Set a listener to receive callbacks when the pointer capture state of a view changes.
25475      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
25476      */
setOnCapturedPointerListener(OnCapturedPointerListener l)25477     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
25478         getListenerInfo().mOnCapturedPointerListener = l;
25479     }
25480 
25481     // Properties
25482     //
25483     /**
25484      * A Property wrapper around the <code>alpha</code> functionality handled by the
25485      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
25486      */
25487     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
25488         @Override
25489         public void setValue(View object, float value) {
25490             object.setAlpha(value);
25491         }
25492 
25493         @Override
25494         public Float get(View object) {
25495             return object.getAlpha();
25496         }
25497     };
25498 
25499     /**
25500      * A Property wrapper around the <code>translationX</code> functionality handled by the
25501      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
25502      */
25503     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
25504         @Override
25505         public void setValue(View object, float value) {
25506             object.setTranslationX(value);
25507         }
25508 
25509                 @Override
25510         public Float get(View object) {
25511             return object.getTranslationX();
25512         }
25513     };
25514 
25515     /**
25516      * A Property wrapper around the <code>translationY</code> functionality handled by the
25517      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
25518      */
25519     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
25520         @Override
25521         public void setValue(View object, float value) {
25522             object.setTranslationY(value);
25523         }
25524 
25525         @Override
25526         public Float get(View object) {
25527             return object.getTranslationY();
25528         }
25529     };
25530 
25531     /**
25532      * A Property wrapper around the <code>translationZ</code> functionality handled by the
25533      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
25534      */
25535     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
25536         @Override
25537         public void setValue(View object, float value) {
25538             object.setTranslationZ(value);
25539         }
25540 
25541         @Override
25542         public Float get(View object) {
25543             return object.getTranslationZ();
25544         }
25545     };
25546 
25547     /**
25548      * A Property wrapper around the <code>x</code> functionality handled by the
25549      * {@link View#setX(float)} and {@link View#getX()} methods.
25550      */
25551     public static final Property<View, Float> X = new FloatProperty<View>("x") {
25552         @Override
25553         public void setValue(View object, float value) {
25554             object.setX(value);
25555         }
25556 
25557         @Override
25558         public Float get(View object) {
25559             return object.getX();
25560         }
25561     };
25562 
25563     /**
25564      * A Property wrapper around the <code>y</code> functionality handled by the
25565      * {@link View#setY(float)} and {@link View#getY()} methods.
25566      */
25567     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
25568         @Override
25569         public void setValue(View object, float value) {
25570             object.setY(value);
25571         }
25572 
25573         @Override
25574         public Float get(View object) {
25575             return object.getY();
25576         }
25577     };
25578 
25579     /**
25580      * A Property wrapper around the <code>z</code> functionality handled by the
25581      * {@link View#setZ(float)} and {@link View#getZ()} methods.
25582      */
25583     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
25584         @Override
25585         public void setValue(View object, float value) {
25586             object.setZ(value);
25587         }
25588 
25589         @Override
25590         public Float get(View object) {
25591             return object.getZ();
25592         }
25593     };
25594 
25595     /**
25596      * A Property wrapper around the <code>rotation</code> functionality handled by the
25597      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
25598      */
25599     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
25600         @Override
25601         public void setValue(View object, float value) {
25602             object.setRotation(value);
25603         }
25604 
25605         @Override
25606         public Float get(View object) {
25607             return object.getRotation();
25608         }
25609     };
25610 
25611     /**
25612      * A Property wrapper around the <code>rotationX</code> functionality handled by the
25613      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
25614      */
25615     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
25616         @Override
25617         public void setValue(View object, float value) {
25618             object.setRotationX(value);
25619         }
25620 
25621         @Override
25622         public Float get(View object) {
25623             return object.getRotationX();
25624         }
25625     };
25626 
25627     /**
25628      * A Property wrapper around the <code>rotationY</code> functionality handled by the
25629      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
25630      */
25631     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
25632         @Override
25633         public void setValue(View object, float value) {
25634             object.setRotationY(value);
25635         }
25636 
25637         @Override
25638         public Float get(View object) {
25639             return object.getRotationY();
25640         }
25641     };
25642 
25643     /**
25644      * A Property wrapper around the <code>scaleX</code> functionality handled by the
25645      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
25646      */
25647     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
25648         @Override
25649         public void setValue(View object, float value) {
25650             object.setScaleX(value);
25651         }
25652 
25653         @Override
25654         public Float get(View object) {
25655             return object.getScaleX();
25656         }
25657     };
25658 
25659     /**
25660      * A Property wrapper around the <code>scaleY</code> functionality handled by the
25661      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
25662      */
25663     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
25664         @Override
25665         public void setValue(View object, float value) {
25666             object.setScaleY(value);
25667         }
25668 
25669         @Override
25670         public Float get(View object) {
25671             return object.getScaleY();
25672         }
25673     };
25674 
25675     /**
25676      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
25677      * Each MeasureSpec represents a requirement for either the width or the height.
25678      * A MeasureSpec is comprised of a size and a mode. There are three possible
25679      * modes:
25680      * <dl>
25681      * <dt>UNSPECIFIED</dt>
25682      * <dd>
25683      * The parent has not imposed any constraint on the child. It can be whatever size
25684      * it wants.
25685      * </dd>
25686      *
25687      * <dt>EXACTLY</dt>
25688      * <dd>
25689      * The parent has determined an exact size for the child. The child is going to be
25690      * given those bounds regardless of how big it wants to be.
25691      * </dd>
25692      *
25693      * <dt>AT_MOST</dt>
25694      * <dd>
25695      * The child can be as large as it wants up to the specified size.
25696      * </dd>
25697      * </dl>
25698      *
25699      * MeasureSpecs are implemented as ints to reduce object allocation. This class
25700      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
25701      */
25702     public static class MeasureSpec {
25703         private static final int MODE_SHIFT = 30;
25704         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
25705 
25706         /** @hide */
25707         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
25708         @Retention(RetentionPolicy.SOURCE)
25709         public @interface MeasureSpecMode {}
25710 
25711         /**
25712          * Measure specification mode: The parent has not imposed any constraint
25713          * on the child. It can be whatever size it wants.
25714          */
25715         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
25716 
25717         /**
25718          * Measure specification mode: The parent has determined an exact size
25719          * for the child. The child is going to be given those bounds regardless
25720          * of how big it wants to be.
25721          */
25722         public static final int EXACTLY     = 1 << MODE_SHIFT;
25723 
25724         /**
25725          * Measure specification mode: The child can be as large as it wants up
25726          * to the specified size.
25727          */
25728         public static final int AT_MOST     = 2 << MODE_SHIFT;
25729 
25730         /**
25731          * Creates a measure specification based on the supplied size and mode.
25732          *
25733          * The mode must always be one of the following:
25734          * <ul>
25735          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
25736          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
25737          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
25738          * </ul>
25739          *
25740          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
25741          * implementation was such that the order of arguments did not matter
25742          * and overflow in either value could impact the resulting MeasureSpec.
25743          * {@link android.widget.RelativeLayout} was affected by this bug.
25744          * Apps targeting API levels greater than 17 will get the fixed, more strict
25745          * behavior.</p>
25746          *
25747          * @param size the size of the measure specification
25748          * @param mode the mode of the measure specification
25749          * @return the measure specification based on size and mode
25750          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)25751         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
25752                                           @MeasureSpecMode int mode) {
25753             if (sUseBrokenMakeMeasureSpec) {
25754                 return size + mode;
25755             } else {
25756                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
25757             }
25758         }
25759 
25760         /**
25761          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
25762          * will automatically get a size of 0. Older apps expect this.
25763          *
25764          * @hide internal use only for compatibility with system widgets and older apps
25765          */
makeSafeMeasureSpec(int size, int mode)25766         public static int makeSafeMeasureSpec(int size, int mode) {
25767             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
25768                 return 0;
25769             }
25770             return makeMeasureSpec(size, mode);
25771         }
25772 
25773         /**
25774          * Extracts the mode from the supplied measure specification.
25775          *
25776          * @param measureSpec the measure specification to extract the mode from
25777          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
25778          *         {@link android.view.View.MeasureSpec#AT_MOST} or
25779          *         {@link android.view.View.MeasureSpec#EXACTLY}
25780          */
25781         @MeasureSpecMode
getMode(int measureSpec)25782         public static int getMode(int measureSpec) {
25783             //noinspection ResourceType
25784             return (measureSpec & MODE_MASK);
25785         }
25786 
25787         /**
25788          * Extracts the size from the supplied measure specification.
25789          *
25790          * @param measureSpec the measure specification to extract the size from
25791          * @return the size in pixels defined in the supplied measure specification
25792          */
getSize(int measureSpec)25793         public static int getSize(int measureSpec) {
25794             return (measureSpec & ~MODE_MASK);
25795         }
25796 
adjust(int measureSpec, int delta)25797         static int adjust(int measureSpec, int delta) {
25798             final int mode = getMode(measureSpec);
25799             int size = getSize(measureSpec);
25800             if (mode == UNSPECIFIED) {
25801                 // No need to adjust size for UNSPECIFIED mode.
25802                 return makeMeasureSpec(size, UNSPECIFIED);
25803             }
25804             size += delta;
25805             if (size < 0) {
25806                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
25807                         ") spec: " + toString(measureSpec) + " delta: " + delta);
25808                 size = 0;
25809             }
25810             return makeMeasureSpec(size, mode);
25811         }
25812 
25813         /**
25814          * Returns a String representation of the specified measure
25815          * specification.
25816          *
25817          * @param measureSpec the measure specification to convert to a String
25818          * @return a String with the following format: "MeasureSpec: MODE SIZE"
25819          */
toString(int measureSpec)25820         public static String toString(int measureSpec) {
25821             int mode = getMode(measureSpec);
25822             int size = getSize(measureSpec);
25823 
25824             StringBuilder sb = new StringBuilder("MeasureSpec: ");
25825 
25826             if (mode == UNSPECIFIED)
25827                 sb.append("UNSPECIFIED ");
25828             else if (mode == EXACTLY)
25829                 sb.append("EXACTLY ");
25830             else if (mode == AT_MOST)
25831                 sb.append("AT_MOST ");
25832             else
25833                 sb.append(mode).append(" ");
25834 
25835             sb.append(size);
25836             return sb.toString();
25837         }
25838     }
25839 
25840     private final class CheckForLongPress implements Runnable {
25841         private int mOriginalWindowAttachCount;
25842         private float mX;
25843         private float mY;
25844         private boolean mOriginalPressedState;
25845 
25846         @Override
run()25847         public void run() {
25848             if ((mOriginalPressedState == isPressed()) && (mParent != null)
25849                     && mOriginalWindowAttachCount == mWindowAttachCount) {
25850                 if (performLongClick(mX, mY)) {
25851                     mHasPerformedLongPress = true;
25852                 }
25853             }
25854         }
25855 
setAnchor(float x, float y)25856         public void setAnchor(float x, float y) {
25857             mX = x;
25858             mY = y;
25859         }
25860 
rememberWindowAttachCount()25861         public void rememberWindowAttachCount() {
25862             mOriginalWindowAttachCount = mWindowAttachCount;
25863         }
25864 
rememberPressedState()25865         public void rememberPressedState() {
25866             mOriginalPressedState = isPressed();
25867         }
25868     }
25869 
25870     private final class CheckForTap implements Runnable {
25871         public float x;
25872         public float y;
25873 
25874         @Override
run()25875         public void run() {
25876             mPrivateFlags &= ~PFLAG_PREPRESSED;
25877             setPressed(true, x, y);
25878             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
25879         }
25880     }
25881 
25882     private final class PerformClick implements Runnable {
25883         @Override
run()25884         public void run() {
25885             performClickInternal();
25886         }
25887     }
25888 
25889     /**
25890      * This method returns a ViewPropertyAnimator object, which can be used to animate
25891      * specific properties on this View.
25892      *
25893      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
25894      */
animate()25895     public ViewPropertyAnimator animate() {
25896         if (mAnimator == null) {
25897             mAnimator = new ViewPropertyAnimator(this);
25898         }
25899         return mAnimator;
25900     }
25901 
25902     /**
25903      * Sets the name of the View to be used to identify Views in Transitions.
25904      * Names should be unique in the View hierarchy.
25905      *
25906      * @param transitionName The name of the View to uniquely identify it for Transitions.
25907      */
setTransitionName(String transitionName)25908     public final void setTransitionName(String transitionName) {
25909         mTransitionName = transitionName;
25910     }
25911 
25912     /**
25913      * Returns the name of the View to be used to identify Views in Transitions.
25914      * Names should be unique in the View hierarchy.
25915      *
25916      * <p>This returns null if the View has not been given a name.</p>
25917      *
25918      * @return The name used of the View to be used to identify Views in Transitions or null
25919      * if no name has been given.
25920      */
25921     @ViewDebug.ExportedProperty
getTransitionName()25922     public String getTransitionName() {
25923         return mTransitionName;
25924     }
25925 
25926     /**
25927      * @hide
25928      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)25929     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
25930         // Do nothing.
25931     }
25932 
25933     /**
25934      * Interface definition for a callback to be invoked when a hardware key event is
25935      * dispatched to this view. The callback will be invoked before the key event is
25936      * given to the view. This is only useful for hardware keyboards; a software input
25937      * method has no obligation to trigger this listener.
25938      */
25939     public interface OnKeyListener {
25940         /**
25941          * Called when a hardware key is dispatched to a view. This allows listeners to
25942          * get a chance to respond before the target view.
25943          * <p>Key presses in software keyboards will generally NOT trigger this method,
25944          * although some may elect to do so in some situations. Do not assume a
25945          * software input method has to be key-based; even if it is, it may use key presses
25946          * in a different way than you expect, so there is no way to reliably catch soft
25947          * input key presses.
25948          *
25949          * @param v The view the key has been dispatched to.
25950          * @param keyCode The code for the physical key that was pressed
25951          * @param event The KeyEvent object containing full information about
25952          *        the event.
25953          * @return True if the listener has consumed the event, false otherwise.
25954          */
onKey(View v, int keyCode, KeyEvent event)25955         boolean onKey(View v, int keyCode, KeyEvent event);
25956     }
25957 
25958     /**
25959      * Interface definition for a callback to be invoked when a hardware key event hasn't
25960      * been handled by the view hierarchy.
25961      */
25962     public interface OnUnhandledKeyEventListener {
25963         /**
25964          * Called when a hardware key is dispatched to a view after being unhandled during normal
25965          * {@link KeyEvent} dispatch.
25966          *
25967          * @param v The view the key has been dispatched to.
25968          * @param event The KeyEvent object containing information about the event.
25969          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
25970          */
onUnhandledKeyEvent(View v, KeyEvent event)25971         boolean onUnhandledKeyEvent(View v, KeyEvent event);
25972     }
25973 
25974     /**
25975      * Interface definition for a callback to be invoked when a touch event is
25976      * dispatched to this view. The callback will be invoked before the touch
25977      * event is given to the view.
25978      */
25979     public interface OnTouchListener {
25980         /**
25981          * Called when a touch event is dispatched to a view. This allows listeners to
25982          * get a chance to respond before the target view.
25983          *
25984          * @param v The view the touch event has been dispatched to.
25985          * @param event The MotionEvent object containing full information about
25986          *        the event.
25987          * @return True if the listener has consumed the event, false otherwise.
25988          */
onTouch(View v, MotionEvent event)25989         boolean onTouch(View v, MotionEvent event);
25990     }
25991 
25992     /**
25993      * Interface definition for a callback to be invoked when a hover event is
25994      * dispatched to this view. The callback will be invoked before the hover
25995      * event is given to the view.
25996      */
25997     public interface OnHoverListener {
25998         /**
25999          * Called when a hover event is dispatched to a view. This allows listeners to
26000          * get a chance to respond before the target view.
26001          *
26002          * @param v The view the hover event has been dispatched to.
26003          * @param event The MotionEvent object containing full information about
26004          *        the event.
26005          * @return True if the listener has consumed the event, false otherwise.
26006          */
onHover(View v, MotionEvent event)26007         boolean onHover(View v, MotionEvent event);
26008     }
26009 
26010     /**
26011      * Interface definition for a callback to be invoked when a generic motion event is
26012      * dispatched to this view. The callback will be invoked before the generic motion
26013      * event is given to the view.
26014      */
26015     public interface OnGenericMotionListener {
26016         /**
26017          * Called when a generic motion event is dispatched to a view. This allows listeners to
26018          * get a chance to respond before the target view.
26019          *
26020          * @param v The view the generic motion event has been dispatched to.
26021          * @param event The MotionEvent object containing full information about
26022          *        the event.
26023          * @return True if the listener has consumed the event, false otherwise.
26024          */
onGenericMotion(View v, MotionEvent event)26025         boolean onGenericMotion(View v, MotionEvent event);
26026     }
26027 
26028     /**
26029      * Interface definition for a callback to be invoked when a view has been clicked and held.
26030      */
26031     public interface OnLongClickListener {
26032         /**
26033          * Called when a view has been clicked and held.
26034          *
26035          * @param v The view that was clicked and held.
26036          *
26037          * @return true if the callback consumed the long click, false otherwise.
26038          */
onLongClick(View v)26039         boolean onLongClick(View v);
26040     }
26041 
26042     /**
26043      * Interface definition for a callback to be invoked when a drag is being dispatched
26044      * to this view.  The callback will be invoked before the hosting view's own
26045      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
26046      * onDrag(event) behavior, it should return 'false' from this callback.
26047      *
26048      * <div class="special reference">
26049      * <h3>Developer Guides</h3>
26050      * <p>For a guide to implementing drag and drop features, read the
26051      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
26052      * </div>
26053      */
26054     public interface OnDragListener {
26055         /**
26056          * Called when a drag event is dispatched to a view. This allows listeners
26057          * to get a chance to override base View behavior.
26058          *
26059          * @param v The View that received the drag event.
26060          * @param event The {@link android.view.DragEvent} object for the drag event.
26061          * @return {@code true} if the drag event was handled successfully, or {@code false}
26062          * if the drag event was not handled. Note that {@code false} will trigger the View
26063          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
26064          */
onDrag(View v, DragEvent event)26065         boolean onDrag(View v, DragEvent event);
26066     }
26067 
26068     /**
26069      * Interface definition for a callback to be invoked when the focus state of
26070      * a view changed.
26071      */
26072     public interface OnFocusChangeListener {
26073         /**
26074          * Called when the focus state of a view has changed.
26075          *
26076          * @param v The view whose state has changed.
26077          * @param hasFocus The new focus state of v.
26078          */
onFocusChange(View v, boolean hasFocus)26079         void onFocusChange(View v, boolean hasFocus);
26080     }
26081 
26082     /**
26083      * Interface definition for a callback to be invoked when a view is clicked.
26084      */
26085     public interface OnClickListener {
26086         /**
26087          * Called when a view has been clicked.
26088          *
26089          * @param v The view that was clicked.
26090          */
onClick(View v)26091         void onClick(View v);
26092     }
26093 
26094     /**
26095      * Interface definition for a callback to be invoked when a view is context clicked.
26096      */
26097     public interface OnContextClickListener {
26098         /**
26099          * Called when a view is context clicked.
26100          *
26101          * @param v The view that has been context clicked.
26102          * @return true if the callback consumed the context click, false otherwise.
26103          */
onContextClick(View v)26104         boolean onContextClick(View v);
26105     }
26106 
26107     /**
26108      * Interface definition for a callback to be invoked when the context menu
26109      * for this view is being built.
26110      */
26111     public interface OnCreateContextMenuListener {
26112         /**
26113          * Called when the context menu for this view is being built. It is not
26114          * safe to hold onto the menu after this method returns.
26115          *
26116          * @param menu The context menu that is being built
26117          * @param v The view for which the context menu is being built
26118          * @param menuInfo Extra information about the item for which the
26119          *            context menu should be shown. This information will vary
26120          *            depending on the class of v.
26121          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)26122         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
26123     }
26124 
26125     /**
26126      * Interface definition for a callback to be invoked when the status bar changes
26127      * visibility.  This reports <strong>global</strong> changes to the system UI
26128      * state, not what the application is requesting.
26129      *
26130      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
26131      */
26132     public interface OnSystemUiVisibilityChangeListener {
26133         /**
26134          * Called when the status bar changes visibility because of a call to
26135          * {@link View#setSystemUiVisibility(int)}.
26136          *
26137          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
26138          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
26139          * This tells you the <strong>global</strong> state of these UI visibility
26140          * flags, not what your app is currently applying.
26141          */
onSystemUiVisibilityChange(int visibility)26142         public void onSystemUiVisibilityChange(int visibility);
26143     }
26144 
26145     /**
26146      * Interface definition for a callback to be invoked when this view is attached
26147      * or detached from its window.
26148      */
26149     public interface OnAttachStateChangeListener {
26150         /**
26151          * Called when the view is attached to a window.
26152          * @param v The view that was attached
26153          */
onViewAttachedToWindow(View v)26154         public void onViewAttachedToWindow(View v);
26155         /**
26156          * Called when the view is detached from a window.
26157          * @param v The view that was detached
26158          */
onViewDetachedFromWindow(View v)26159         public void onViewDetachedFromWindow(View v);
26160     }
26161 
26162     /**
26163      * Listener for applying window insets on a view in a custom way.
26164      *
26165      * <p>Apps may choose to implement this interface if they want to apply custom policy
26166      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
26167      * is set, its
26168      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
26169      * method will be called instead of the View's own
26170      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
26171      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
26172      * the View's normal behavior as part of its own.</p>
26173      */
26174     public interface OnApplyWindowInsetsListener {
26175         /**
26176          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
26177          * on a View, this listener method will be called instead of the view's own
26178          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
26179          *
26180          * @param v The view applying window insets
26181          * @param insets The insets to apply
26182          * @return The insets supplied, minus any insets that were consumed
26183          */
onApplyWindowInsets(View v, WindowInsets insets)26184         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
26185     }
26186 
26187     private final class UnsetPressedState implements Runnable {
26188         @Override
run()26189         public void run() {
26190             setPressed(false);
26191         }
26192     }
26193 
26194     /**
26195      * When a view becomes invisible checks if autofill considers the view invisible too. This
26196      * happens after the regular removal operation to make sure the operation is finished by the
26197      * time this is called.
26198      */
26199     private static class VisibilityChangeForAutofillHandler extends Handler {
26200         private final AutofillManager mAfm;
26201         private final View mView;
26202 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)26203         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
26204                 @NonNull View view) {
26205             mAfm = afm;
26206             mView = view;
26207         }
26208 
26209         @Override
handleMessage(Message msg)26210         public void handleMessage(Message msg) {
26211             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
26212         }
26213     }
26214 
26215     /**
26216      * Base class for derived classes that want to save and restore their own
26217      * state in {@link android.view.View#onSaveInstanceState()}.
26218      */
26219     public static class BaseSavedState extends AbsSavedState {
26220         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
26221         static final int IS_AUTOFILLED = 0b10;
26222         static final int AUTOFILL_ID = 0b100;
26223 
26224         // Flags that describe what data in this state is valid
26225         int mSavedData;
26226         String mStartActivityRequestWhoSaved;
26227         boolean mIsAutofilled;
26228         int mAutofillViewId;
26229 
26230         /**
26231          * Constructor used when reading from a parcel. Reads the state of the superclass.
26232          *
26233          * @param source parcel to read from
26234          */
BaseSavedState(Parcel source)26235         public BaseSavedState(Parcel source) {
26236             this(source, null);
26237         }
26238 
26239         /**
26240          * Constructor used when reading from a parcel using a given class loader.
26241          * Reads the state of the superclass.
26242          *
26243          * @param source parcel to read from
26244          * @param loader ClassLoader to use for reading
26245          */
BaseSavedState(Parcel source, ClassLoader loader)26246         public BaseSavedState(Parcel source, ClassLoader loader) {
26247             super(source, loader);
26248             mSavedData = source.readInt();
26249             mStartActivityRequestWhoSaved = source.readString();
26250             mIsAutofilled = source.readBoolean();
26251             mAutofillViewId = source.readInt();
26252         }
26253 
26254         /**
26255          * Constructor called by derived classes when creating their SavedState objects
26256          *
26257          * @param superState The state of the superclass of this view
26258          */
BaseSavedState(Parcelable superState)26259         public BaseSavedState(Parcelable superState) {
26260             super(superState);
26261         }
26262 
26263         @Override
writeToParcel(Parcel out, int flags)26264         public void writeToParcel(Parcel out, int flags) {
26265             super.writeToParcel(out, flags);
26266 
26267             out.writeInt(mSavedData);
26268             out.writeString(mStartActivityRequestWhoSaved);
26269             out.writeBoolean(mIsAutofilled);
26270             out.writeInt(mAutofillViewId);
26271         }
26272 
26273         public static final Parcelable.Creator<BaseSavedState> CREATOR
26274                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
26275             @Override
26276             public BaseSavedState createFromParcel(Parcel in) {
26277                 return new BaseSavedState(in);
26278             }
26279 
26280             @Override
26281             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
26282                 return new BaseSavedState(in, loader);
26283             }
26284 
26285             @Override
26286             public BaseSavedState[] newArray(int size) {
26287                 return new BaseSavedState[size];
26288             }
26289         };
26290     }
26291 
26292     /**
26293      * A set of information given to a view when it is attached to its parent
26294      * window.
26295      */
26296     final static class AttachInfo {
26297         interface Callbacks {
playSoundEffect(int effectId)26298             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)26299             boolean performHapticFeedback(int effectId, boolean always);
26300         }
26301 
26302         /**
26303          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
26304          * to a Handler. This class contains the target (View) to invalidate and
26305          * the coordinates of the dirty rectangle.
26306          *
26307          * For performance purposes, this class also implements a pool of up to
26308          * POOL_LIMIT objects that get reused. This reduces memory allocations
26309          * whenever possible.
26310          */
26311         static class InvalidateInfo {
26312             private static final int POOL_LIMIT = 10;
26313 
26314             private static final SynchronizedPool<InvalidateInfo> sPool =
26315                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
26316 
26317             View target;
26318 
26319             int left;
26320             int top;
26321             int right;
26322             int bottom;
26323 
obtain()26324             public static InvalidateInfo obtain() {
26325                 InvalidateInfo instance = sPool.acquire();
26326                 return (instance != null) ? instance : new InvalidateInfo();
26327             }
26328 
recycle()26329             public void recycle() {
26330                 target = null;
26331                 sPool.release(this);
26332             }
26333         }
26334 
26335         final IWindowSession mSession;
26336 
26337         final IWindow mWindow;
26338 
26339         final IBinder mWindowToken;
26340 
26341         Display mDisplay;
26342 
26343         final Callbacks mRootCallbacks;
26344 
26345         IWindowId mIWindowId;
26346         WindowId mWindowId;
26347 
26348         /**
26349          * The top view of the hierarchy.
26350          */
26351         View mRootView;
26352 
26353         IBinder mPanelParentWindowToken;
26354 
26355         boolean mHardwareAccelerated;
26356         boolean mHardwareAccelerationRequested;
26357         ThreadedRenderer mThreadedRenderer;
26358         List<RenderNode> mPendingAnimatingRenderNodes;
26359 
26360         /**
26361          * The state of the display to which the window is attached, as reported
26362          * by {@link Display#getState()}.  Note that the display state constants
26363          * declared by {@link Display} do not exactly line up with the screen state
26364          * constants declared by {@link View} (there are more display states than
26365          * screen states).
26366          */
26367         int mDisplayState = Display.STATE_UNKNOWN;
26368 
26369         /**
26370          * Scale factor used by the compatibility mode
26371          */
26372         float mApplicationScale;
26373 
26374         /**
26375          * Indicates whether the application is in compatibility mode
26376          */
26377         boolean mScalingRequired;
26378 
26379         /**
26380          * Left position of this view's window
26381          */
26382         int mWindowLeft;
26383 
26384         /**
26385          * Top position of this view's window
26386          */
26387         int mWindowTop;
26388 
26389         /**
26390          * Indicates whether views need to use 32-bit drawing caches
26391          */
26392         boolean mUse32BitDrawingCache;
26393 
26394         /**
26395          * For windows that are full-screen but using insets to layout inside
26396          * of the screen areas, these are the current insets to appear inside
26397          * the overscan area of the display.
26398          */
26399         final Rect mOverscanInsets = new Rect();
26400 
26401         /**
26402          * For windows that are full-screen but using insets to layout inside
26403          * of the screen decorations, these are the current insets for the
26404          * content of the window.
26405          */
26406         final Rect mContentInsets = new Rect();
26407 
26408         /**
26409          * For windows that are full-screen but using insets to layout inside
26410          * of the screen decorations, these are the current insets for the
26411          * actual visible parts of the window.
26412          */
26413         final Rect mVisibleInsets = new Rect();
26414 
26415         /**
26416          * For windows that are full-screen but using insets to layout inside
26417          * of the screen decorations, these are the current insets for the
26418          * stable system windows.
26419          */
26420         final Rect mStableInsets = new Rect();
26421 
26422         final DisplayCutout.ParcelableWrapper mDisplayCutout =
26423                 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
26424 
26425         /**
26426          * For windows that include areas that are not covered by real surface these are the outsets
26427          * for real surface.
26428          */
26429         final Rect mOutsets = new Rect();
26430 
26431         /**
26432          * In multi-window we force show the navigation bar. Because we don't want that the surface
26433          * size changes in this mode, we instead have a flag whether the navigation bar size should
26434          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
26435          */
26436         boolean mAlwaysConsumeNavBar;
26437 
26438         /**
26439          * The internal insets given by this window.  This value is
26440          * supplied by the client (through
26441          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
26442          * be given to the window manager when changed to be used in laying
26443          * out windows behind it.
26444          */
26445         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
26446                 = new ViewTreeObserver.InternalInsetsInfo();
26447 
26448         /**
26449          * Set to true when mGivenInternalInsets is non-empty.
26450          */
26451         boolean mHasNonEmptyGivenInternalInsets;
26452 
26453         /**
26454          * All views in the window's hierarchy that serve as scroll containers,
26455          * used to determine if the window can be resized or must be panned
26456          * to adjust for a soft input area.
26457          */
26458         final ArrayList<View> mScrollContainers = new ArrayList<View>();
26459 
26460         final KeyEvent.DispatcherState mKeyDispatchState
26461                 = new KeyEvent.DispatcherState();
26462 
26463         /**
26464          * Indicates whether the view's window currently has the focus.
26465          */
26466         boolean mHasWindowFocus;
26467 
26468         /**
26469          * The current visibility of the window.
26470          */
26471         int mWindowVisibility;
26472 
26473         /**
26474          * Indicates the time at which drawing started to occur.
26475          */
26476         long mDrawingTime;
26477 
26478         /**
26479          * Indicates whether or not ignoring the DIRTY_MASK flags.
26480          */
26481         boolean mIgnoreDirtyState;
26482 
26483         /**
26484          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
26485          * to avoid clearing that flag prematurely.
26486          */
26487         boolean mSetIgnoreDirtyState = false;
26488 
26489         /**
26490          * Indicates whether the view's window is currently in touch mode.
26491          */
26492         boolean mInTouchMode;
26493 
26494         /**
26495          * Indicates whether the view has requested unbuffered input dispatching for the current
26496          * event stream.
26497          */
26498         boolean mUnbufferedDispatchRequested;
26499 
26500         /**
26501          * Indicates that ViewAncestor should trigger a global layout change
26502          * the next time it performs a traversal
26503          */
26504         boolean mRecomputeGlobalAttributes;
26505 
26506         /**
26507          * Always report new attributes at next traversal.
26508          */
26509         boolean mForceReportNewAttributes;
26510 
26511         /**
26512          * Set during a traveral if any views want to keep the screen on.
26513          */
26514         boolean mKeepScreenOn;
26515 
26516         /**
26517          * Set during a traveral if the light center needs to be updated.
26518          */
26519         boolean mNeedsUpdateLightCenter;
26520 
26521         /**
26522          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
26523          */
26524         int mSystemUiVisibility;
26525 
26526         /**
26527          * Hack to force certain system UI visibility flags to be cleared.
26528          */
26529         int mDisabledSystemUiVisibility;
26530 
26531         /**
26532          * Last global system UI visibility reported by the window manager.
26533          */
26534         int mGlobalSystemUiVisibility = -1;
26535 
26536         /**
26537          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
26538          * attached.
26539          */
26540         boolean mHasSystemUiListeners;
26541 
26542         /**
26543          * Set if the window has requested to extend into the overscan region
26544          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
26545          */
26546         boolean mOverscanRequested;
26547 
26548         /**
26549          * Set if the visibility of any views has changed.
26550          */
26551         boolean mViewVisibilityChanged;
26552 
26553         /**
26554          * Set to true if a view has been scrolled.
26555          */
26556         boolean mViewScrollChanged;
26557 
26558         /**
26559          * Set to true if a pointer event is currently being handled.
26560          */
26561         boolean mHandlingPointerEvent;
26562 
26563         /**
26564          * Global to the view hierarchy used as a temporary for dealing with
26565          * x/y points in the transparent region computations.
26566          */
26567         final int[] mTransparentLocation = new int[2];
26568 
26569         /**
26570          * Global to the view hierarchy used as a temporary for dealing with
26571          * x/y points in the ViewGroup.invalidateChild implementation.
26572          */
26573         final int[] mInvalidateChildLocation = new int[2];
26574 
26575         /**
26576          * Global to the view hierarchy used as a temporary for dealing with
26577          * computing absolute on-screen location.
26578          */
26579         final int[] mTmpLocation = new int[2];
26580 
26581         /**
26582          * Global to the view hierarchy used as a temporary for dealing with
26583          * x/y location when view is transformed.
26584          */
26585         final float[] mTmpTransformLocation = new float[2];
26586 
26587         /**
26588          * The view tree observer used to dispatch global events like
26589          * layout, pre-draw, touch mode change, etc.
26590          */
26591         final ViewTreeObserver mTreeObserver;
26592 
26593         /**
26594          * A Canvas used by the view hierarchy to perform bitmap caching.
26595          */
26596         Canvas mCanvas;
26597 
26598         /**
26599          * The view root impl.
26600          */
26601         final ViewRootImpl mViewRootImpl;
26602 
26603         /**
26604          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
26605          * handler can be used to pump events in the UI events queue.
26606          */
26607         final Handler mHandler;
26608 
26609         /**
26610          * Temporary for use in computing invalidate rectangles while
26611          * calling up the hierarchy.
26612          */
26613         final Rect mTmpInvalRect = new Rect();
26614 
26615         /**
26616          * Temporary for use in computing hit areas with transformed views
26617          */
26618         final RectF mTmpTransformRect = new RectF();
26619 
26620         /**
26621          * Temporary for use in computing hit areas with transformed views
26622          */
26623         final RectF mTmpTransformRect1 = new RectF();
26624 
26625         /**
26626          * Temporary list of rectanges.
26627          */
26628         final List<RectF> mTmpRectList = new ArrayList<>();
26629 
26630         /**
26631          * Temporary for use in transforming invalidation rect
26632          */
26633         final Matrix mTmpMatrix = new Matrix();
26634 
26635         /**
26636          * Temporary for use in transforming invalidation rect
26637          */
26638         final Transformation mTmpTransformation = new Transformation();
26639 
26640         /**
26641          * Temporary for use in querying outlines from OutlineProviders
26642          */
26643         final Outline mTmpOutline = new Outline();
26644 
26645         /**
26646          * Temporary list for use in collecting focusable descendents of a view.
26647          */
26648         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
26649 
26650         /**
26651          * The id of the window for accessibility purposes.
26652          */
26653         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
26654 
26655         /**
26656          * Flags related to accessibility processing.
26657          *
26658          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
26659          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
26660          */
26661         int mAccessibilityFetchFlags;
26662 
26663         /**
26664          * The drawable for highlighting accessibility focus.
26665          */
26666         Drawable mAccessibilityFocusDrawable;
26667 
26668         /**
26669          * The drawable for highlighting autofilled views.
26670          *
26671          * @see #isAutofilled()
26672          */
26673         Drawable mAutofilledDrawable;
26674 
26675         /**
26676          * Show where the margins, bounds and layout bounds are for each view.
26677          */
26678         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
26679 
26680         /**
26681          * Point used to compute visible regions.
26682          */
26683         final Point mPoint = new Point();
26684 
26685         /**
26686          * Used to track which View originated a requestLayout() call, used when
26687          * requestLayout() is called during layout.
26688          */
26689         View mViewRequestingLayout;
26690 
26691         /**
26692          * Used to track views that need (at least) a partial relayout at their current size
26693          * during the next traversal.
26694          */
26695         List<View> mPartialLayoutViews = new ArrayList<>();
26696 
26697         /**
26698          * Swapped with mPartialLayoutViews during layout to avoid concurrent
26699          * modification. Lazily assigned during ViewRootImpl layout.
26700          */
26701         List<View> mEmptyPartialLayoutViews;
26702 
26703         /**
26704          * Used to track the identity of the current drag operation.
26705          */
26706         IBinder mDragToken;
26707 
26708         /**
26709          * The drag shadow surface for the current drag operation.
26710          */
26711         public Surface mDragSurface;
26712 
26713 
26714         /**
26715          * The view that currently has a tooltip displayed.
26716          */
26717         View mTooltipHost;
26718 
26719         /**
26720          * Creates a new set of attachment information with the specified
26721          * events handler and thread.
26722          *
26723          * @param handler the events handler the view must use
26724          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)26725         AttachInfo(IWindowSession session, IWindow window, Display display,
26726                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
26727                 Context context) {
26728             mSession = session;
26729             mWindow = window;
26730             mWindowToken = window.asBinder();
26731             mDisplay = display;
26732             mViewRootImpl = viewRootImpl;
26733             mHandler = handler;
26734             mRootCallbacks = effectPlayer;
26735             mTreeObserver = new ViewTreeObserver(context);
26736         }
26737     }
26738 
26739     /**
26740      * <p>ScrollabilityCache holds various fields used by a View when scrolling
26741      * is supported. This avoids keeping too many unused fields in most
26742      * instances of View.</p>
26743      */
26744     private static class ScrollabilityCache implements Runnable {
26745 
26746         /**
26747          * Scrollbars are not visible
26748          */
26749         public static final int OFF = 0;
26750 
26751         /**
26752          * Scrollbars are visible
26753          */
26754         public static final int ON = 1;
26755 
26756         /**
26757          * Scrollbars are fading away
26758          */
26759         public static final int FADING = 2;
26760 
26761         public boolean fadeScrollBars;
26762 
26763         public int fadingEdgeLength;
26764         public int scrollBarDefaultDelayBeforeFade;
26765         public int scrollBarFadeDuration;
26766 
26767         public int scrollBarSize;
26768         public int scrollBarMinTouchTarget;
26769         public ScrollBarDrawable scrollBar;
26770         public float[] interpolatorValues;
26771         public View host;
26772 
26773         public final Paint paint;
26774         public final Matrix matrix;
26775         public Shader shader;
26776 
26777         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
26778 
26779         private static final float[] OPAQUE = { 255 };
26780         private static final float[] TRANSPARENT = { 0.0f };
26781 
26782         /**
26783          * When fading should start. This time moves into the future every time
26784          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
26785          */
26786         public long fadeStartTime;
26787 
26788 
26789         /**
26790          * The current state of the scrollbars: ON, OFF, or FADING
26791          */
26792         public int state = OFF;
26793 
26794         private int mLastColor;
26795 
26796         public final Rect mScrollBarBounds = new Rect();
26797         public final Rect mScrollBarTouchBounds = new Rect();
26798 
26799         public static final int NOT_DRAGGING = 0;
26800         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
26801         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
26802         public int mScrollBarDraggingState = NOT_DRAGGING;
26803 
26804         public float mScrollBarDraggingPos = 0;
26805 
ScrollabilityCache(ViewConfiguration configuration, View host)26806         public ScrollabilityCache(ViewConfiguration configuration, View host) {
26807             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
26808             scrollBarSize = configuration.getScaledScrollBarSize();
26809             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
26810             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
26811             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
26812 
26813             paint = new Paint();
26814             matrix = new Matrix();
26815             // use use a height of 1, and then wack the matrix each time we
26816             // actually use it.
26817             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
26818             paint.setShader(shader);
26819             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
26820 
26821             this.host = host;
26822         }
26823 
setFadeColor(int color)26824         public void setFadeColor(int color) {
26825             if (color != mLastColor) {
26826                 mLastColor = color;
26827 
26828                 if (color != 0) {
26829                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
26830                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
26831                     paint.setShader(shader);
26832                     // Restore the default transfer mode (src_over)
26833                     paint.setXfermode(null);
26834                 } else {
26835                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
26836                     paint.setShader(shader);
26837                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
26838                 }
26839             }
26840         }
26841 
run()26842         public void run() {
26843             long now = AnimationUtils.currentAnimationTimeMillis();
26844             if (now >= fadeStartTime) {
26845 
26846                 // the animation fades the scrollbars out by changing
26847                 // the opacity (alpha) from fully opaque to fully
26848                 // transparent
26849                 int nextFrame = (int) now;
26850                 int framesCount = 0;
26851 
26852                 Interpolator interpolator = scrollBarInterpolator;
26853 
26854                 // Start opaque
26855                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
26856 
26857                 // End transparent
26858                 nextFrame += scrollBarFadeDuration;
26859                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
26860 
26861                 state = FADING;
26862 
26863                 // Kick off the fade animation
26864                 host.invalidate(true);
26865             }
26866         }
26867     }
26868 
26869     /**
26870      * Resuable callback for sending
26871      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
26872      */
26873     private class SendViewScrolledAccessibilityEvent implements Runnable {
26874         public volatile boolean mIsPending;
26875         public int mDeltaX;
26876         public int mDeltaY;
26877 
post(int dx, int dy)26878         public void post(int dx, int dy) {
26879             mDeltaX += dx;
26880             mDeltaY += dy;
26881             if (!mIsPending) {
26882                 mIsPending = true;
26883                 postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
26884             }
26885         }
26886 
26887         @Override
run()26888         public void run() {
26889             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
26890                 AccessibilityEvent event = AccessibilityEvent.obtain(
26891                         AccessibilityEvent.TYPE_VIEW_SCROLLED);
26892                 event.setScrollDeltaX(mDeltaX);
26893                 event.setScrollDeltaY(mDeltaY);
26894                 sendAccessibilityEventUnchecked(event);
26895             }
26896             reset();
26897         }
26898 
reset()26899         private void reset() {
26900             mIsPending = false;
26901             mDeltaX = 0;
26902             mDeltaY = 0;
26903         }
26904     }
26905 
26906     /**
26907      * Remove the pending callback for sending a
26908      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
26909      */
cancel(@ullable SendViewScrolledAccessibilityEvent callback)26910     private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
26911         if (callback == null || !callback.mIsPending) return;
26912         removeCallbacks(callback);
26913         callback.reset();
26914     }
26915 
26916     /**
26917      * <p>
26918      * This class represents a delegate that can be registered in a {@link View}
26919      * to enhance accessibility support via composition rather via inheritance.
26920      * It is specifically targeted to widget developers that extend basic View
26921      * classes i.e. classes in package android.view, that would like their
26922      * applications to be backwards compatible.
26923      * </p>
26924      * <div class="special reference">
26925      * <h3>Developer Guides</h3>
26926      * <p>For more information about making applications accessible, read the
26927      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
26928      * developer guide.</p>
26929      * </div>
26930      * <p>
26931      * A scenario in which a developer would like to use an accessibility delegate
26932      * is overriding a method introduced in a later API version than the minimal API
26933      * version supported by the application. For example, the method
26934      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
26935      * in API version 4 when the accessibility APIs were first introduced. If a
26936      * developer would like their application to run on API version 4 devices (assuming
26937      * all other APIs used by the application are version 4 or lower) and take advantage
26938      * of this method, instead of overriding the method which would break the application's
26939      * backwards compatibility, they can override the corresponding method in this
26940      * delegate and register the delegate in the target View if the API version of
26941      * the system is high enough, i.e. the API version is the same as or higher than the API
26942      * version that introduced
26943      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
26944      * </p>
26945      * <p>
26946      * Here is an example implementation:
26947      * </p>
26948      * <code><pre><p>
26949      * if (Build.VERSION.SDK_INT >= 14) {
26950      *     // If the API version is equal of higher than the version in
26951      *     // which onInitializeAccessibilityNodeInfo was introduced we
26952      *     // register a delegate with a customized implementation.
26953      *     View view = findViewById(R.id.view_id);
26954      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
26955      *         public void onInitializeAccessibilityNodeInfo(View host,
26956      *                 AccessibilityNodeInfo info) {
26957      *             // Let the default implementation populate the info.
26958      *             super.onInitializeAccessibilityNodeInfo(host, info);
26959      *             // Set some other information.
26960      *             info.setEnabled(host.isEnabled());
26961      *         }
26962      *     });
26963      * }
26964      * </code></pre></p>
26965      * <p>
26966      * This delegate contains methods that correspond to the accessibility methods
26967      * in View. If a delegate has been specified the implementation in View hands
26968      * off handling to the corresponding method in this delegate. The default
26969      * implementation the delegate methods behaves exactly as the corresponding
26970      * method in View for the case of no accessibility delegate been set. Hence,
26971      * to customize the behavior of a View method, clients can override only the
26972      * corresponding delegate method without altering the behavior of the rest
26973      * accessibility related methods of the host view.
26974      * </p>
26975      * <p>
26976      * <strong>Note:</strong> On platform versions prior to
26977      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
26978      * views in the {@code android.widget.*} package are called <i>before</i>
26979      * host methods. This prevents certain properties such as class name from
26980      * being modified by overriding
26981      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
26982      * as any changes will be overwritten by the host class.
26983      * <p>
26984      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
26985      * methods are called <i>after</i> host methods, which all properties to be
26986      * modified without being overwritten by the host class.
26987      */
26988     public static class AccessibilityDelegate {
26989 
26990         /**
26991          * Sends an accessibility event of the given type. If accessibility is not
26992          * enabled this method has no effect.
26993          * <p>
26994          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
26995          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
26996          * been set.
26997          * </p>
26998          *
26999          * @param host The View hosting the delegate.
27000          * @param eventType The type of the event to send.
27001          *
27002          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
27003          */
sendAccessibilityEvent(View host, int eventType)27004         public void sendAccessibilityEvent(View host, int eventType) {
27005             host.sendAccessibilityEventInternal(eventType);
27006         }
27007 
27008         /**
27009          * Performs the specified accessibility action on the view. For
27010          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
27011          * <p>
27012          * The default implementation behaves as
27013          * {@link View#performAccessibilityAction(int, Bundle)
27014          *  View#performAccessibilityAction(int, Bundle)} for the case of
27015          *  no accessibility delegate been set.
27016          * </p>
27017          *
27018          * @param action The action to perform.
27019          * @return Whether the action was performed.
27020          *
27021          * @see View#performAccessibilityAction(int, Bundle)
27022          *      View#performAccessibilityAction(int, Bundle)
27023          */
performAccessibilityAction(View host, int action, Bundle args)27024         public boolean performAccessibilityAction(View host, int action, Bundle args) {
27025             return host.performAccessibilityActionInternal(action, args);
27026         }
27027 
27028         /**
27029          * Sends an accessibility event. This method behaves exactly as
27030          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
27031          * empty {@link AccessibilityEvent} and does not perform a check whether
27032          * accessibility is enabled.
27033          * <p>
27034          * The default implementation behaves as
27035          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
27036          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
27037          * the case of no accessibility delegate been set.
27038          * </p>
27039          *
27040          * @param host The View hosting the delegate.
27041          * @param event The event to send.
27042          *
27043          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
27044          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
27045          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)27046         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
27047             host.sendAccessibilityEventUncheckedInternal(event);
27048         }
27049 
27050         /**
27051          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
27052          * to its children for adding their text content to the event.
27053          * <p>
27054          * The default implementation behaves as
27055          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
27056          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
27057          * the case of no accessibility delegate been set.
27058          * </p>
27059          *
27060          * @param host The View hosting the delegate.
27061          * @param event The event.
27062          * @return True if the event population was completed.
27063          *
27064          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
27065          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
27066          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)27067         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
27068             return host.dispatchPopulateAccessibilityEventInternal(event);
27069         }
27070 
27071         /**
27072          * Gives a chance to the host View to populate the accessibility event with its
27073          * text content.
27074          * <p>
27075          * The default implementation behaves as
27076          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
27077          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
27078          * the case of no accessibility delegate been set.
27079          * </p>
27080          *
27081          * @param host The View hosting the delegate.
27082          * @param event The accessibility event which to populate.
27083          *
27084          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
27085          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
27086          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)27087         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
27088             host.onPopulateAccessibilityEventInternal(event);
27089         }
27090 
27091         /**
27092          * Initializes an {@link AccessibilityEvent} with information about the
27093          * the host View which is the event source.
27094          * <p>
27095          * The default implementation behaves as
27096          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
27097          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
27098          * the case of no accessibility delegate been set.
27099          * </p>
27100          *
27101          * @param host The View hosting the delegate.
27102          * @param event The event to initialize.
27103          *
27104          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
27105          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
27106          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)27107         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
27108             host.onInitializeAccessibilityEventInternal(event);
27109         }
27110 
27111         /**
27112          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
27113          * <p>
27114          * The default implementation behaves as
27115          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
27116          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
27117          * the case of no accessibility delegate been set.
27118          * </p>
27119          *
27120          * @param host The View hosting the delegate.
27121          * @param info The instance to initialize.
27122          *
27123          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
27124          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
27125          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)27126         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
27127             host.onInitializeAccessibilityNodeInfoInternal(info);
27128         }
27129 
27130         /**
27131          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
27132          * additional data.
27133          * <p>
27134          * This method only needs to be implemented if the View offers to provide additional data.
27135          * </p>
27136          * <p>
27137          * The default implementation behaves as
27138          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
27139          * for the case where no accessibility delegate is set.
27140          * </p>
27141          *
27142          * @param host The View hosting the delegate. Never {@code null}.
27143          * @param info The info to which to add the extra data. Never {@code null}.
27144          * @param extraDataKey A key specifying the type of extra data to add to the info. The
27145          *                     extra data should be added to the {@link Bundle} returned by
27146          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
27147          *                     {@code null}.
27148          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
27149          *                  May be {@code null} if the if the service provided no arguments.
27150          *
27151          * @see AccessibilityNodeInfo#setExtraAvailableData
27152          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)27153         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
27154                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
27155                 @Nullable Bundle arguments) {
27156             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
27157         }
27158 
27159         /**
27160          * Called when a child of the host View has requested sending an
27161          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
27162          * to augment the event.
27163          * <p>
27164          * The default implementation behaves as
27165          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
27166          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
27167          * the case of no accessibility delegate been set.
27168          * </p>
27169          *
27170          * @param host The View hosting the delegate.
27171          * @param child The child which requests sending the event.
27172          * @param event The event to be sent.
27173          * @return True if the event should be sent
27174          *
27175          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
27176          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
27177          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)27178         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
27179                 AccessibilityEvent event) {
27180             return host.onRequestSendAccessibilityEventInternal(child, event);
27181         }
27182 
27183         /**
27184          * Gets the provider for managing a virtual view hierarchy rooted at this View
27185          * and reported to {@link android.accessibilityservice.AccessibilityService}s
27186          * that explore the window content.
27187          * <p>
27188          * The default implementation behaves as
27189          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
27190          * the case of no accessibility delegate been set.
27191          * </p>
27192          *
27193          * @return The provider.
27194          *
27195          * @see AccessibilityNodeProvider
27196          */
getAccessibilityNodeProvider(View host)27197         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
27198             return null;
27199         }
27200 
27201         /**
27202          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
27203          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
27204          * This method is responsible for obtaining an accessibility node info from a
27205          * pool of reusable instances and calling
27206          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
27207          * view to initialize the former.
27208          * <p>
27209          * <strong>Note:</strong> The client is responsible for recycling the obtained
27210          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
27211          * creation.
27212          * </p>
27213          * <p>
27214          * The default implementation behaves as
27215          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
27216          * the case of no accessibility delegate been set.
27217          * </p>
27218          * @return A populated {@link AccessibilityNodeInfo}.
27219          *
27220          * @see AccessibilityNodeInfo
27221          *
27222          * @hide
27223          */
createAccessibilityNodeInfo(View host)27224         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
27225             return host.createAccessibilityNodeInfoInternal();
27226         }
27227     }
27228 
27229     private static class MatchIdPredicate implements Predicate<View> {
27230         public int mId;
27231 
27232         @Override
test(View view)27233         public boolean test(View view) {
27234             return (view.mID == mId);
27235         }
27236     }
27237 
27238     private static class MatchLabelForPredicate implements Predicate<View> {
27239         private int mLabeledId;
27240 
27241         @Override
test(View view)27242         public boolean test(View view) {
27243             return (view.mLabelForId == mLabeledId);
27244         }
27245     }
27246 
27247     /**
27248      * Dump all private flags in readable format, useful for documentation and
27249      * sanity checking.
27250      */
dumpFlags()27251     private static void dumpFlags() {
27252         final HashMap<String, String> found = Maps.newHashMap();
27253         try {
27254             for (Field field : View.class.getDeclaredFields()) {
27255                 final int modifiers = field.getModifiers();
27256                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
27257                     if (field.getType().equals(int.class)) {
27258                         final int value = field.getInt(null);
27259                         dumpFlag(found, field.getName(), value);
27260                     } else if (field.getType().equals(int[].class)) {
27261                         final int[] values = (int[]) field.get(null);
27262                         for (int i = 0; i < values.length; i++) {
27263                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
27264                         }
27265                     }
27266                 }
27267             }
27268         } catch (IllegalAccessException e) {
27269             throw new RuntimeException(e);
27270         }
27271 
27272         final ArrayList<String> keys = Lists.newArrayList();
27273         keys.addAll(found.keySet());
27274         Collections.sort(keys);
27275         for (String key : keys) {
27276             Log.d(VIEW_LOG_TAG, found.get(key));
27277         }
27278     }
27279 
dumpFlag(HashMap<String, String> found, String name, int value)27280     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
27281         // Sort flags by prefix, then by bits, always keeping unique keys
27282         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
27283         final int prefix = name.indexOf('_');
27284         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
27285         final String output = bits + " " + name;
27286         found.put(key, output);
27287     }
27288 
27289     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)27290     public void encode(@NonNull ViewHierarchyEncoder stream) {
27291         stream.beginObject(this);
27292         encodeProperties(stream);
27293         stream.endObject();
27294     }
27295 
27296     /** {@hide} */
27297     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)27298     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
27299         Object resolveId = ViewDebug.resolveId(getContext(), mID);
27300         if (resolveId instanceof String) {
27301             stream.addProperty("id", (String) resolveId);
27302         } else {
27303             stream.addProperty("id", mID);
27304         }
27305 
27306         stream.addProperty("misc:transformation.alpha",
27307                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
27308         stream.addProperty("misc:transitionName", getTransitionName());
27309 
27310         // layout
27311         stream.addProperty("layout:left", mLeft);
27312         stream.addProperty("layout:right", mRight);
27313         stream.addProperty("layout:top", mTop);
27314         stream.addProperty("layout:bottom", mBottom);
27315         stream.addProperty("layout:width", getWidth());
27316         stream.addProperty("layout:height", getHeight());
27317         stream.addProperty("layout:layoutDirection", getLayoutDirection());
27318         stream.addProperty("layout:layoutRtl", isLayoutRtl());
27319         stream.addProperty("layout:hasTransientState", hasTransientState());
27320         stream.addProperty("layout:baseline", getBaseline());
27321 
27322         // layout params
27323         ViewGroup.LayoutParams layoutParams = getLayoutParams();
27324         if (layoutParams != null) {
27325             stream.addPropertyKey("layoutParams");
27326             layoutParams.encode(stream);
27327         }
27328 
27329         // scrolling
27330         stream.addProperty("scrolling:scrollX", mScrollX);
27331         stream.addProperty("scrolling:scrollY", mScrollY);
27332 
27333         // padding
27334         stream.addProperty("padding:paddingLeft", mPaddingLeft);
27335         stream.addProperty("padding:paddingRight", mPaddingRight);
27336         stream.addProperty("padding:paddingTop", mPaddingTop);
27337         stream.addProperty("padding:paddingBottom", mPaddingBottom);
27338         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
27339         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
27340         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
27341         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
27342         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
27343 
27344         // measurement
27345         stream.addProperty("measurement:minHeight", mMinHeight);
27346         stream.addProperty("measurement:minWidth", mMinWidth);
27347         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
27348         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
27349 
27350         // drawing
27351         stream.addProperty("drawing:elevation", getElevation());
27352         stream.addProperty("drawing:translationX", getTranslationX());
27353         stream.addProperty("drawing:translationY", getTranslationY());
27354         stream.addProperty("drawing:translationZ", getTranslationZ());
27355         stream.addProperty("drawing:rotation", getRotation());
27356         stream.addProperty("drawing:rotationX", getRotationX());
27357         stream.addProperty("drawing:rotationY", getRotationY());
27358         stream.addProperty("drawing:scaleX", getScaleX());
27359         stream.addProperty("drawing:scaleY", getScaleY());
27360         stream.addProperty("drawing:pivotX", getPivotX());
27361         stream.addProperty("drawing:pivotY", getPivotY());
27362         stream.addProperty("drawing:clipBounds",
27363                 mClipBounds == null ? null : mClipBounds.toString());
27364         stream.addProperty("drawing:opaque", isOpaque());
27365         stream.addProperty("drawing:alpha", getAlpha());
27366         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
27367         stream.addProperty("drawing:shadow", hasShadow());
27368         stream.addProperty("drawing:solidColor", getSolidColor());
27369         stream.addProperty("drawing:layerType", mLayerType);
27370         stream.addProperty("drawing:willNotDraw", willNotDraw());
27371         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
27372         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
27373         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
27374         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
27375         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
27376         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
27377 
27378         // focus
27379         stream.addProperty("focus:hasFocus", hasFocus());
27380         stream.addProperty("focus:isFocused", isFocused());
27381         stream.addProperty("focus:focusable", getFocusable());
27382         stream.addProperty("focus:isFocusable", isFocusable());
27383         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
27384 
27385         stream.addProperty("misc:clickable", isClickable());
27386         stream.addProperty("misc:pressed", isPressed());
27387         stream.addProperty("misc:selected", isSelected());
27388         stream.addProperty("misc:touchMode", isInTouchMode());
27389         stream.addProperty("misc:hovered", isHovered());
27390         stream.addProperty("misc:activated", isActivated());
27391 
27392         stream.addProperty("misc:visibility", getVisibility());
27393         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
27394         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
27395 
27396         stream.addProperty("misc:enabled", isEnabled());
27397         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
27398         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
27399 
27400         // theme attributes
27401         Resources.Theme theme = getContext().getTheme();
27402         if (theme != null) {
27403             stream.addPropertyKey("theme");
27404             theme.encode(stream);
27405         }
27406 
27407         // view attribute information
27408         int n = mAttributes != null ? mAttributes.length : 0;
27409         stream.addProperty("meta:__attrCount__", n/2);
27410         for (int i = 0; i < n; i += 2) {
27411             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
27412         }
27413 
27414         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
27415 
27416         // text
27417         stream.addProperty("text:textDirection", getTextDirection());
27418         stream.addProperty("text:textAlignment", getTextAlignment());
27419 
27420         // accessibility
27421         CharSequence contentDescription = getContentDescription();
27422         stream.addProperty("accessibility:contentDescription",
27423                 contentDescription == null ? "" : contentDescription.toString());
27424         stream.addProperty("accessibility:labelFor", getLabelFor());
27425         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
27426     }
27427 
27428     /**
27429      * Determine if this view is rendered on a round wearable device and is the main view
27430      * on the screen.
27431      */
shouldDrawRoundScrollbar()27432     boolean shouldDrawRoundScrollbar() {
27433         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
27434             return false;
27435         }
27436 
27437         final View rootView = getRootView();
27438         final WindowInsets insets = getRootWindowInsets();
27439 
27440         int height = getHeight();
27441         int width = getWidth();
27442         int displayHeight = rootView.getHeight();
27443         int displayWidth = rootView.getWidth();
27444 
27445         if (height != displayHeight || width != displayWidth) {
27446             return false;
27447         }
27448 
27449         getLocationInWindow(mAttachInfo.mTmpLocation);
27450         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
27451                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
27452     }
27453 
27454     /**
27455      * Sets the tooltip text which will be displayed in a small popup next to the view.
27456      * <p>
27457      * The tooltip will be displayed:
27458      * <ul>
27459      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
27460      * menu). </li>
27461      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
27462      * </ul>
27463      * <p>
27464      * <strong>Note:</strong> Do not override this method, as it will have no
27465      * effect on the text displayed in the tooltip.
27466      *
27467      * @param tooltipText the tooltip text, or null if no tooltip is required
27468      * @see #getTooltipText()
27469      * @attr ref android.R.styleable#View_tooltipText
27470      */
setTooltipText(@ullable CharSequence tooltipText)27471     public void setTooltipText(@Nullable CharSequence tooltipText) {
27472         if (TextUtils.isEmpty(tooltipText)) {
27473             setFlags(0, TOOLTIP);
27474             hideTooltip();
27475             mTooltipInfo = null;
27476         } else {
27477             setFlags(TOOLTIP, TOOLTIP);
27478             if (mTooltipInfo == null) {
27479                 mTooltipInfo = new TooltipInfo();
27480                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
27481                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
27482                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
27483                 mTooltipInfo.clearAnchorPos();
27484             }
27485             mTooltipInfo.mTooltipText = tooltipText;
27486         }
27487     }
27488 
27489     /**
27490      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
27491      */
setTooltip(@ullable CharSequence tooltipText)27492     public void setTooltip(@Nullable CharSequence tooltipText) {
27493         setTooltipText(tooltipText);
27494     }
27495 
27496     /**
27497      * Returns the view's tooltip text.
27498      *
27499      * <strong>Note:</strong> Do not override this method, as it will have no
27500      * effect on the text displayed in the tooltip. You must call
27501      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
27502      *
27503      * @return the tooltip text
27504      * @see #setTooltipText(CharSequence)
27505      * @attr ref android.R.styleable#View_tooltipText
27506      */
27507     @Nullable
getTooltipText()27508     public CharSequence getTooltipText() {
27509         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
27510     }
27511 
27512     /**
27513      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
27514      */
27515     @Nullable
getTooltip()27516     public CharSequence getTooltip() {
27517         return getTooltipText();
27518     }
27519 
showTooltip(int x, int y, boolean fromLongClick)27520     private boolean showTooltip(int x, int y, boolean fromLongClick) {
27521         if (mAttachInfo == null || mTooltipInfo == null) {
27522             return false;
27523         }
27524         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
27525             return false;
27526         }
27527         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
27528             return false;
27529         }
27530         hideTooltip();
27531         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
27532         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
27533         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
27534         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
27535         mAttachInfo.mTooltipHost = this;
27536         // The available accessibility actions have changed
27537         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
27538         return true;
27539     }
27540 
hideTooltip()27541     void hideTooltip() {
27542         if (mTooltipInfo == null) {
27543             return;
27544         }
27545         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
27546         if (mTooltipInfo.mTooltipPopup == null) {
27547             return;
27548         }
27549         mTooltipInfo.mTooltipPopup.hide();
27550         mTooltipInfo.mTooltipPopup = null;
27551         mTooltipInfo.mTooltipFromLongClick = false;
27552         mTooltipInfo.clearAnchorPos();
27553         if (mAttachInfo != null) {
27554             mAttachInfo.mTooltipHost = null;
27555         }
27556         // The available accessibility actions have changed
27557         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
27558     }
27559 
showLongClickTooltip(int x, int y)27560     private boolean showLongClickTooltip(int x, int y) {
27561         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
27562         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
27563         return showTooltip(x, y, true);
27564     }
27565 
showHoverTooltip()27566     private boolean showHoverTooltip() {
27567         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
27568     }
27569 
dispatchTooltipHoverEvent(MotionEvent event)27570     boolean dispatchTooltipHoverEvent(MotionEvent event) {
27571         if (mTooltipInfo == null) {
27572             return false;
27573         }
27574         switch(event.getAction()) {
27575             case MotionEvent.ACTION_HOVER_MOVE:
27576                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
27577                     break;
27578                 }
27579                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
27580                     if (mTooltipInfo.mTooltipPopup == null) {
27581                         // Schedule showing the tooltip after a timeout.
27582                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
27583                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
27584                                 ViewConfiguration.getHoverTooltipShowTimeout());
27585                     }
27586 
27587                     // Hide hover-triggered tooltip after a period of inactivity.
27588                     // Match the timeout used by NativeInputManager to hide the mouse pointer
27589                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
27590                     final int timeout;
27591                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
27592                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
27593                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
27594                     } else {
27595                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
27596                     }
27597                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
27598                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
27599                 }
27600                 return true;
27601 
27602             case MotionEvent.ACTION_HOVER_EXIT:
27603                 mTooltipInfo.clearAnchorPos();
27604                 if (!mTooltipInfo.mTooltipFromLongClick) {
27605                     hideTooltip();
27606                 }
27607                 break;
27608         }
27609         return false;
27610     }
27611 
handleTooltipKey(KeyEvent event)27612     void handleTooltipKey(KeyEvent event) {
27613         switch (event.getAction()) {
27614             case KeyEvent.ACTION_DOWN:
27615                 if (event.getRepeatCount() == 0) {
27616                     hideTooltip();
27617                 }
27618                 break;
27619 
27620             case KeyEvent.ACTION_UP:
27621                 handleTooltipUp();
27622                 break;
27623         }
27624     }
27625 
handleTooltipUp()27626     private void handleTooltipUp() {
27627         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
27628             return;
27629         }
27630         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
27631         postDelayed(mTooltipInfo.mHideTooltipRunnable,
27632                 ViewConfiguration.getLongPressTooltipHideTimeout());
27633     }
27634 
getFocusableAttribute(TypedArray attributes)27635     private int getFocusableAttribute(TypedArray attributes) {
27636         TypedValue val = new TypedValue();
27637         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
27638             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
27639                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
27640             } else {
27641                 return val.data;
27642             }
27643         } else {
27644             return FOCUSABLE_AUTO;
27645         }
27646     }
27647 
27648     /**
27649      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
27650      * is not showing.
27651      * @hide
27652      */
27653     @TestApi
getTooltipView()27654     public View getTooltipView() {
27655         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
27656             return null;
27657         }
27658         return mTooltipInfo.mTooltipPopup.getContentView();
27659     }
27660 
27661     /**
27662      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
27663      * @hide
27664      */
27665     @TestApi
isDefaultFocusHighlightEnabled()27666     public static boolean isDefaultFocusHighlightEnabled() {
27667         return sUseDefaultFocusHighlight;
27668     }
27669 
27670     /**
27671      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
27672      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
27673      * (visually on-top views first).
27674      *
27675      * @param evt the previously unhandled {@link KeyEvent}.
27676      * @return the {@link View} which consumed the event or {@code null} if not consumed.
27677      */
dispatchUnhandledKeyEvent(KeyEvent evt)27678     View dispatchUnhandledKeyEvent(KeyEvent evt) {
27679         if (onUnhandledKeyEvent(evt)) {
27680             return this;
27681         }
27682         return null;
27683     }
27684 
27685     /**
27686      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
27687      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
27688      * this will dispatch into all the listeners registered via
27689      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
27690      * order (most recently added will receive events first).
27691      *
27692      * @param event An unhandled event.
27693      * @return {@code true} if the event was handled, {@code false} otherwise.
27694      * @see #addOnUnhandledKeyEventListener
27695      */
onUnhandledKeyEvent(@onNull KeyEvent event)27696     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
27697         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
27698             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
27699                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
27700                     return true;
27701                 }
27702             }
27703         }
27704         return false;
27705     }
27706 
hasUnhandledKeyListener()27707     boolean hasUnhandledKeyListener() {
27708         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
27709                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
27710     }
27711 
27712     /**
27713      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
27714      * UI thread.
27715      *
27716      * @param listener a receiver of unhandled {@link KeyEvent}s.
27717      * @see #removeOnUnhandledKeyEventListener
27718      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)27719     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
27720         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
27721         if (listeners == null) {
27722             listeners = new ArrayList<>();
27723             getListenerInfo().mUnhandledKeyListeners = listeners;
27724         }
27725         listeners.add(listener);
27726         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
27727             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
27728         }
27729     }
27730 
27731     /**
27732      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
27733      * UI thread.
27734      *
27735      * @param listener a receiver of unhandled {@link KeyEvent}s.
27736      * @see #addOnUnhandledKeyEventListener
27737      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)27738     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
27739         if (mListenerInfo != null) {
27740             if (mListenerInfo.mUnhandledKeyListeners != null
27741                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
27742                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
27743                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
27744                     mListenerInfo.mUnhandledKeyListeners = null;
27745                     if (mParent instanceof ViewGroup) {
27746                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
27747                     }
27748                 }
27749             }
27750         }
27751     }
27752 }
27753