• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import static java.lang.Math.max;
20 
21 import android.animation.AnimatorInflater;
22 import android.animation.StateListAnimator;
23 import android.annotation.CallSuper;
24 import android.annotation.ColorInt;
25 import android.annotation.DrawableRes;
26 import android.annotation.FloatRange;
27 import android.annotation.IdRes;
28 import android.annotation.IntDef;
29 import android.annotation.IntRange;
30 import android.annotation.LayoutRes;
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.annotation.Size;
34 import android.annotation.TestApi;
35 import android.annotation.UiThread;
36 import android.content.ClipData;
37 import android.content.Context;
38 import android.content.ContextWrapper;
39 import android.content.Intent;
40 import android.content.res.ColorStateList;
41 import android.content.res.Configuration;
42 import android.content.res.Resources;
43 import android.content.res.TypedArray;
44 import android.graphics.Bitmap;
45 import android.graphics.Canvas;
46 import android.graphics.Color;
47 import android.graphics.Insets;
48 import android.graphics.Interpolator;
49 import android.graphics.LinearGradient;
50 import android.graphics.Matrix;
51 import android.graphics.Outline;
52 import android.graphics.Paint;
53 import android.graphics.PixelFormat;
54 import android.graphics.Point;
55 import android.graphics.PorterDuff;
56 import android.graphics.PorterDuffXfermode;
57 import android.graphics.Rect;
58 import android.graphics.RectF;
59 import android.graphics.Region;
60 import android.graphics.Shader;
61 import android.graphics.drawable.ColorDrawable;
62 import android.graphics.drawable.Drawable;
63 import android.hardware.display.DisplayManagerGlobal;
64 import android.net.Uri;
65 import android.os.Build;
66 import android.os.Bundle;
67 import android.os.Handler;
68 import android.os.IBinder;
69 import android.os.Message;
70 import android.os.Parcel;
71 import android.os.Parcelable;
72 import android.os.RemoteException;
73 import android.os.SystemClock;
74 import android.os.SystemProperties;
75 import android.os.Trace;
76 import android.text.TextUtils;
77 import android.util.AttributeSet;
78 import android.util.FloatProperty;
79 import android.util.LayoutDirection;
80 import android.util.Log;
81 import android.util.LongSparseLongArray;
82 import android.util.Pools.SynchronizedPool;
83 import android.util.Property;
84 import android.util.SparseArray;
85 import android.util.StateSet;
86 import android.util.SuperNotCalledException;
87 import android.util.TypedValue;
88 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
89 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
90 import android.view.AccessibilityIterators.TextSegmentIterator;
91 import android.view.AccessibilityIterators.WordTextSegmentIterator;
92 import android.view.ContextMenu.ContextMenuInfo;
93 import android.view.accessibility.AccessibilityEvent;
94 import android.view.accessibility.AccessibilityEventSource;
95 import android.view.accessibility.AccessibilityManager;
96 import android.view.accessibility.AccessibilityNodeInfo;
97 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
98 import android.view.accessibility.AccessibilityNodeProvider;
99 import android.view.accessibility.AccessibilityWindowInfo;
100 import android.view.animation.Animation;
101 import android.view.animation.AnimationUtils;
102 import android.view.animation.Transformation;
103 import android.view.autofill.AutofillId;
104 import android.view.autofill.AutofillManager;
105 import android.view.autofill.AutofillValue;
106 import android.view.inputmethod.EditorInfo;
107 import android.view.inputmethod.InputConnection;
108 import android.view.inputmethod.InputMethodManager;
109 import android.widget.Checkable;
110 import android.widget.FrameLayout;
111 import android.widget.ScrollBarDrawable;
112 
113 import com.android.internal.R;
114 import com.android.internal.view.TooltipPopup;
115 import com.android.internal.view.menu.MenuBuilder;
116 import com.android.internal.widget.ScrollBarUtils;
117 
118 import com.google.android.collect.Lists;
119 import com.google.android.collect.Maps;
120 
121 import java.lang.annotation.Retention;
122 import java.lang.annotation.RetentionPolicy;
123 import java.lang.ref.WeakReference;
124 import java.lang.reflect.Field;
125 import java.lang.reflect.InvocationTargetException;
126 import java.lang.reflect.Method;
127 import java.lang.reflect.Modifier;
128 import java.util.ArrayList;
129 import java.util.Arrays;
130 import java.util.Calendar;
131 import java.util.Collection;
132 import java.util.Collections;
133 import java.util.HashMap;
134 import java.util.List;
135 import java.util.Locale;
136 import java.util.Map;
137 import java.util.concurrent.CopyOnWriteArrayList;
138 import java.util.concurrent.atomic.AtomicInteger;
139 import java.util.function.Predicate;
140 
141 /**
142  * <p>
143  * This class represents the basic building block for user interface components. A View
144  * occupies a rectangular area on the screen and is responsible for drawing and
145  * event handling. View is the base class for <em>widgets</em>, which are
146  * used to create interactive UI components (buttons, text fields, etc.). The
147  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
148  * are invisible containers that hold other Views (or other ViewGroups) and define
149  * their layout properties.
150  * </p>
151  *
152  * <div class="special reference">
153  * <h3>Developer Guides</h3>
154  * <p>For information about using this class to develop your application's user interface,
155  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
156  * </div>
157  *
158  * <a name="Using"></a>
159  * <h3>Using Views</h3>
160  * <p>
161  * All of the views in a window are arranged in a single tree. You can add views
162  * either from code or by specifying a tree of views in one or more XML layout
163  * files. There are many specialized subclasses of views that act as controls or
164  * are capable of displaying text, images, or other content.
165  * </p>
166  * <p>
167  * Once you have created a tree of views, there are typically a few types of
168  * common operations you may wish to perform:
169  * <ul>
170  * <li><strong>Set properties:</strong> for example setting the text of a
171  * {@link android.widget.TextView}. The available properties and the methods
172  * that set them will vary among the different subclasses of views. Note that
173  * properties that are known at build time can be set in the XML layout
174  * files.</li>
175  * <li><strong>Set focus:</strong> The framework will handle moving focus in
176  * response to user input. To force focus to a specific view, call
177  * {@link #requestFocus}.</li>
178  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
179  * that will be notified when something interesting happens to the view. For
180  * example, all views will let you set a listener to be notified when the view
181  * gains or loses focus. You can register such a listener using
182  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
183  * Other view subclasses offer more specialized listeners. For example, a Button
184  * exposes a listener to notify clients when the button is clicked.</li>
185  * <li><strong>Set visibility:</strong> You can hide or show views using
186  * {@link #setVisibility(int)}.</li>
187  * </ul>
188  * </p>
189  * <p><em>
190  * Note: The Android framework is responsible for measuring, laying out and
191  * drawing views. You should not call methods that perform these actions on
192  * views yourself unless you are actually implementing a
193  * {@link android.view.ViewGroup}.
194  * </em></p>
195  *
196  * <a name="Lifecycle"></a>
197  * <h3>Implementing a Custom View</h3>
198  *
199  * <p>
200  * To implement a custom view, you will usually begin by providing overrides for
201  * some of the standard methods that the framework calls on all views. You do
202  * not need to override all of these methods. In fact, you can start by just
203  * overriding {@link #onDraw(android.graphics.Canvas)}.
204  * <table border="2" width="85%" align="center" cellpadding="5">
205  *     <thead>
206  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
207  *     </thead>
208  *
209  *     <tbody>
210  *     <tr>
211  *         <td rowspan="2">Creation</td>
212  *         <td>Constructors</td>
213  *         <td>There is a form of the constructor that are called when the view
214  *         is created from code and a form that is called when the view is
215  *         inflated from a layout file. The second form should parse and apply
216  *         any attributes defined in the layout file.
217  *         </td>
218  *     </tr>
219  *     <tr>
220  *         <td><code>{@link #onFinishInflate()}</code></td>
221  *         <td>Called after a view and all of its children has been inflated
222  *         from XML.</td>
223  *     </tr>
224  *
225  *     <tr>
226  *         <td rowspan="3">Layout</td>
227  *         <td><code>{@link #onMeasure(int, int)}</code></td>
228  *         <td>Called to determine the size requirements for this view and all
229  *         of its children.
230  *         </td>
231  *     </tr>
232  *     <tr>
233  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
234  *         <td>Called when this view should assign a size and position to all
235  *         of its children.
236  *         </td>
237  *     </tr>
238  *     <tr>
239  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
240  *         <td>Called when the size of this view has changed.
241  *         </td>
242  *     </tr>
243  *
244  *     <tr>
245  *         <td>Drawing</td>
246  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
247  *         <td>Called when the view should render its content.
248  *         </td>
249  *     </tr>
250  *
251  *     <tr>
252  *         <td rowspan="4">Event processing</td>
253  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
254  *         <td>Called when a new hardware key event occurs.
255  *         </td>
256  *     </tr>
257  *     <tr>
258  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
259  *         <td>Called when a hardware key up event occurs.
260  *         </td>
261  *     </tr>
262  *     <tr>
263  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
264  *         <td>Called when a trackball motion event occurs.
265  *         </td>
266  *     </tr>
267  *     <tr>
268  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
269  *         <td>Called when a touch screen motion event occurs.
270  *         </td>
271  *     </tr>
272  *
273  *     <tr>
274  *         <td rowspan="2">Focus</td>
275  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
276  *         <td>Called when the view gains or loses focus.
277  *         </td>
278  *     </tr>
279  *
280  *     <tr>
281  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
282  *         <td>Called when the window containing the view gains or loses focus.
283  *         </td>
284  *     </tr>
285  *
286  *     <tr>
287  *         <td rowspan="3">Attaching</td>
288  *         <td><code>{@link #onAttachedToWindow()}</code></td>
289  *         <td>Called when the view is attached to a window.
290  *         </td>
291  *     </tr>
292  *
293  *     <tr>
294  *         <td><code>{@link #onDetachedFromWindow}</code></td>
295  *         <td>Called when the view is detached from its window.
296  *         </td>
297  *     </tr>
298  *
299  *     <tr>
300  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
301  *         <td>Called when the visibility of the window containing the view
302  *         has changed.
303  *         </td>
304  *     </tr>
305  *     </tbody>
306  *
307  * </table>
308  * </p>
309  *
310  * <a name="IDs"></a>
311  * <h3>IDs</h3>
312  * Views may have an integer id associated with them. These ids are typically
313  * assigned in the layout XML files, and are used to find specific views within
314  * the view tree. A common pattern is to:
315  * <ul>
316  * <li>Define a Button in the layout file and assign it a unique ID.
317  * <pre>
318  * &lt;Button
319  *     android:id="@+id/my_button"
320  *     android:layout_width="wrap_content"
321  *     android:layout_height="wrap_content"
322  *     android:text="@string/my_button_text"/&gt;
323  * </pre></li>
324  * <li>From the onCreate method of an Activity, find the Button
325  * <pre class="prettyprint">
326  *      Button myButton = findViewById(R.id.my_button);
327  * </pre></li>
328  * </ul>
329  * <p>
330  * View IDs need not be unique throughout the tree, but it is good practice to
331  * ensure that they are at least unique within the part of the tree you are
332  * searching.
333  * </p>
334  *
335  * <a name="Position"></a>
336  * <h3>Position</h3>
337  * <p>
338  * The geometry of a view is that of a rectangle. A view has a location,
339  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
340  * two dimensions, expressed as a width and a height. The unit for location
341  * and dimensions is the pixel.
342  * </p>
343  *
344  * <p>
345  * It is possible to retrieve the location of a view by invoking the methods
346  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
347  * coordinate of the rectangle representing the view. The latter returns the
348  * top, or Y, coordinate of the rectangle representing the view. These methods
349  * both return the location of the view relative to its parent. For instance,
350  * when getLeft() returns 20, that means the view is located 20 pixels to the
351  * right of the left edge of its direct parent.
352  * </p>
353  *
354  * <p>
355  * In addition, several convenience methods are offered to avoid unnecessary
356  * computations, namely {@link #getRight()} and {@link #getBottom()}.
357  * These methods return the coordinates of the right and bottom edges of the
358  * rectangle representing the view. For instance, calling {@link #getRight()}
359  * is similar to the following computation: <code>getLeft() + getWidth()</code>
360  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
361  * </p>
362  *
363  * <a name="SizePaddingMargins"></a>
364  * <h3>Size, padding and margins</h3>
365  * <p>
366  * The size of a view is expressed with a width and a height. A view actually
367  * possess two pairs of width and height values.
368  * </p>
369  *
370  * <p>
371  * The first pair is known as <em>measured width</em> and
372  * <em>measured height</em>. These dimensions define how big a view wants to be
373  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
374  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
375  * and {@link #getMeasuredHeight()}.
376  * </p>
377  *
378  * <p>
379  * The second pair is simply known as <em>width</em> and <em>height</em>, or
380  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
381  * dimensions define the actual size of the view on screen, at drawing time and
382  * after layout. These values may, but do not have to, be different from the
383  * measured width and height. The width and height can be obtained by calling
384  * {@link #getWidth()} and {@link #getHeight()}.
385  * </p>
386  *
387  * <p>
388  * To measure its dimensions, a view takes into account its padding. The padding
389  * is expressed in pixels for the left, top, right and bottom parts of the view.
390  * Padding can be used to offset the content of the view by a specific amount of
391  * pixels. For instance, a left padding of 2 will push the view's content by
392  * 2 pixels to the right of the left edge. Padding can be set using the
393  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
394  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
395  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
396  * {@link #getPaddingEnd()}.
397  * </p>
398  *
399  * <p>
400  * Even though a view can define a padding, it does not provide any support for
401  * margins. However, view groups provide such a support. Refer to
402  * {@link android.view.ViewGroup} and
403  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
404  * </p>
405  *
406  * <a name="Layout"></a>
407  * <h3>Layout</h3>
408  * <p>
409  * Layout is a two pass process: a measure pass and a layout pass. The measuring
410  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
411  * of the view tree. Each view pushes dimension specifications down the tree
412  * during the recursion. At the end of the measure pass, every view has stored
413  * its measurements. The second pass happens in
414  * {@link #layout(int,int,int,int)} and is also top-down. During
415  * this pass each parent is responsible for positioning all of its children
416  * using the sizes computed in the measure pass.
417  * </p>
418  *
419  * <p>
420  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
421  * {@link #getMeasuredHeight()} values must be set, along with those for all of
422  * that view's descendants. A view's measured width and measured height values
423  * must respect the constraints imposed by the view's parents. This guarantees
424  * that at the end of the measure pass, all parents accept all of their
425  * children's measurements. A parent view may call measure() more than once on
426  * its children. For example, the parent may measure each child once with
427  * unspecified dimensions to find out how big they want to be, then call
428  * measure() on them again with actual numbers if the sum of all the children's
429  * unconstrained sizes is too big or too small.
430  * </p>
431  *
432  * <p>
433  * The measure pass uses two classes to communicate dimensions. The
434  * {@link MeasureSpec} class is used by views to tell their parents how they
435  * want to be measured and positioned. The base LayoutParams class just
436  * describes how big the view wants to be for both width and height. For each
437  * dimension, it can specify one of:
438  * <ul>
439  * <li> an exact number
440  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
441  * (minus padding)
442  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
443  * enclose its content (plus padding).
444  * </ul>
445  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
446  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
447  * an X and Y value.
448  * </p>
449  *
450  * <p>
451  * MeasureSpecs are used to push requirements down the tree from parent to
452  * child. A MeasureSpec can be in one of three modes:
453  * <ul>
454  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
455  * of a child view. For example, a LinearLayout may call measure() on its child
456  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
457  * tall the child view wants to be given a width of 240 pixels.
458  * <li>EXACTLY: This is used by the parent to impose an exact size on the
459  * child. The child must use this size, and guarantee that all of its
460  * descendants will fit within this size.
461  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
462  * child. The child must guarantee that it and all of its descendants will fit
463  * within this size.
464  * </ul>
465  * </p>
466  *
467  * <p>
468  * To initiate a layout, call {@link #requestLayout}. This method is typically
469  * called by a view on itself when it believes that is can no longer fit within
470  * its current bounds.
471  * </p>
472  *
473  * <a name="Drawing"></a>
474  * <h3>Drawing</h3>
475  * <p>
476  * Drawing is handled by walking the tree and recording the drawing commands of
477  * any View that needs to update. After this, the drawing commands of the
478  * entire tree are issued to screen, clipped to the newly damaged area.
479  * </p>
480  *
481  * <p>
482  * The tree is largely recorded and drawn in order, with parents drawn before
483  * (i.e., behind) their children, with siblings drawn in the order they appear
484  * in the tree. If you set a background drawable for a View, then the View will
485  * draw it before calling back to its <code>onDraw()</code> method. The child
486  * drawing order can be overridden with
487  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
488  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
489  * </p>
490  *
491  * <p>
492  * To force a view to draw, call {@link #invalidate()}.
493  * </p>
494  *
495  * <a name="EventHandlingThreading"></a>
496  * <h3>Event Handling and Threading</h3>
497  * <p>
498  * The basic cycle of a view is as follows:
499  * <ol>
500  * <li>An event comes in and is dispatched to the appropriate view. The view
501  * handles the event and notifies any listeners.</li>
502  * <li>If in the course of processing the event, the view's bounds may need
503  * to be changed, the view will call {@link #requestLayout()}.</li>
504  * <li>Similarly, if in the course of processing the event the view's appearance
505  * may need to be changed, the view will call {@link #invalidate()}.</li>
506  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
507  * the framework will take care of measuring, laying out, and drawing the tree
508  * as appropriate.</li>
509  * </ol>
510  * </p>
511  *
512  * <p><em>Note: The entire view tree is single threaded. You must always be on
513  * the UI thread when calling any method on any view.</em>
514  * If you are doing work on other threads and want to update the state of a view
515  * from that thread, you should use a {@link Handler}.
516  * </p>
517  *
518  * <a name="FocusHandling"></a>
519  * <h3>Focus Handling</h3>
520  * <p>
521  * The framework will handle routine focus movement in response to user input.
522  * This includes changing the focus as views are removed or hidden, or as new
523  * views become available. Views indicate their willingness to take focus
524  * through the {@link #isFocusable} method. To change whether a view can take
525  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
526  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
527  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
528  * </p>
529  * <p>
530  * Focus movement is based on an algorithm which finds the nearest neighbor in a
531  * given direction. In rare cases, the default algorithm may not match the
532  * intended behavior of the developer. In these situations, you can provide
533  * explicit overrides by using these XML attributes in the layout file:
534  * <pre>
535  * nextFocusDown
536  * nextFocusLeft
537  * nextFocusRight
538  * nextFocusUp
539  * </pre>
540  * </p>
541  *
542  *
543  * <p>
544  * To get a particular view to take focus, call {@link #requestFocus()}.
545  * </p>
546  *
547  * <a name="TouchMode"></a>
548  * <h3>Touch Mode</h3>
549  * <p>
550  * When a user is navigating a user interface via directional keys such as a D-pad, it is
551  * necessary to give focus to actionable items such as buttons so the user can see
552  * what will take input.  If the device has touch capabilities, however, and the user
553  * begins interacting with the interface by touching it, it is no longer necessary to
554  * always highlight, or give focus to, a particular view.  This motivates a mode
555  * for interaction named 'touch mode'.
556  * </p>
557  * <p>
558  * For a touch capable device, once the user touches the screen, the device
559  * will enter touch mode.  From this point onward, only views for which
560  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
561  * Other views that are touchable, like buttons, will not take focus when touched; they will
562  * only fire the on click listeners.
563  * </p>
564  * <p>
565  * Any time a user hits a directional key, such as a D-pad direction, the view device will
566  * exit touch mode, and find a view to take focus, so that the user may resume interacting
567  * with the user interface without touching the screen again.
568  * </p>
569  * <p>
570  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
571  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
572  * </p>
573  *
574  * <a name="Scrolling"></a>
575  * <h3>Scrolling</h3>
576  * <p>
577  * The framework provides basic support for views that wish to internally
578  * scroll their content. This includes keeping track of the X and Y scroll
579  * offset as well as mechanisms for drawing scrollbars. See
580  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
581  * {@link #awakenScrollBars()} for more details.
582  * </p>
583  *
584  * <a name="Tags"></a>
585  * <h3>Tags</h3>
586  * <p>
587  * Unlike IDs, tags are not used to identify views. Tags are essentially an
588  * extra piece of information that can be associated with a view. They are most
589  * often used as a convenience to store data related to views in the views
590  * themselves rather than by putting them in a separate structure.
591  * </p>
592  * <p>
593  * Tags may be specified with character sequence values in layout XML as either
594  * a single tag using the {@link android.R.styleable#View_tag android:tag}
595  * attribute or multiple tags using the {@code <tag>} child element:
596  * <pre>
597  *     &lt;View ...
598  *           android:tag="@string/mytag_value" /&gt;
599  *     &lt;View ...&gt;
600  *         &lt;tag android:id="@+id/mytag"
601  *              android:value="@string/mytag_value" /&gt;
602  *     &lt;/View>
603  * </pre>
604  * </p>
605  * <p>
606  * Tags may also be specified with arbitrary objects from code using
607  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
608  * </p>
609  *
610  * <a name="Themes"></a>
611  * <h3>Themes</h3>
612  * <p>
613  * By default, Views are created using the theme of the Context object supplied
614  * to their constructor; however, a different theme may be specified by using
615  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
616  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
617  * code.
618  * </p>
619  * <p>
620  * When the {@link android.R.styleable#View_theme android:theme} attribute is
621  * used in XML, the specified theme is applied on top of the inflation
622  * context's theme (see {@link LayoutInflater}) and used for the view itself as
623  * well as any child elements.
624  * </p>
625  * <p>
626  * In the following example, both views will be created using the Material dark
627  * color scheme; however, because an overlay theme is used which only defines a
628  * subset of attributes, the value of
629  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
630  * the inflation context's theme (e.g. the Activity theme) will be preserved.
631  * <pre>
632  *     &lt;LinearLayout
633  *             ...
634  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
635  *         &lt;View ...&gt;
636  *     &lt;/LinearLayout&gt;
637  * </pre>
638  * </p>
639  *
640  * <a name="Properties"></a>
641  * <h3>Properties</h3>
642  * <p>
643  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
644  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
645  * available both in the {@link Property} form as well as in similarly-named setter/getter
646  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
647  * be used to set persistent state associated with these rendering-related properties on the view.
648  * The properties and methods can also be used in conjunction with
649  * {@link android.animation.Animator Animator}-based animations, described more in the
650  * <a href="#Animation">Animation</a> section.
651  * </p>
652  *
653  * <a name="Animation"></a>
654  * <h3>Animation</h3>
655  * <p>
656  * Starting with Android 3.0, the preferred way of animating views is to use the
657  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
658  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
659  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
660  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
661  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
662  * makes animating these View properties particularly easy and efficient.
663  * </p>
664  * <p>
665  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
666  * You can attach an {@link Animation} object to a view using
667  * {@link #setAnimation(Animation)} or
668  * {@link #startAnimation(Animation)}. The animation can alter the scale,
669  * rotation, translation and alpha of a view over time. If the animation is
670  * attached to a view that has children, the animation will affect the entire
671  * subtree rooted by that node. When an animation is started, the framework will
672  * take care of redrawing the appropriate views until the animation completes.
673  * </p>
674  *
675  * <a name="Security"></a>
676  * <h3>Security</h3>
677  * <p>
678  * Sometimes it is essential that an application be able to verify that an action
679  * is being performed with the full knowledge and consent of the user, such as
680  * granting a permission request, making a purchase or clicking on an advertisement.
681  * Unfortunately, a malicious application could try to spoof the user into
682  * performing these actions, unaware, by concealing the intended purpose of the view.
683  * As a remedy, the framework offers a touch filtering mechanism that can be used to
684  * improve the security of views that provide access to sensitive functionality.
685  * </p><p>
686  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
687  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
688  * will discard touches that are received whenever the view's window is obscured by
689  * another visible window.  As a result, the view will not receive touches whenever a
690  * toast, dialog or other window appears above the view's window.
691  * </p><p>
692  * For more fine-grained control over security, consider overriding the
693  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
694  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
695  * </p>
696  *
697  * @attr ref android.R.styleable#View_alpha
698  * @attr ref android.R.styleable#View_background
699  * @attr ref android.R.styleable#View_clickable
700  * @attr ref android.R.styleable#View_contentDescription
701  * @attr ref android.R.styleable#View_drawingCacheQuality
702  * @attr ref android.R.styleable#View_duplicateParentState
703  * @attr ref android.R.styleable#View_id
704  * @attr ref android.R.styleable#View_requiresFadingEdge
705  * @attr ref android.R.styleable#View_fadeScrollbars
706  * @attr ref android.R.styleable#View_fadingEdgeLength
707  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
708  * @attr ref android.R.styleable#View_fitsSystemWindows
709  * @attr ref android.R.styleable#View_isScrollContainer
710  * @attr ref android.R.styleable#View_focusable
711  * @attr ref android.R.styleable#View_focusableInTouchMode
712  * @attr ref android.R.styleable#View_focusedByDefault
713  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
714  * @attr ref android.R.styleable#View_keepScreenOn
715  * @attr ref android.R.styleable#View_keyboardNavigationCluster
716  * @attr ref android.R.styleable#View_layerType
717  * @attr ref android.R.styleable#View_layoutDirection
718  * @attr ref android.R.styleable#View_longClickable
719  * @attr ref android.R.styleable#View_minHeight
720  * @attr ref android.R.styleable#View_minWidth
721  * @attr ref android.R.styleable#View_nextClusterForward
722  * @attr ref android.R.styleable#View_nextFocusDown
723  * @attr ref android.R.styleable#View_nextFocusLeft
724  * @attr ref android.R.styleable#View_nextFocusRight
725  * @attr ref android.R.styleable#View_nextFocusUp
726  * @attr ref android.R.styleable#View_onClick
727  * @attr ref android.R.styleable#View_padding
728  * @attr ref android.R.styleable#View_paddingHorizontal
729  * @attr ref android.R.styleable#View_paddingVertical
730  * @attr ref android.R.styleable#View_paddingBottom
731  * @attr ref android.R.styleable#View_paddingLeft
732  * @attr ref android.R.styleable#View_paddingRight
733  * @attr ref android.R.styleable#View_paddingTop
734  * @attr ref android.R.styleable#View_paddingStart
735  * @attr ref android.R.styleable#View_paddingEnd
736  * @attr ref android.R.styleable#View_saveEnabled
737  * @attr ref android.R.styleable#View_rotation
738  * @attr ref android.R.styleable#View_rotationX
739  * @attr ref android.R.styleable#View_rotationY
740  * @attr ref android.R.styleable#View_scaleX
741  * @attr ref android.R.styleable#View_scaleY
742  * @attr ref android.R.styleable#View_scrollX
743  * @attr ref android.R.styleable#View_scrollY
744  * @attr ref android.R.styleable#View_scrollbarSize
745  * @attr ref android.R.styleable#View_scrollbarStyle
746  * @attr ref android.R.styleable#View_scrollbars
747  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
748  * @attr ref android.R.styleable#View_scrollbarFadeDuration
749  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
750  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
751  * @attr ref android.R.styleable#View_scrollbarThumbVertical
752  * @attr ref android.R.styleable#View_scrollbarTrackVertical
753  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
754  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
755  * @attr ref android.R.styleable#View_stateListAnimator
756  * @attr ref android.R.styleable#View_transitionName
757  * @attr ref android.R.styleable#View_soundEffectsEnabled
758  * @attr ref android.R.styleable#View_tag
759  * @attr ref android.R.styleable#View_textAlignment
760  * @attr ref android.R.styleable#View_textDirection
761  * @attr ref android.R.styleable#View_transformPivotX
762  * @attr ref android.R.styleable#View_transformPivotY
763  * @attr ref android.R.styleable#View_translationX
764  * @attr ref android.R.styleable#View_translationY
765  * @attr ref android.R.styleable#View_translationZ
766  * @attr ref android.R.styleable#View_visibility
767  * @attr ref android.R.styleable#View_theme
768  *
769  * @see android.view.ViewGroup
770  */
771 @UiThread
772 public class View implements Drawable.Callback, KeyEvent.Callback,
773         AccessibilityEventSource {
774     private static final boolean DBG = false;
775 
776     /** @hide */
777     public static boolean DEBUG_DRAW = false;
778 
779     /**
780      * The logging tag used by this class with android.util.Log.
781      */
782     protected static final String VIEW_LOG_TAG = "View";
783 
784     /**
785      * When set to true, apps will draw debugging information about their layouts.
786      *
787      * @hide
788      */
789     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
790 
791     /**
792      * When set to true, this view will save its attribute data.
793      *
794      * @hide
795      */
796     public static boolean mDebugViewAttributes = false;
797 
798     /**
799      * Used to mark a View that has no ID.
800      */
801     public static final int NO_ID = -1;
802 
803     /**
804      * Last ID that is given to Views that are no part of activities.
805      *
806      * {@hide}
807      */
808     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
809 
810     /**
811      * Attribute to find the autofilled highlight
812      *
813      * @see #getAutofilledDrawable()
814      */
815     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
816             new int[]{android.R.attr.autofilledHighlight};
817 
818     /**
819      * Signals that compatibility booleans have been initialized according to
820      * target SDK versions.
821      */
822     private static boolean sCompatibilityDone = false;
823 
824     /**
825      * Use the old (broken) way of building MeasureSpecs.
826      */
827     private static boolean sUseBrokenMakeMeasureSpec = false;
828 
829     /**
830      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
831      */
832     static boolean sUseZeroUnspecifiedMeasureSpec = false;
833 
834     /**
835      * Ignore any optimizations using the measure cache.
836      */
837     private static boolean sIgnoreMeasureCache = false;
838 
839     /**
840      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
841      */
842     private static boolean sAlwaysRemeasureExactly = false;
843 
844     /**
845      * Relax constraints around whether setLayoutParams() must be called after
846      * modifying the layout params.
847      */
848     private static boolean sLayoutParamsAlwaysChanged = false;
849 
850     /**
851      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
852      * without throwing
853      */
854     static boolean sTextureViewIgnoresDrawableSetters = false;
855 
856     /**
857      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
858      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
859      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
860      * check is implemented for backwards compatibility.
861      *
862      * {@hide}
863      */
864     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
865 
866     /**
867      * Prior to N, when drag enters into child of a view that has already received an
868      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
869      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
870      * false from its event handler for these events.
871      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
872      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
873      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
874      */
875     static boolean sCascadedDragDrop;
876 
877     /**
878      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
879      * to determine things like whether or not to permit item click events. We can't break
880      * apps that do this just because more things (clickable things) are now auto-focusable
881      * and they would get different results, so give old behavior to old apps.
882      */
883     static boolean sHasFocusableExcludeAutoFocusable;
884 
885     /**
886      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
887      * made focusable by default. As a result, apps could (incorrectly) change the clickable
888      * setting of views off the UI thread. Now that clickable can effect the focusable state,
889      * changing the clickable attribute off the UI thread will cause an exception (since changing
890      * the focusable state checks). In order to prevent apps from crashing, we will handle this
891      * specific case and just not notify parents on new focusables resulting from marking views
892      * clickable from outside the UI thread.
893      */
894     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
895 
896     /** @hide */
897     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
898     @Retention(RetentionPolicy.SOURCE)
899     public @interface Focusable {}
900 
901     /**
902      * This view does not want keystrokes.
903      * <p>
904      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
905      * android:focusable}.
906      */
907     public static final int NOT_FOCUSABLE = 0x00000000;
908 
909     /**
910      * This view wants keystrokes.
911      * <p>
912      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
913      * android:focusable}.
914      */
915     public static final int FOCUSABLE = 0x00000001;
916 
917     /**
918      * This view determines focusability automatically. This is the default.
919      * <p>
920      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
921      * android:focusable}.
922      */
923     public static final int FOCUSABLE_AUTO = 0x00000010;
924 
925     /**
926      * Mask for use with setFlags indicating bits used for focus.
927      */
928     private static final int FOCUSABLE_MASK = 0x00000011;
929 
930     /**
931      * This view will adjust its padding to fit sytem windows (e.g. status bar)
932      */
933     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
934 
935     /** @hide */
936     @IntDef({VISIBLE, INVISIBLE, GONE})
937     @Retention(RetentionPolicy.SOURCE)
938     public @interface Visibility {}
939 
940     /**
941      * This view is visible.
942      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
943      * android:visibility}.
944      */
945     public static final int VISIBLE = 0x00000000;
946 
947     /**
948      * This view is invisible, but it still takes up space for layout purposes.
949      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
950      * android:visibility}.
951      */
952     public static final int INVISIBLE = 0x00000004;
953 
954     /**
955      * This view is invisible, and it doesn't take any space for layout
956      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
957      * android:visibility}.
958      */
959     public static final int GONE = 0x00000008;
960 
961     /**
962      * Mask for use with setFlags indicating bits used for visibility.
963      * {@hide}
964      */
965     static final int VISIBILITY_MASK = 0x0000000C;
966 
967     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
968 
969     /**
970      * Hint indicating that this view can be autofilled with an email address.
971      *
972      * <p>Can be used with either {@link #setAutofillHints(String[])} or
973      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
974      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
975      *
976      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
977      */
978     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
979 
980     /**
981      * Hint indicating that this view can be autofilled with a user's real name.
982      *
983      * <p>Can be used with either {@link #setAutofillHints(String[])} or
984      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
985      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
986      *
987      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
988      */
989     public static final String AUTOFILL_HINT_NAME = "name";
990 
991     /**
992      * Hint indicating that this view can be autofilled with a username.
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_USERNAME}</code>).
997      *
998      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
999      */
1000     public static final String AUTOFILL_HINT_USERNAME = "username";
1001 
1002     /**
1003      * Hint indicating that this view can be autofilled with a password.
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_PASSWORD}</code>).
1008      *
1009      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1010      */
1011     public static final String AUTOFILL_HINT_PASSWORD = "password";
1012 
1013     /**
1014      * Hint indicating that this view can be autofilled with a phone number.
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_PHONE}</code>).
1019      *
1020      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1021      */
1022     public static final String AUTOFILL_HINT_PHONE = "phone";
1023 
1024     /**
1025      * Hint indicating that this view can be autofilled with a postal address.
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_POSTAL_ADDRESS}</code>).
1030      *
1031      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1032      */
1033     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1034 
1035     /**
1036      * Hint indicating that this view can be autofilled with a postal code.
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_POSTAL_CODE}</code>).
1041      *
1042      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1043      */
1044     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1045 
1046     /**
1047      * Hint indicating that this view can be autofilled with a credit card number.
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_CREDIT_CARD_NUMBER}</code>).
1052      *
1053      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1054      */
1055     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1056 
1057     /**
1058      * Hint indicating that this view can be autofilled with a credit card security 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_CREDIT_CARD_SECURITY_CODE}</code>).
1063      *
1064      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1065      */
1066     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1067 
1068     /**
1069      * Hint indicating that this view can be autofilled with a credit card expiration date.
1070      *
1071      * <p>It should be used when the credit card expiration date is represented by just one view;
1072      * if it is represented by more than one (for example, one view for the month and another view
1073      * for the year), then each of these views should use the hint specific for the unit
1074      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1075      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1076      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1077      *
1078      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1079      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1080      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1081      *
1082      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1083      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1084      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1085      * the following options:
1086      *
1087      * <ul>
1088      *   <li>{@code "04/2020"}
1089      *   <li>{@code "4/2020"}
1090      *   <li>{@code "2020/04"}
1091      *   <li>{@code "2020/4"}
1092      *   <li>{@code "April/2020"}
1093      *   <li>{@code "Apr/2020"}
1094      * </ul>
1095      *
1096      * <p>You define a date autofill value for the view by overriding the following methods:
1097      *
1098      * <ol>
1099      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1100      *   <li>{@link #getAutofillValue()} to return a
1101      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1102      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1103      * </ol>
1104      *
1105      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1106      */
1107     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1108             "creditCardExpirationDate";
1109 
1110     /**
1111      * Hint indicating that this view can be autofilled with a credit card expiration month.
1112      *
1113      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1114      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1115      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1116      *
1117      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1118      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1119      * ambiguity when the autofill service provides a value for it. To understand why a
1120      * value can be ambiguous, consider "January", which could be represented as either of
1121      *
1122      * <ul>
1123      *   <li>{@code "1"}: recommended way.
1124      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1125      *   <li>{@code "January"}: full name, in English.
1126      *   <li>{@code "jan"}: abbreviated name, in English.
1127      *   <li>{@code "Janeiro"}: full name, in another language.
1128      * </ul>
1129      *
1130      * <p>Another recommended approach is to use a date autofill value - see
1131      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1132      *
1133      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1134      */
1135     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1136             "creditCardExpirationMonth";
1137 
1138     /**
1139      * Hint indicating that this view can be autofilled with a credit card expiration year.
1140      *
1141      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1142      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1143      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1144      *
1145      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1146      */
1147     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1148             "creditCardExpirationYear";
1149 
1150     /**
1151      * Hint indicating that this view can be autofilled with a credit card expiration day.
1152      *
1153      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1154      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1155      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1156      *
1157      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1158      */
1159     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1160 
1161     /**
1162      * Hints for the autofill services that describes the content of the view.
1163      */
1164     private @Nullable String[] mAutofillHints;
1165 
1166     /**
1167      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1168      */
1169     private AutofillId mAutofillId;
1170 
1171     /** @hide */
1172     @IntDef({
1173             AUTOFILL_TYPE_NONE,
1174             AUTOFILL_TYPE_TEXT,
1175             AUTOFILL_TYPE_TOGGLE,
1176             AUTOFILL_TYPE_LIST,
1177             AUTOFILL_TYPE_DATE
1178     })
1179     @Retention(RetentionPolicy.SOURCE)
1180     public @interface AutofillType {}
1181 
1182     /**
1183      * Autofill type for views that cannot be autofilled.
1184      *
1185      * <p>Typically used when the view is read-only; for example, a text label.
1186      *
1187      * @see #getAutofillType()
1188      */
1189     public static final int AUTOFILL_TYPE_NONE = 0;
1190 
1191     /**
1192      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1193      *
1194      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1195      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1196      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1197      *
1198      * @see #getAutofillType()
1199      */
1200     public static final int AUTOFILL_TYPE_TEXT = 1;
1201 
1202     /**
1203      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1204      *
1205      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1206      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1207      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1208      *
1209      * @see #getAutofillType()
1210      */
1211     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1212 
1213     /**
1214      * Autofill type for a selection list field, which is filled by an {@code int}
1215      * representing the element index inside the list (starting at {@code 0}).
1216      *
1217      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1218      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1219      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1220      *
1221      * <p>The available options in the selection list are typically provided by
1222      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1223      *
1224      * @see #getAutofillType()
1225      */
1226     public static final int AUTOFILL_TYPE_LIST = 3;
1227 
1228 
1229     /**
1230      * Autofill type for a field that contains a date, which is represented by a long representing
1231      * the number of milliseconds since the standard base time known as "the epoch", namely
1232      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1233      *
1234      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1235      * {@link AutofillValue#forDate(long)}, and the values passed to
1236      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1237      *
1238      * @see #getAutofillType()
1239      */
1240     public static final int AUTOFILL_TYPE_DATE = 4;
1241 
1242     /** @hide */
1243     @IntDef({
1244             IMPORTANT_FOR_AUTOFILL_AUTO,
1245             IMPORTANT_FOR_AUTOFILL_YES,
1246             IMPORTANT_FOR_AUTOFILL_NO,
1247             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1248             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1249     })
1250     @Retention(RetentionPolicy.SOURCE)
1251     public @interface AutofillImportance {}
1252 
1253     /**
1254      * Automatically determine whether a view is important for autofill.
1255      *
1256      * @see #isImportantForAutofill()
1257      * @see #setImportantForAutofill(int)
1258      */
1259     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1260 
1261     /**
1262      * The view is important for autofill, and its children (if any) will be traversed.
1263      *
1264      * @see #isImportantForAutofill()
1265      * @see #setImportantForAutofill(int)
1266      */
1267     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1268 
1269     /**
1270      * The view is not important for autofill, but its children (if any) will be traversed.
1271      *
1272      * @see #isImportantForAutofill()
1273      * @see #setImportantForAutofill(int)
1274      */
1275     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1276 
1277     /**
1278      * The view is important for autofill, but its children (if any) will not be traversed.
1279      *
1280      * @see #isImportantForAutofill()
1281      * @see #setImportantForAutofill(int)
1282      */
1283     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1284 
1285     /**
1286      * The view is not important for autofill, and its children (if any) will not be traversed.
1287      *
1288      * @see #isImportantForAutofill()
1289      * @see #setImportantForAutofill(int)
1290      */
1291     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1292 
1293     /** @hide */
1294     @IntDef(
1295             flag = true,
1296             value = {AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS})
1297     @Retention(RetentionPolicy.SOURCE)
1298     public @interface AutofillFlags {}
1299 
1300     /**
1301      * Flag requesting you to add views that are marked as not important for autofill
1302      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1303      */
1304     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1305 
1306     /**
1307      * This view is enabled. Interpretation varies by subclass.
1308      * Use with ENABLED_MASK when calling setFlags.
1309      * {@hide}
1310      */
1311     static final int ENABLED = 0x00000000;
1312 
1313     /**
1314      * This view is disabled. Interpretation varies by subclass.
1315      * Use with ENABLED_MASK when calling setFlags.
1316      * {@hide}
1317      */
1318     static final int DISABLED = 0x00000020;
1319 
1320    /**
1321     * Mask for use with setFlags indicating bits used for indicating whether
1322     * this view is enabled
1323     * {@hide}
1324     */
1325     static final int ENABLED_MASK = 0x00000020;
1326 
1327     /**
1328      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1329      * called and further optimizations will be performed. It is okay to have
1330      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1331      * {@hide}
1332      */
1333     static final int WILL_NOT_DRAW = 0x00000080;
1334 
1335     /**
1336      * Mask for use with setFlags indicating bits used for indicating whether
1337      * this view is will draw
1338      * {@hide}
1339      */
1340     static final int DRAW_MASK = 0x00000080;
1341 
1342     /**
1343      * <p>This view doesn't show scrollbars.</p>
1344      * {@hide}
1345      */
1346     static final int SCROLLBARS_NONE = 0x00000000;
1347 
1348     /**
1349      * <p>This view shows horizontal scrollbars.</p>
1350      * {@hide}
1351      */
1352     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1353 
1354     /**
1355      * <p>This view shows vertical scrollbars.</p>
1356      * {@hide}
1357      */
1358     static final int SCROLLBARS_VERTICAL = 0x00000200;
1359 
1360     /**
1361      * <p>Mask for use with setFlags indicating bits used for indicating which
1362      * scrollbars are enabled.</p>
1363      * {@hide}
1364      */
1365     static final int SCROLLBARS_MASK = 0x00000300;
1366 
1367     /**
1368      * Indicates that the view should filter touches when its window is obscured.
1369      * Refer to the class comments for more information about this security feature.
1370      * {@hide}
1371      */
1372     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1373 
1374     /**
1375      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1376      * that they are optional and should be skipped if the window has
1377      * requested system UI flags that ignore those insets for layout.
1378      */
1379     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1380 
1381     /**
1382      * <p>This view doesn't show fading edges.</p>
1383      * {@hide}
1384      */
1385     static final int FADING_EDGE_NONE = 0x00000000;
1386 
1387     /**
1388      * <p>This view shows horizontal fading edges.</p>
1389      * {@hide}
1390      */
1391     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1392 
1393     /**
1394      * <p>This view shows vertical fading edges.</p>
1395      * {@hide}
1396      */
1397     static final int FADING_EDGE_VERTICAL = 0x00002000;
1398 
1399     /**
1400      * <p>Mask for use with setFlags indicating bits used for indicating which
1401      * fading edges are enabled.</p>
1402      * {@hide}
1403      */
1404     static final int FADING_EDGE_MASK = 0x00003000;
1405 
1406     /**
1407      * <p>Indicates this view can be clicked. When clickable, a View reacts
1408      * to clicks by notifying the OnClickListener.<p>
1409      * {@hide}
1410      */
1411     static final int CLICKABLE = 0x00004000;
1412 
1413     /**
1414      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1415      * {@hide}
1416      */
1417     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1418 
1419     /**
1420      * <p>Indicates that no icicle should be saved for this view.<p>
1421      * {@hide}
1422      */
1423     static final int SAVE_DISABLED = 0x000010000;
1424 
1425     /**
1426      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1427      * property.</p>
1428      * {@hide}
1429      */
1430     static final int SAVE_DISABLED_MASK = 0x000010000;
1431 
1432     /**
1433      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1434      * {@hide}
1435      */
1436     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1437 
1438     /**
1439      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1440      * {@hide}
1441      */
1442     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1443 
1444     /** @hide */
1445     @Retention(RetentionPolicy.SOURCE)
1446     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1447     public @interface DrawingCacheQuality {}
1448 
1449     /**
1450      * <p>Enables low quality mode for the drawing cache.</p>
1451      */
1452     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1453 
1454     /**
1455      * <p>Enables high quality mode for the drawing cache.</p>
1456      */
1457     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1458 
1459     /**
1460      * <p>Enables automatic quality mode for the drawing cache.</p>
1461      */
1462     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1463 
1464     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1465             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1466     };
1467 
1468     /**
1469      * <p>Mask for use with setFlags indicating bits used for the cache
1470      * quality property.</p>
1471      * {@hide}
1472      */
1473     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1474 
1475     /**
1476      * <p>
1477      * Indicates this view can be long clicked. When long clickable, a View
1478      * reacts to long clicks by notifying the OnLongClickListener or showing a
1479      * context menu.
1480      * </p>
1481      * {@hide}
1482      */
1483     static final int LONG_CLICKABLE = 0x00200000;
1484 
1485     /**
1486      * <p>Indicates that this view gets its drawable states from its direct parent
1487      * and ignores its original internal states.</p>
1488      *
1489      * @hide
1490      */
1491     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1492 
1493     /**
1494      * <p>
1495      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1496      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1497      * OnContextClickListener.
1498      * </p>
1499      * {@hide}
1500      */
1501     static final int CONTEXT_CLICKABLE = 0x00800000;
1502 
1503 
1504     /** @hide */
1505     @IntDef({
1506         SCROLLBARS_INSIDE_OVERLAY,
1507         SCROLLBARS_INSIDE_INSET,
1508         SCROLLBARS_OUTSIDE_OVERLAY,
1509         SCROLLBARS_OUTSIDE_INSET
1510     })
1511     @Retention(RetentionPolicy.SOURCE)
1512     public @interface ScrollBarStyle {}
1513 
1514     /**
1515      * The scrollbar style to display the scrollbars inside the content area,
1516      * without increasing the padding. The scrollbars will be overlaid with
1517      * translucency on the view's content.
1518      */
1519     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1520 
1521     /**
1522      * The scrollbar style to display the scrollbars inside the padded area,
1523      * increasing the padding of the view. The scrollbars will not overlap the
1524      * content area of the view.
1525      */
1526     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1527 
1528     /**
1529      * The scrollbar style to display the scrollbars at the edge of the view,
1530      * without increasing the padding. The scrollbars will be overlaid with
1531      * translucency.
1532      */
1533     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1534 
1535     /**
1536      * The scrollbar style to display the scrollbars at the edge of the view,
1537      * increasing the padding of the view. The scrollbars will only overlap the
1538      * background, if any.
1539      */
1540     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1541 
1542     /**
1543      * Mask to check if the scrollbar style is overlay or inset.
1544      * {@hide}
1545      */
1546     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1547 
1548     /**
1549      * Mask to check if the scrollbar style is inside or outside.
1550      * {@hide}
1551      */
1552     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1553 
1554     /**
1555      * Mask for scrollbar style.
1556      * {@hide}
1557      */
1558     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1559 
1560     /**
1561      * View flag indicating that the screen should remain on while the
1562      * window containing this view is visible to the user.  This effectively
1563      * takes care of automatically setting the WindowManager's
1564      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1565      */
1566     public static final int KEEP_SCREEN_ON = 0x04000000;
1567 
1568     /**
1569      * View flag indicating whether this view should have sound effects enabled
1570      * for events such as clicking and touching.
1571      */
1572     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1573 
1574     /**
1575      * View flag indicating whether this view should have haptic feedback
1576      * enabled for events such as long presses.
1577      */
1578     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1579 
1580     /**
1581      * <p>Indicates that the view hierarchy should stop saving state when
1582      * it reaches this view.  If state saving is initiated immediately at
1583      * the view, it will be allowed.
1584      * {@hide}
1585      */
1586     static final int PARENT_SAVE_DISABLED = 0x20000000;
1587 
1588     /**
1589      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1590      * {@hide}
1591      */
1592     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1593 
1594     private static Paint sDebugPaint;
1595 
1596     /**
1597      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1598      * {@hide}
1599      */
1600     static final int TOOLTIP = 0x40000000;
1601 
1602     /** @hide */
1603     @IntDef(flag = true,
1604             value = {
1605                 FOCUSABLES_ALL,
1606                 FOCUSABLES_TOUCH_MODE
1607             })
1608     @Retention(RetentionPolicy.SOURCE)
1609     public @interface FocusableMode {}
1610 
1611     /**
1612      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1613      * should add all focusable Views regardless if they are focusable in touch mode.
1614      */
1615     public static final int FOCUSABLES_ALL = 0x00000000;
1616 
1617     /**
1618      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1619      * should add only Views focusable in touch mode.
1620      */
1621     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1622 
1623     /** @hide */
1624     @IntDef({
1625             FOCUS_BACKWARD,
1626             FOCUS_FORWARD,
1627             FOCUS_LEFT,
1628             FOCUS_UP,
1629             FOCUS_RIGHT,
1630             FOCUS_DOWN
1631     })
1632     @Retention(RetentionPolicy.SOURCE)
1633     public @interface FocusDirection {}
1634 
1635     /** @hide */
1636     @IntDef({
1637             FOCUS_LEFT,
1638             FOCUS_UP,
1639             FOCUS_RIGHT,
1640             FOCUS_DOWN
1641     })
1642     @Retention(RetentionPolicy.SOURCE)
1643     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1644 
1645     /**
1646      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1647      * item.
1648      */
1649     public static final int FOCUS_BACKWARD = 0x00000001;
1650 
1651     /**
1652      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1653      * item.
1654      */
1655     public static final int FOCUS_FORWARD = 0x00000002;
1656 
1657     /**
1658      * Use with {@link #focusSearch(int)}. Move focus to the left.
1659      */
1660     public static final int FOCUS_LEFT = 0x00000011;
1661 
1662     /**
1663      * Use with {@link #focusSearch(int)}. Move focus up.
1664      */
1665     public static final int FOCUS_UP = 0x00000021;
1666 
1667     /**
1668      * Use with {@link #focusSearch(int)}. Move focus to the right.
1669      */
1670     public static final int FOCUS_RIGHT = 0x00000042;
1671 
1672     /**
1673      * Use with {@link #focusSearch(int)}. Move focus down.
1674      */
1675     public static final int FOCUS_DOWN = 0x00000082;
1676 
1677     /**
1678      * Bits of {@link #getMeasuredWidthAndState()} and
1679      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1680      */
1681     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1682 
1683     /**
1684      * Bits of {@link #getMeasuredWidthAndState()} and
1685      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1686      */
1687     public static final int MEASURED_STATE_MASK = 0xff000000;
1688 
1689     /**
1690      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1691      * for functions that combine both width and height into a single int,
1692      * such as {@link #getMeasuredState()} and the childState argument of
1693      * {@link #resolveSizeAndState(int, int, int)}.
1694      */
1695     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1696 
1697     /**
1698      * Bit of {@link #getMeasuredWidthAndState()} and
1699      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1700      * is smaller that the space the view would like to have.
1701      */
1702     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1703 
1704     /**
1705      * Base View state sets
1706      */
1707     // Singles
1708     /**
1709      * Indicates the view has no states set. States are used with
1710      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1711      * view depending on its state.
1712      *
1713      * @see android.graphics.drawable.Drawable
1714      * @see #getDrawableState()
1715      */
1716     protected static final int[] EMPTY_STATE_SET;
1717     /**
1718      * Indicates the view is enabled. States are used with
1719      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1720      * view depending on its state.
1721      *
1722      * @see android.graphics.drawable.Drawable
1723      * @see #getDrawableState()
1724      */
1725     protected static final int[] ENABLED_STATE_SET;
1726     /**
1727      * Indicates the view is focused. States are used with
1728      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1729      * view depending on its state.
1730      *
1731      * @see android.graphics.drawable.Drawable
1732      * @see #getDrawableState()
1733      */
1734     protected static final int[] FOCUSED_STATE_SET;
1735     /**
1736      * Indicates the view is selected. States are used with
1737      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1738      * view depending on its state.
1739      *
1740      * @see android.graphics.drawable.Drawable
1741      * @see #getDrawableState()
1742      */
1743     protected static final int[] SELECTED_STATE_SET;
1744     /**
1745      * Indicates the view is pressed. States are used with
1746      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1747      * view depending on its state.
1748      *
1749      * @see android.graphics.drawable.Drawable
1750      * @see #getDrawableState()
1751      */
1752     protected static final int[] PRESSED_STATE_SET;
1753     /**
1754      * Indicates the view's window has focus. States are used with
1755      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1756      * view depending on its state.
1757      *
1758      * @see android.graphics.drawable.Drawable
1759      * @see #getDrawableState()
1760      */
1761     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1762     // Doubles
1763     /**
1764      * Indicates the view is enabled and has the focus.
1765      *
1766      * @see #ENABLED_STATE_SET
1767      * @see #FOCUSED_STATE_SET
1768      */
1769     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1770     /**
1771      * Indicates the view is enabled and selected.
1772      *
1773      * @see #ENABLED_STATE_SET
1774      * @see #SELECTED_STATE_SET
1775      */
1776     protected static final int[] ENABLED_SELECTED_STATE_SET;
1777     /**
1778      * Indicates the view is enabled and that its window has focus.
1779      *
1780      * @see #ENABLED_STATE_SET
1781      * @see #WINDOW_FOCUSED_STATE_SET
1782      */
1783     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1784     /**
1785      * Indicates the view is focused and selected.
1786      *
1787      * @see #FOCUSED_STATE_SET
1788      * @see #SELECTED_STATE_SET
1789      */
1790     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1791     /**
1792      * Indicates the view has the focus and that its window has the focus.
1793      *
1794      * @see #FOCUSED_STATE_SET
1795      * @see #WINDOW_FOCUSED_STATE_SET
1796      */
1797     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1798     /**
1799      * Indicates the view is selected and that its window has the focus.
1800      *
1801      * @see #SELECTED_STATE_SET
1802      * @see #WINDOW_FOCUSED_STATE_SET
1803      */
1804     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1805     // Triples
1806     /**
1807      * Indicates the view is enabled, focused and selected.
1808      *
1809      * @see #ENABLED_STATE_SET
1810      * @see #FOCUSED_STATE_SET
1811      * @see #SELECTED_STATE_SET
1812      */
1813     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1814     /**
1815      * Indicates the view is enabled, focused and its window has the focus.
1816      *
1817      * @see #ENABLED_STATE_SET
1818      * @see #FOCUSED_STATE_SET
1819      * @see #WINDOW_FOCUSED_STATE_SET
1820      */
1821     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1822     /**
1823      * Indicates the view is enabled, selected and its window has the focus.
1824      *
1825      * @see #ENABLED_STATE_SET
1826      * @see #SELECTED_STATE_SET
1827      * @see #WINDOW_FOCUSED_STATE_SET
1828      */
1829     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1830     /**
1831      * Indicates the view is focused, selected and its window has the focus.
1832      *
1833      * @see #FOCUSED_STATE_SET
1834      * @see #SELECTED_STATE_SET
1835      * @see #WINDOW_FOCUSED_STATE_SET
1836      */
1837     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1838     /**
1839      * Indicates the view is enabled, focused, selected and its window
1840      * has the focus.
1841      *
1842      * @see #ENABLED_STATE_SET
1843      * @see #FOCUSED_STATE_SET
1844      * @see #SELECTED_STATE_SET
1845      * @see #WINDOW_FOCUSED_STATE_SET
1846      */
1847     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1848     /**
1849      * Indicates the view is pressed and its window has the focus.
1850      *
1851      * @see #PRESSED_STATE_SET
1852      * @see #WINDOW_FOCUSED_STATE_SET
1853      */
1854     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1855     /**
1856      * Indicates the view is pressed and selected.
1857      *
1858      * @see #PRESSED_STATE_SET
1859      * @see #SELECTED_STATE_SET
1860      */
1861     protected static final int[] PRESSED_SELECTED_STATE_SET;
1862     /**
1863      * Indicates the view is pressed, selected and its window has the focus.
1864      *
1865      * @see #PRESSED_STATE_SET
1866      * @see #SELECTED_STATE_SET
1867      * @see #WINDOW_FOCUSED_STATE_SET
1868      */
1869     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1870     /**
1871      * Indicates the view is pressed and focused.
1872      *
1873      * @see #PRESSED_STATE_SET
1874      * @see #FOCUSED_STATE_SET
1875      */
1876     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1877     /**
1878      * Indicates the view is pressed, focused and its window has the focus.
1879      *
1880      * @see #PRESSED_STATE_SET
1881      * @see #FOCUSED_STATE_SET
1882      * @see #WINDOW_FOCUSED_STATE_SET
1883      */
1884     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1885     /**
1886      * Indicates the view is pressed, focused and selected.
1887      *
1888      * @see #PRESSED_STATE_SET
1889      * @see #SELECTED_STATE_SET
1890      * @see #FOCUSED_STATE_SET
1891      */
1892     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1893     /**
1894      * Indicates the view is pressed, focused, selected and its window has the focus.
1895      *
1896      * @see #PRESSED_STATE_SET
1897      * @see #FOCUSED_STATE_SET
1898      * @see #SELECTED_STATE_SET
1899      * @see #WINDOW_FOCUSED_STATE_SET
1900      */
1901     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1902     /**
1903      * Indicates the view is pressed and enabled.
1904      *
1905      * @see #PRESSED_STATE_SET
1906      * @see #ENABLED_STATE_SET
1907      */
1908     protected static final int[] PRESSED_ENABLED_STATE_SET;
1909     /**
1910      * Indicates the view is pressed, enabled and its window has the focus.
1911      *
1912      * @see #PRESSED_STATE_SET
1913      * @see #ENABLED_STATE_SET
1914      * @see #WINDOW_FOCUSED_STATE_SET
1915      */
1916     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1917     /**
1918      * Indicates the view is pressed, enabled and selected.
1919      *
1920      * @see #PRESSED_STATE_SET
1921      * @see #ENABLED_STATE_SET
1922      * @see #SELECTED_STATE_SET
1923      */
1924     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1925     /**
1926      * Indicates the view is pressed, enabled, selected and its window has the
1927      * focus.
1928      *
1929      * @see #PRESSED_STATE_SET
1930      * @see #ENABLED_STATE_SET
1931      * @see #SELECTED_STATE_SET
1932      * @see #WINDOW_FOCUSED_STATE_SET
1933      */
1934     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1935     /**
1936      * Indicates the view is pressed, enabled and focused.
1937      *
1938      * @see #PRESSED_STATE_SET
1939      * @see #ENABLED_STATE_SET
1940      * @see #FOCUSED_STATE_SET
1941      */
1942     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1943     /**
1944      * Indicates the view is pressed, enabled, focused and its window has the
1945      * focus.
1946      *
1947      * @see #PRESSED_STATE_SET
1948      * @see #ENABLED_STATE_SET
1949      * @see #FOCUSED_STATE_SET
1950      * @see #WINDOW_FOCUSED_STATE_SET
1951      */
1952     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1953     /**
1954      * Indicates the view is pressed, enabled, focused and selected.
1955      *
1956      * @see #PRESSED_STATE_SET
1957      * @see #ENABLED_STATE_SET
1958      * @see #SELECTED_STATE_SET
1959      * @see #FOCUSED_STATE_SET
1960      */
1961     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1962     /**
1963      * Indicates the view is pressed, enabled, focused, selected and its window
1964      * has the focus.
1965      *
1966      * @see #PRESSED_STATE_SET
1967      * @see #ENABLED_STATE_SET
1968      * @see #SELECTED_STATE_SET
1969      * @see #FOCUSED_STATE_SET
1970      * @see #WINDOW_FOCUSED_STATE_SET
1971      */
1972     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1973 
1974     static {
1975         EMPTY_STATE_SET = StateSet.get(0);
1976 
1977         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1978 
1979         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1980         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1981                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1982 
1983         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1984         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1985                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1986         FOCUSED_SELECTED_STATE_SET = StateSet.get(
1987                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1988         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1989                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1990                         | StateSet.VIEW_STATE_FOCUSED);
1991 
1992         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1993         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1994                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1995         ENABLED_SELECTED_STATE_SET = StateSet.get(
1996                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1997         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1998                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1999                         | StateSet.VIEW_STATE_ENABLED);
2000         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2001                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2002         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2003                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2004                         | StateSet.VIEW_STATE_ENABLED);
2005         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2006                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2007                         | StateSet.VIEW_STATE_ENABLED);
2008         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2009                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2010                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2011 
2012         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2013         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2014                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2015         PRESSED_SELECTED_STATE_SET = StateSet.get(
2016                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2017         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2018                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2019                         | StateSet.VIEW_STATE_PRESSED);
2020         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2021                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2022         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2023                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2024                         | StateSet.VIEW_STATE_PRESSED);
2025         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2026                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2027                         | StateSet.VIEW_STATE_PRESSED);
2028         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2029                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2030                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2031         PRESSED_ENABLED_STATE_SET = StateSet.get(
2032                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2033         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2034                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2035                         | StateSet.VIEW_STATE_PRESSED);
2036         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2037                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2038                         | StateSet.VIEW_STATE_PRESSED);
2039         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2040                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2041                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2042         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2043                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2044                         | StateSet.VIEW_STATE_PRESSED);
2045         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2046                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2047                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2048         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2049                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2050                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2051         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2052                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2053                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2054                         | StateSet.VIEW_STATE_PRESSED);
2055     }
2056 
2057     /**
2058      * Accessibility event types that are dispatched for text population.
2059      */
2060     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2061             AccessibilityEvent.TYPE_VIEW_CLICKED
2062             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2063             | AccessibilityEvent.TYPE_VIEW_SELECTED
2064             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2065             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2066             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2067             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2068             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2069             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2070             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2071             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2072 
2073     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2074 
2075     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2076 
2077     /**
2078      * Temporary Rect currently for use in setBackground().  This will probably
2079      * be extended in the future to hold our own class with more than just
2080      * a Rect. :)
2081      */
2082     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2083 
2084     /**
2085      * Map used to store views' tags.
2086      */
2087     private SparseArray<Object> mKeyedTags;
2088 
2089     /**
2090      * The next available accessibility id.
2091      */
2092     private static int sNextAccessibilityViewId;
2093 
2094     /**
2095      * The animation currently associated with this view.
2096      * @hide
2097      */
2098     protected Animation mCurrentAnimation = null;
2099 
2100     /**
2101      * Width as measured during measure pass.
2102      * {@hide}
2103      */
2104     @ViewDebug.ExportedProperty(category = "measurement")
2105     int mMeasuredWidth;
2106 
2107     /**
2108      * Height as measured during measure pass.
2109      * {@hide}
2110      */
2111     @ViewDebug.ExportedProperty(category = "measurement")
2112     int mMeasuredHeight;
2113 
2114     /**
2115      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2116      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2117      * its display list. This flag, used only when hw accelerated, allows us to clear the
2118      * flag while retaining this information until it's needed (at getDisplayList() time and
2119      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2120      *
2121      * {@hide}
2122      */
2123     boolean mRecreateDisplayList = false;
2124 
2125     /**
2126      * The view's identifier.
2127      * {@hide}
2128      *
2129      * @see #setId(int)
2130      * @see #getId()
2131      */
2132     @IdRes
2133     @ViewDebug.ExportedProperty(resolveId = true)
2134     int mID = NO_ID;
2135 
2136     /** The ID of this view for autofill purposes.
2137      * <ul>
2138      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2139      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2140      *                                                  unique in the process. This might change
2141      *                                                  over activity lifecycle events.
2142      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2143      *                                                  unique in the activity. This stays the same
2144      *                                                  over activity lifecycle events.
2145      */
2146     private int mAutofillViewId = NO_ID;
2147 
2148     // ID for accessibility purposes. This ID must be unique for every window
2149     private int mAccessibilityViewId = NO_ID;
2150 
2151     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2152 
2153     /**
2154      * The view's tag.
2155      * {@hide}
2156      *
2157      * @see #setTag(Object)
2158      * @see #getTag()
2159      */
2160     protected Object mTag = null;
2161 
2162     // for mPrivateFlags:
2163     /** {@hide} */
2164     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2165     /** {@hide} */
2166     static final int PFLAG_FOCUSED                     = 0x00000002;
2167     /** {@hide} */
2168     static final int PFLAG_SELECTED                    = 0x00000004;
2169     /** {@hide} */
2170     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2171     /** {@hide} */
2172     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2173     /** {@hide} */
2174     static final int PFLAG_DRAWN                       = 0x00000020;
2175     /**
2176      * When this flag is set, this view is running an animation on behalf of its
2177      * children and should therefore not cancel invalidate requests, even if they
2178      * lie outside of this view's bounds.
2179      *
2180      * {@hide}
2181      */
2182     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2183     /** {@hide} */
2184     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2185     /** {@hide} */
2186     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2187     /** {@hide} */
2188     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2189     /** {@hide} */
2190     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2191     /** {@hide} */
2192     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2193     /** {@hide} */
2194     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2195 
2196     private static final int PFLAG_PRESSED             = 0x00004000;
2197 
2198     /** {@hide} */
2199     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2200     /**
2201      * Flag used to indicate that this view should be drawn once more (and only once
2202      * more) after its animation has completed.
2203      * {@hide}
2204      */
2205     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2206 
2207     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2208 
2209     /**
2210      * Indicates that the View returned true when onSetAlpha() was called and that
2211      * the alpha must be restored.
2212      * {@hide}
2213      */
2214     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2215 
2216     /**
2217      * Set by {@link #setScrollContainer(boolean)}.
2218      */
2219     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2220 
2221     /**
2222      * Set by {@link #setScrollContainer(boolean)}.
2223      */
2224     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2225 
2226     /**
2227      * View flag indicating whether this view was invalidated (fully or partially.)
2228      *
2229      * @hide
2230      */
2231     static final int PFLAG_DIRTY                       = 0x00200000;
2232 
2233     /**
2234      * View flag indicating whether this view was invalidated by an opaque
2235      * invalidate request.
2236      *
2237      * @hide
2238      */
2239     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2240 
2241     /**
2242      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2243      *
2244      * @hide
2245      */
2246     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2247 
2248     /**
2249      * Indicates whether the background is opaque.
2250      *
2251      * @hide
2252      */
2253     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2254 
2255     /**
2256      * Indicates whether the scrollbars are opaque.
2257      *
2258      * @hide
2259      */
2260     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2261 
2262     /**
2263      * Indicates whether the view is opaque.
2264      *
2265      * @hide
2266      */
2267     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2268 
2269     /**
2270      * Indicates a prepressed state;
2271      * the short time between ACTION_DOWN and recognizing
2272      * a 'real' press. Prepressed is used to recognize quick taps
2273      * even when they are shorter than ViewConfiguration.getTapTimeout().
2274      *
2275      * @hide
2276      */
2277     private static final int PFLAG_PREPRESSED          = 0x02000000;
2278 
2279     /**
2280      * Indicates whether the view is temporarily detached.
2281      *
2282      * @hide
2283      */
2284     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2285 
2286     /**
2287      * Indicates that we should awaken scroll bars once attached
2288      *
2289      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2290      * during window attachment and it is no longer needed. Feel free to repurpose it.
2291      *
2292      * @hide
2293      */
2294     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2295 
2296     /**
2297      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2298      * @hide
2299      */
2300     private static final int PFLAG_HOVERED             = 0x10000000;
2301 
2302     /**
2303      * no longer needed, should be reused
2304      */
2305     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2306 
2307     /** {@hide} */
2308     static final int PFLAG_ACTIVATED                   = 0x40000000;
2309 
2310     /**
2311      * Indicates that this view was specifically invalidated, not just dirtied because some
2312      * child view was invalidated. The flag is used to determine when we need to recreate
2313      * a view's display list (as opposed to just returning a reference to its existing
2314      * display list).
2315      *
2316      * @hide
2317      */
2318     static final int PFLAG_INVALIDATED                 = 0x80000000;
2319 
2320     /**
2321      * Masks for mPrivateFlags2, as generated by dumpFlags():
2322      *
2323      * |-------|-------|-------|-------|
2324      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2325      *                                1  PFLAG2_DRAG_HOVERED
2326      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2327      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2328      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2329      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2330      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2331      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2332      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2333      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2334      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2335      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2336      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2337      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2338      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2339      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2340      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2341      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2342      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2343      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2344      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2345      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2346      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2347      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2348      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2349      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2350      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2351      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2352      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2353      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2354      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2355      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2356      *    1                              PFLAG2_PADDING_RESOLVED
2357      *   1                               PFLAG2_DRAWABLE_RESOLVED
2358      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2359      * |-------|-------|-------|-------|
2360      */
2361 
2362     /**
2363      * Indicates that this view has reported that it can accept the current drag's content.
2364      * Cleared when the drag operation concludes.
2365      * @hide
2366      */
2367     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2368 
2369     /**
2370      * Indicates that this view is currently directly under the drag location in a
2371      * drag-and-drop operation involving content that it can accept.  Cleared when
2372      * the drag exits the view, or when the drag operation concludes.
2373      * @hide
2374      */
2375     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2376 
2377     /** @hide */
2378     @IntDef({
2379         LAYOUT_DIRECTION_LTR,
2380         LAYOUT_DIRECTION_RTL,
2381         LAYOUT_DIRECTION_INHERIT,
2382         LAYOUT_DIRECTION_LOCALE
2383     })
2384     @Retention(RetentionPolicy.SOURCE)
2385     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2386     public @interface LayoutDir {}
2387 
2388     /** @hide */
2389     @IntDef({
2390         LAYOUT_DIRECTION_LTR,
2391         LAYOUT_DIRECTION_RTL
2392     })
2393     @Retention(RetentionPolicy.SOURCE)
2394     public @interface ResolvedLayoutDir {}
2395 
2396     /**
2397      * A flag to indicate that the layout direction of this view has not been defined yet.
2398      * @hide
2399      */
2400     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2401 
2402     /**
2403      * Horizontal layout direction of this view is from Left to Right.
2404      * Use with {@link #setLayoutDirection}.
2405      */
2406     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2407 
2408     /**
2409      * Horizontal layout direction of this view is from Right to Left.
2410      * Use with {@link #setLayoutDirection}.
2411      */
2412     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2413 
2414     /**
2415      * Horizontal layout direction of this view is inherited from its parent.
2416      * Use with {@link #setLayoutDirection}.
2417      */
2418     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2419 
2420     /**
2421      * Horizontal layout direction of this view is from deduced from the default language
2422      * script for the locale. Use with {@link #setLayoutDirection}.
2423      */
2424     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2425 
2426     /**
2427      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2428      * @hide
2429      */
2430     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2431 
2432     /**
2433      * Mask for use with private flags indicating bits used for horizontal layout direction.
2434      * @hide
2435      */
2436     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2437 
2438     /**
2439      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2440      * right-to-left direction.
2441      * @hide
2442      */
2443     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2444 
2445     /**
2446      * Indicates whether the view horizontal layout direction has been resolved.
2447      * @hide
2448      */
2449     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2450 
2451     /**
2452      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2453      * @hide
2454      */
2455     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2456             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2457 
2458     /*
2459      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2460      * flag value.
2461      * @hide
2462      */
2463     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2464             LAYOUT_DIRECTION_LTR,
2465             LAYOUT_DIRECTION_RTL,
2466             LAYOUT_DIRECTION_INHERIT,
2467             LAYOUT_DIRECTION_LOCALE
2468     };
2469 
2470     /**
2471      * Default horizontal layout direction.
2472      */
2473     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2474 
2475     /**
2476      * Default horizontal layout direction.
2477      * @hide
2478      */
2479     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2480 
2481     /**
2482      * Text direction is inherited through {@link ViewGroup}
2483      */
2484     public static final int TEXT_DIRECTION_INHERIT = 0;
2485 
2486     /**
2487      * Text direction is using "first strong algorithm". The first strong directional character
2488      * determines the paragraph direction. If there is no strong directional character, the
2489      * paragraph direction is the view's resolved layout direction.
2490      */
2491     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2492 
2493     /**
2494      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2495      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2496      * If there are neither, the paragraph direction is the view's resolved layout direction.
2497      */
2498     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2499 
2500     /**
2501      * Text direction is forced to LTR.
2502      */
2503     public static final int TEXT_DIRECTION_LTR = 3;
2504 
2505     /**
2506      * Text direction is forced to RTL.
2507      */
2508     public static final int TEXT_DIRECTION_RTL = 4;
2509 
2510     /**
2511      * Text direction is coming from the system Locale.
2512      */
2513     public static final int TEXT_DIRECTION_LOCALE = 5;
2514 
2515     /**
2516      * Text direction is using "first strong algorithm". The first strong directional character
2517      * determines the paragraph direction. If there is no strong directional character, the
2518      * paragraph direction is LTR.
2519      */
2520     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2521 
2522     /**
2523      * Text direction is using "first strong algorithm". The first strong directional character
2524      * determines the paragraph direction. If there is no strong directional character, the
2525      * paragraph direction is RTL.
2526      */
2527     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2528 
2529     /**
2530      * Default text direction is inherited
2531      */
2532     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2533 
2534     /**
2535      * Default resolved text direction
2536      * @hide
2537      */
2538     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2539 
2540     /**
2541      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2542      * @hide
2543      */
2544     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2545 
2546     /**
2547      * Mask for use with private flags indicating bits used for text direction.
2548      * @hide
2549      */
2550     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2551             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2552 
2553     /**
2554      * Array of text direction flags for mapping attribute "textDirection" to correct
2555      * flag value.
2556      * @hide
2557      */
2558     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2559             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2560             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2561             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2562             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2563             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2564             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2565             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2566             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2567     };
2568 
2569     /**
2570      * Indicates whether the view text direction has been resolved.
2571      * @hide
2572      */
2573     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2574             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2575 
2576     /**
2577      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2578      * @hide
2579      */
2580     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2581 
2582     /**
2583      * Mask for use with private flags indicating bits used for resolved text direction.
2584      * @hide
2585      */
2586     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2587             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2588 
2589     /**
2590      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2591      * @hide
2592      */
2593     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2594             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2595 
2596     /** @hide */
2597     @IntDef({
2598         TEXT_ALIGNMENT_INHERIT,
2599         TEXT_ALIGNMENT_GRAVITY,
2600         TEXT_ALIGNMENT_CENTER,
2601         TEXT_ALIGNMENT_TEXT_START,
2602         TEXT_ALIGNMENT_TEXT_END,
2603         TEXT_ALIGNMENT_VIEW_START,
2604         TEXT_ALIGNMENT_VIEW_END
2605     })
2606     @Retention(RetentionPolicy.SOURCE)
2607     public @interface TextAlignment {}
2608 
2609     /**
2610      * Default text alignment. The text alignment of this View is inherited from its parent.
2611      * Use with {@link #setTextAlignment(int)}
2612      */
2613     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2614 
2615     /**
2616      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2617      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2618      *
2619      * Use with {@link #setTextAlignment(int)}
2620      */
2621     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2622 
2623     /**
2624      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2625      *
2626      * Use with {@link #setTextAlignment(int)}
2627      */
2628     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2629 
2630     /**
2631      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2632      *
2633      * Use with {@link #setTextAlignment(int)}
2634      */
2635     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2636 
2637     /**
2638      * Center the paragraph, e.g. ALIGN_CENTER.
2639      *
2640      * Use with {@link #setTextAlignment(int)}
2641      */
2642     public static final int TEXT_ALIGNMENT_CENTER = 4;
2643 
2644     /**
2645      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2646      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2647      *
2648      * Use with {@link #setTextAlignment(int)}
2649      */
2650     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2651 
2652     /**
2653      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2654      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2655      *
2656      * Use with {@link #setTextAlignment(int)}
2657      */
2658     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2659 
2660     /**
2661      * Default text alignment is inherited
2662      */
2663     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2664 
2665     /**
2666      * Default resolved text alignment
2667      * @hide
2668      */
2669     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2670 
2671     /**
2672       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2673       * @hide
2674       */
2675     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2676 
2677     /**
2678       * Mask for use with private flags indicating bits used for text alignment.
2679       * @hide
2680       */
2681     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2682 
2683     /**
2684      * Array of text direction flags for mapping attribute "textAlignment" to correct
2685      * flag value.
2686      * @hide
2687      */
2688     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2689             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2690             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2691             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2692             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2693             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2694             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2695             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2696     };
2697 
2698     /**
2699      * Indicates whether the view text alignment has been resolved.
2700      * @hide
2701      */
2702     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2703 
2704     /**
2705      * Bit shift to get the resolved text alignment.
2706      * @hide
2707      */
2708     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2709 
2710     /**
2711      * Mask for use with private flags indicating bits used for text alignment.
2712      * @hide
2713      */
2714     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2715             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2716 
2717     /**
2718      * Indicates whether if the view text alignment has been resolved to gravity
2719      */
2720     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2721             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2722 
2723     // Accessiblity constants for mPrivateFlags2
2724 
2725     /**
2726      * Shift for the bits in {@link #mPrivateFlags2} related to the
2727      * "importantForAccessibility" attribute.
2728      */
2729     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2730 
2731     /**
2732      * Automatically determine whether a view is important for accessibility.
2733      */
2734     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2735 
2736     /**
2737      * The view is important for accessibility.
2738      */
2739     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2740 
2741     /**
2742      * The view is not important for accessibility.
2743      */
2744     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2745 
2746     /**
2747      * The view is not important for accessibility, nor are any of its
2748      * descendant views.
2749      */
2750     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2751 
2752     /**
2753      * The default whether the view is important for accessibility.
2754      */
2755     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2756 
2757     /**
2758      * Mask for obtaining the bits which specify how to determine
2759      * whether a view is important for accessibility.
2760      */
2761     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2762         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2763         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2764         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2765 
2766     /**
2767      * Shift for the bits in {@link #mPrivateFlags2} related to the
2768      * "accessibilityLiveRegion" attribute.
2769      */
2770     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2771 
2772     /**
2773      * Live region mode specifying that accessibility services should not
2774      * automatically announce changes to this view. This is the default live
2775      * region mode for most views.
2776      * <p>
2777      * Use with {@link #setAccessibilityLiveRegion(int)}.
2778      */
2779     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2780 
2781     /**
2782      * Live region mode specifying that accessibility services should announce
2783      * changes to this view.
2784      * <p>
2785      * Use with {@link #setAccessibilityLiveRegion(int)}.
2786      */
2787     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2788 
2789     /**
2790      * Live region mode specifying that accessibility services should interrupt
2791      * ongoing speech to immediately announce changes to this view.
2792      * <p>
2793      * Use with {@link #setAccessibilityLiveRegion(int)}.
2794      */
2795     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2796 
2797     /**
2798      * The default whether the view is important for accessibility.
2799      */
2800     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2801 
2802     /**
2803      * Mask for obtaining the bits which specify a view's accessibility live
2804      * region mode.
2805      */
2806     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2807             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2808             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2809 
2810     /**
2811      * Flag indicating whether a view has accessibility focus.
2812      */
2813     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2814 
2815     /**
2816      * Flag whether the accessibility state of the subtree rooted at this view changed.
2817      */
2818     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2819 
2820     /**
2821      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2822      * is used to check whether later changes to the view's transform should invalidate the
2823      * view to force the quickReject test to run again.
2824      */
2825     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2826 
2827     /**
2828      * Flag indicating that start/end padding has been resolved into left/right padding
2829      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2830      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2831      * during measurement. In some special cases this is required such as when an adapter-based
2832      * view measures prospective children without attaching them to a window.
2833      */
2834     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2835 
2836     /**
2837      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2838      */
2839     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2840 
2841     /**
2842      * Indicates that the view is tracking some sort of transient state
2843      * that the app should not need to be aware of, but that the framework
2844      * should take special care to preserve.
2845      */
2846     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2847 
2848     /**
2849      * Group of bits indicating that RTL properties resolution is done.
2850      */
2851     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2852             PFLAG2_TEXT_DIRECTION_RESOLVED |
2853             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2854             PFLAG2_PADDING_RESOLVED |
2855             PFLAG2_DRAWABLE_RESOLVED;
2856 
2857     // There are a couple of flags left in mPrivateFlags2
2858 
2859     /* End of masks for mPrivateFlags2 */
2860 
2861     /**
2862      * Masks for mPrivateFlags3, as generated by dumpFlags():
2863      *
2864      * |-------|-------|-------|-------|
2865      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2866      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2867      *                               1   PFLAG3_IS_LAID_OUT
2868      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2869      *                             1     PFLAG3_CALLED_SUPER
2870      *                            1      PFLAG3_APPLYING_INSETS
2871      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2872      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2873      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2874      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2875      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2876      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2877      *                     1             PFLAG3_SCROLL_INDICATOR_START
2878      *                    1              PFLAG3_SCROLL_INDICATOR_END
2879      *                   1               PFLAG3_ASSIST_BLOCKED
2880      *                  1                PFLAG3_CLUSTER
2881      *                 1                 PFLAG3_IS_AUTOFILLED
2882      *                1                  PFLAG3_FINGER_DOWN
2883      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2884      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2885      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2886      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2887      *        1                          PFLAG3_TEMPORARY_DETACH
2888      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2889      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
2890      * |-------|-------|-------|-------|
2891      */
2892 
2893     /**
2894      * Flag indicating that view has a transform animation set on it. This is used to track whether
2895      * an animation is cleared between successive frames, in order to tell the associated
2896      * DisplayList to clear its animation matrix.
2897      */
2898     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2899 
2900     /**
2901      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2902      * animation is cleared between successive frames, in order to tell the associated
2903      * DisplayList to restore its alpha value.
2904      */
2905     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2906 
2907     /**
2908      * Flag indicating that the view has been through at least one layout since it
2909      * was last attached to a window.
2910      */
2911     static final int PFLAG3_IS_LAID_OUT = 0x4;
2912 
2913     /**
2914      * Flag indicating that a call to measure() was skipped and should be done
2915      * instead when layout() is invoked.
2916      */
2917     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2918 
2919     /**
2920      * Flag indicating that an overridden method correctly called down to
2921      * the superclass implementation as required by the API spec.
2922      */
2923     static final int PFLAG3_CALLED_SUPER = 0x10;
2924 
2925     /**
2926      * Flag indicating that we're in the process of applying window insets.
2927      */
2928     static final int PFLAG3_APPLYING_INSETS = 0x20;
2929 
2930     /**
2931      * Flag indicating that we're in the process of fitting system windows using the old method.
2932      */
2933     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2934 
2935     /**
2936      * Flag indicating that nested scrolling is enabled for this view.
2937      * The view will optionally cooperate with views up its parent chain to allow for
2938      * integrated nested scrolling along the same axis.
2939      */
2940     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2941 
2942     /**
2943      * Flag indicating that the bottom scroll indicator should be displayed
2944      * when this view can scroll up.
2945      */
2946     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2947 
2948     /**
2949      * Flag indicating that the bottom scroll indicator should be displayed
2950      * when this view can scroll down.
2951      */
2952     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2953 
2954     /**
2955      * Flag indicating that the left scroll indicator should be displayed
2956      * when this view can scroll left.
2957      */
2958     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2959 
2960     /**
2961      * Flag indicating that the right scroll indicator should be displayed
2962      * when this view can scroll right.
2963      */
2964     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2965 
2966     /**
2967      * Flag indicating that the start scroll indicator should be displayed
2968      * when this view can scroll in the start direction.
2969      */
2970     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2971 
2972     /**
2973      * Flag indicating that the end scroll indicator should be displayed
2974      * when this view can scroll in the end direction.
2975      */
2976     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2977 
2978     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2979 
2980     static final int SCROLL_INDICATORS_NONE = 0x0000;
2981 
2982     /**
2983      * Mask for use with setFlags indicating bits used for indicating which
2984      * scroll indicators are enabled.
2985      */
2986     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2987             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2988             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2989             | PFLAG3_SCROLL_INDICATOR_END;
2990 
2991     /**
2992      * Left-shift required to translate between public scroll indicator flags
2993      * and internal PFLAGS3 flags. When used as a right-shift, translates
2994      * PFLAGS3 flags to public flags.
2995      */
2996     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2997 
2998     /** @hide */
2999     @Retention(RetentionPolicy.SOURCE)
3000     @IntDef(flag = true,
3001             value = {
3002                     SCROLL_INDICATOR_TOP,
3003                     SCROLL_INDICATOR_BOTTOM,
3004                     SCROLL_INDICATOR_LEFT,
3005                     SCROLL_INDICATOR_RIGHT,
3006                     SCROLL_INDICATOR_START,
3007                     SCROLL_INDICATOR_END,
3008             })
3009     public @interface ScrollIndicators {}
3010 
3011     /**
3012      * Scroll indicator direction for the top edge of the view.
3013      *
3014      * @see #setScrollIndicators(int)
3015      * @see #setScrollIndicators(int, int)
3016      * @see #getScrollIndicators()
3017      */
3018     public static final int SCROLL_INDICATOR_TOP =
3019             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3020 
3021     /**
3022      * Scroll indicator direction for the bottom edge of the view.
3023      *
3024      * @see #setScrollIndicators(int)
3025      * @see #setScrollIndicators(int, int)
3026      * @see #getScrollIndicators()
3027      */
3028     public static final int SCROLL_INDICATOR_BOTTOM =
3029             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3030 
3031     /**
3032      * Scroll indicator direction for the left edge of the view.
3033      *
3034      * @see #setScrollIndicators(int)
3035      * @see #setScrollIndicators(int, int)
3036      * @see #getScrollIndicators()
3037      */
3038     public static final int SCROLL_INDICATOR_LEFT =
3039             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3040 
3041     /**
3042      * Scroll indicator direction for the right edge of the view.
3043      *
3044      * @see #setScrollIndicators(int)
3045      * @see #setScrollIndicators(int, int)
3046      * @see #getScrollIndicators()
3047      */
3048     public static final int SCROLL_INDICATOR_RIGHT =
3049             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3050 
3051     /**
3052      * Scroll indicator direction for the starting edge of the view.
3053      * <p>
3054      * Resolved according to the view's layout direction, see
3055      * {@link #getLayoutDirection()} for more information.
3056      *
3057      * @see #setScrollIndicators(int)
3058      * @see #setScrollIndicators(int, int)
3059      * @see #getScrollIndicators()
3060      */
3061     public static final int SCROLL_INDICATOR_START =
3062             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3063 
3064     /**
3065      * Scroll indicator direction for the ending edge of the view.
3066      * <p>
3067      * Resolved according to the view's layout direction, see
3068      * {@link #getLayoutDirection()} for more information.
3069      *
3070      * @see #setScrollIndicators(int)
3071      * @see #setScrollIndicators(int, int)
3072      * @see #getScrollIndicators()
3073      */
3074     public static final int SCROLL_INDICATOR_END =
3075             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3076 
3077     /**
3078      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3079      * into this view.<p>
3080      */
3081     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3082 
3083     /**
3084      * Flag indicating that the view is a root of a keyboard navigation cluster.
3085      *
3086      * @see #isKeyboardNavigationCluster()
3087      * @see #setKeyboardNavigationCluster(boolean)
3088      */
3089     private static final int PFLAG3_CLUSTER = 0x8000;
3090 
3091     /**
3092      * Flag indicating that the view is autofilled
3093      *
3094      * @see #isAutofilled()
3095      * @see #setAutofilled(boolean)
3096      */
3097     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3098 
3099     /**
3100      * Indicates that the user is currently touching the screen.
3101      * Currently used for the tooltip positioning only.
3102      */
3103     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3104 
3105     /**
3106      * Flag indicating that this view is the default-focus view.
3107      *
3108      * @see #isFocusedByDefault()
3109      * @see #setFocusedByDefault(boolean)
3110      */
3111     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3112 
3113     /**
3114      * Shift for the bits in {@link #mPrivateFlags3} related to the
3115      * "importantForAutofill" attribute.
3116      */
3117     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3118 
3119     /**
3120      * Mask for obtaining the bits which specify how to determine
3121      * whether a view is important for autofill.
3122      */
3123     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3124             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3125             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3126             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3127             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3128 
3129     /**
3130      * Whether this view has rendered elements that overlap (see {@link
3131      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3132      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3133      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3134      * determined by whatever {@link #hasOverlappingRendering()} returns.
3135      */
3136     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3137 
3138     /**
3139      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3140      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3141      */
3142     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3143 
3144     /**
3145      * Flag indicating that the view is temporarily detached from the parent view.
3146      *
3147      * @see #onStartTemporaryDetach()
3148      * @see #onFinishTemporaryDetach()
3149      */
3150     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3151 
3152     /**
3153      * Flag indicating that the view does not wish to be revealed within its parent
3154      * hierarchy when it gains focus. Expressed in the negative since the historical
3155      * default behavior is to reveal on focus; this flag suppresses that behavior.
3156      *
3157      * @see #setRevealOnFocusHint(boolean)
3158      * @see #getRevealOnFocusHint()
3159      */
3160     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3161 
3162     /**
3163      * Flag indicating that when layout is completed we should notify
3164      * that the view was entered for autofill purposes. To minimize
3165      * showing autofill for views not visible to the user we evaluate
3166      * user visibility which cannot be done until the view is laid out.
3167      */
3168     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3169 
3170     /* End of masks for mPrivateFlags3 */
3171 
3172     /**
3173      * Always allow a user to over-scroll this view, provided it is a
3174      * view that can scroll.
3175      *
3176      * @see #getOverScrollMode()
3177      * @see #setOverScrollMode(int)
3178      */
3179     public static final int OVER_SCROLL_ALWAYS = 0;
3180 
3181     /**
3182      * Allow a user to over-scroll this view only if the content is large
3183      * enough to meaningfully scroll, provided it is a view that can scroll.
3184      *
3185      * @see #getOverScrollMode()
3186      * @see #setOverScrollMode(int)
3187      */
3188     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3189 
3190     /**
3191      * Never allow a user to over-scroll this view.
3192      *
3193      * @see #getOverScrollMode()
3194      * @see #setOverScrollMode(int)
3195      */
3196     public static final int OVER_SCROLL_NEVER = 2;
3197 
3198     /**
3199      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3200      * requested the system UI (status bar) to be visible (the default).
3201      *
3202      * @see #setSystemUiVisibility(int)
3203      */
3204     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3205 
3206     /**
3207      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3208      * system UI to enter an unobtrusive "low profile" mode.
3209      *
3210      * <p>This is for use in games, book readers, video players, or any other
3211      * "immersive" application where the usual system chrome is deemed too distracting.
3212      *
3213      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3214      *
3215      * @see #setSystemUiVisibility(int)
3216      */
3217     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3218 
3219     /**
3220      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3221      * system navigation be temporarily hidden.
3222      *
3223      * <p>This is an even less obtrusive state than that called for by
3224      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3225      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3226      * those to disappear. This is useful (in conjunction with the
3227      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3228      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3229      * window flags) for displaying content using every last pixel on the display.
3230      *
3231      * <p>There is a limitation: because navigation controls are so important, the least user
3232      * interaction will cause them to reappear immediately.  When this happens, both
3233      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3234      * so that both elements reappear at the same time.
3235      *
3236      * @see #setSystemUiVisibility(int)
3237      */
3238     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3239 
3240     /**
3241      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3242      * into the normal fullscreen mode so that its content can take over the screen
3243      * while still allowing the user to interact with the application.
3244      *
3245      * <p>This has the same visual effect as
3246      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3247      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3248      * meaning that non-critical screen decorations (such as the status bar) will be
3249      * hidden while the user is in the View's window, focusing the experience on
3250      * that content.  Unlike the window flag, if you are using ActionBar in
3251      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3252      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3253      * hide the action bar.
3254      *
3255      * <p>This approach to going fullscreen is best used over the window flag when
3256      * it is a transient state -- that is, the application does this at certain
3257      * points in its user interaction where it wants to allow the user to focus
3258      * on content, but not as a continuous state.  For situations where the application
3259      * would like to simply stay full screen the entire time (such as a game that
3260      * wants to take over the screen), the
3261      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3262      * is usually a better approach.  The state set here will be removed by the system
3263      * in various situations (such as the user moving to another application) like
3264      * the other system UI states.
3265      *
3266      * <p>When using this flag, the application should provide some easy facility
3267      * for the user to go out of it.  A common example would be in an e-book
3268      * reader, where tapping on the screen brings back whatever screen and UI
3269      * decorations that had been hidden while the user was immersed in reading
3270      * the book.
3271      *
3272      * @see #setSystemUiVisibility(int)
3273      */
3274     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3275 
3276     /**
3277      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3278      * flags, we would like a stable view of the content insets given to
3279      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3280      * will always represent the worst case that the application can expect
3281      * as a continuous state.  In the stock Android UI this is the space for
3282      * the system bar, nav bar, and status bar, but not more transient elements
3283      * such as an input method.
3284      *
3285      * The stable layout your UI sees is based on the system UI modes you can
3286      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3287      * then you will get a stable layout for changes of the
3288      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3289      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3290      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3291      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3292      * with a stable layout.  (Note that you should avoid using
3293      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3294      *
3295      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3296      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3297      * then a hidden status bar will be considered a "stable" state for purposes
3298      * here.  This allows your UI to continually hide the status bar, while still
3299      * using the system UI flags to hide the action bar while still retaining
3300      * a stable layout.  Note that changing the window fullscreen flag will never
3301      * provide a stable layout for a clean transition.
3302      *
3303      * <p>If you are using ActionBar in
3304      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3305      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3306      * insets it adds to those given to the application.
3307      */
3308     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3309 
3310     /**
3311      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3312      * to be laid out as if it has requested
3313      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3314      * allows it to avoid artifacts when switching in and out of that mode, at
3315      * the expense that some of its user interface may be covered by screen
3316      * decorations when they are shown.  You can perform layout of your inner
3317      * UI elements to account for the navigation system UI through the
3318      * {@link #fitSystemWindows(Rect)} method.
3319      */
3320     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3321 
3322     /**
3323      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3324      * to be laid out as if it has requested
3325      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3326      * allows it to avoid artifacts when switching in and out of that mode, at
3327      * the expense that some of its user interface may be covered by screen
3328      * decorations when they are shown.  You can perform layout of your inner
3329      * UI elements to account for non-fullscreen system UI through the
3330      * {@link #fitSystemWindows(Rect)} method.
3331      */
3332     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3333 
3334     /**
3335      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3336      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3337      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3338      * user interaction.
3339      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3340      * has an effect when used in combination with that flag.</p>
3341      */
3342     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3343 
3344     /**
3345      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3346      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3347      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3348      * experience while also hiding the system bars.  If this flag is not set,
3349      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3350      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3351      * if the user swipes from the top of the screen.
3352      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3353      * system gestures, such as swiping from the top of the screen.  These transient system bars
3354      * will overlay app’s content, may have some degree of transparency, and will automatically
3355      * hide after a short timeout.
3356      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3357      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3358      * with one or both of those flags.</p>
3359      */
3360     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3361 
3362     /**
3363      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3364      * is compatible with light status bar backgrounds.
3365      *
3366      * <p>For this to take effect, the window must request
3367      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3368      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3369      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3370      *         FLAG_TRANSLUCENT_STATUS}.
3371      *
3372      * @see android.R.attr#windowLightStatusBar
3373      */
3374     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3375 
3376     /**
3377      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3378      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3379      */
3380     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3381 
3382     /**
3383      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3384      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3385      */
3386     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3387 
3388     /**
3389      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3390      * that is compatible with light navigation bar backgrounds.
3391      *
3392      * <p>For this to take effect, the window must request
3393      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3394      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3395      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3396      *         FLAG_TRANSLUCENT_NAVIGATION}.
3397      */
3398     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3399 
3400     /**
3401      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3402      */
3403     @Deprecated
3404     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3405 
3406     /**
3407      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3408      */
3409     @Deprecated
3410     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3411 
3412     /**
3413      * @hide
3414      *
3415      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3416      * out of the public fields to keep the undefined bits out of the developer's way.
3417      *
3418      * Flag to make the status bar not expandable.  Unless you also
3419      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3420      */
3421     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3422 
3423     /**
3424      * @hide
3425      *
3426      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3427      * out of the public fields to keep the undefined bits out of the developer's way.
3428      *
3429      * Flag to hide notification icons and scrolling ticker text.
3430      */
3431     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3432 
3433     /**
3434      * @hide
3435      *
3436      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3437      * out of the public fields to keep the undefined bits out of the developer's way.
3438      *
3439      * Flag to disable incoming notification alerts.  This will not block
3440      * icons, but it will block sound, vibrating and other visual or aural notifications.
3441      */
3442     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3443 
3444     /**
3445      * @hide
3446      *
3447      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3448      * out of the public fields to keep the undefined bits out of the developer's way.
3449      *
3450      * Flag to hide only the scrolling ticker.  Note that
3451      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3452      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3453      */
3454     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3455 
3456     /**
3457      * @hide
3458      *
3459      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3460      * out of the public fields to keep the undefined bits out of the developer's way.
3461      *
3462      * Flag to hide the center system info area.
3463      */
3464     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3465 
3466     /**
3467      * @hide
3468      *
3469      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3470      * out of the public fields to keep the undefined bits out of the developer's way.
3471      *
3472      * Flag to hide only the home button.  Don't use this
3473      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3474      */
3475     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3476 
3477     /**
3478      * @hide
3479      *
3480      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3481      * out of the public fields to keep the undefined bits out of the developer's way.
3482      *
3483      * Flag to hide only the back button. Don't use this
3484      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3485      */
3486     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3487 
3488     /**
3489      * @hide
3490      *
3491      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3492      * out of the public fields to keep the undefined bits out of the developer's way.
3493      *
3494      * Flag to hide only the clock.  You might use this if your activity has
3495      * its own clock making the status bar's clock redundant.
3496      */
3497     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3498 
3499     /**
3500      * @hide
3501      *
3502      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3503      * out of the public fields to keep the undefined bits out of the developer's way.
3504      *
3505      * Flag to hide only the recent apps button. Don't use this
3506      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3507      */
3508     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3509 
3510     /**
3511      * @hide
3512      *
3513      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3514      * out of the public fields to keep the undefined bits out of the developer's way.
3515      *
3516      * Flag to disable the global search gesture. Don't use this
3517      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3518      */
3519     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3520 
3521     /**
3522      * @hide
3523      *
3524      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3525      * out of the public fields to keep the undefined bits out of the developer's way.
3526      *
3527      * Flag to specify that the status bar is displayed in transient mode.
3528      */
3529     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3530 
3531     /**
3532      * @hide
3533      *
3534      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3535      * out of the public fields to keep the undefined bits out of the developer's way.
3536      *
3537      * Flag to specify that the navigation bar is displayed in transient mode.
3538      */
3539     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3540 
3541     /**
3542      * @hide
3543      *
3544      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3545      * out of the public fields to keep the undefined bits out of the developer's way.
3546      *
3547      * Flag to specify that the hidden status bar would like to be shown.
3548      */
3549     public static final int STATUS_BAR_UNHIDE = 0x10000000;
3550 
3551     /**
3552      * @hide
3553      *
3554      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3555      * out of the public fields to keep the undefined bits out of the developer's way.
3556      *
3557      * Flag to specify that the hidden navigation bar would like to be shown.
3558      */
3559     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
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 specify that the status bar is displayed in translucent mode.
3568      */
3569     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
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 specify that the navigation bar is displayed in translucent mode.
3578      */
3579     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3580 
3581     /**
3582      * @hide
3583      *
3584      * Makes navigation bar transparent (but not the status bar).
3585      */
3586     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3587 
3588     /**
3589      * @hide
3590      *
3591      * Makes status bar transparent (but not the navigation bar).
3592      */
3593     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3594 
3595     /**
3596      * @hide
3597      *
3598      * Makes both status bar and navigation bar transparent.
3599      */
3600     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3601             | STATUS_BAR_TRANSPARENT;
3602 
3603     /**
3604      * @hide
3605      */
3606     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3607 
3608     /**
3609      * These are the system UI flags that can be cleared by events outside
3610      * of an application.  Currently this is just the ability to tap on the
3611      * screen while hiding the navigation bar to have it return.
3612      * @hide
3613      */
3614     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3615             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3616             | SYSTEM_UI_FLAG_FULLSCREEN;
3617 
3618     /**
3619      * Flags that can impact the layout in relation to system UI.
3620      */
3621     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3622             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3623             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3624 
3625     /** @hide */
3626     @IntDef(flag = true,
3627             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3628     @Retention(RetentionPolicy.SOURCE)
3629     public @interface FindViewFlags {}
3630 
3631     /**
3632      * Find views that render the specified text.
3633      *
3634      * @see #findViewsWithText(ArrayList, CharSequence, int)
3635      */
3636     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3637 
3638     /**
3639      * Find find views that contain the specified content description.
3640      *
3641      * @see #findViewsWithText(ArrayList, CharSequence, int)
3642      */
3643     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3644 
3645     /**
3646      * Find views that contain {@link AccessibilityNodeProvider}. Such
3647      * a View is a root of virtual view hierarchy and may contain the searched
3648      * text. If this flag is set Views with providers are automatically
3649      * added and it is a responsibility of the client to call the APIs of
3650      * the provider to determine whether the virtual tree rooted at this View
3651      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3652      * representing the virtual views with this text.
3653      *
3654      * @see #findViewsWithText(ArrayList, CharSequence, int)
3655      *
3656      * @hide
3657      */
3658     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3659 
3660     /**
3661      * The undefined cursor position.
3662      *
3663      * @hide
3664      */
3665     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3666 
3667     /**
3668      * Indicates that the screen has changed state and is now off.
3669      *
3670      * @see #onScreenStateChanged(int)
3671      */
3672     public static final int SCREEN_STATE_OFF = 0x0;
3673 
3674     /**
3675      * Indicates that the screen has changed state and is now on.
3676      *
3677      * @see #onScreenStateChanged(int)
3678      */
3679     public static final int SCREEN_STATE_ON = 0x1;
3680 
3681     /**
3682      * Indicates no axis of view scrolling.
3683      */
3684     public static final int SCROLL_AXIS_NONE = 0;
3685 
3686     /**
3687      * Indicates scrolling along the horizontal axis.
3688      */
3689     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3690 
3691     /**
3692      * Indicates scrolling along the vertical axis.
3693      */
3694     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3695 
3696     /**
3697      * Controls the over-scroll mode for this view.
3698      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3699      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3700      * and {@link #OVER_SCROLL_NEVER}.
3701      */
3702     private int mOverScrollMode;
3703 
3704     /**
3705      * The parent this view is attached to.
3706      * {@hide}
3707      *
3708      * @see #getParent()
3709      */
3710     protected ViewParent mParent;
3711 
3712     /**
3713      * {@hide}
3714      */
3715     AttachInfo mAttachInfo;
3716 
3717     /**
3718      * {@hide}
3719      */
3720     @ViewDebug.ExportedProperty(flagMapping = {
3721         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3722                 name = "FORCE_LAYOUT"),
3723         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3724                 name = "LAYOUT_REQUIRED"),
3725         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3726             name = "DRAWING_CACHE_INVALID", outputIf = false),
3727         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3728         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3729         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3730         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3731     }, formatToHexString = true)
3732 
3733     /* @hide */
3734     public int mPrivateFlags;
3735     int mPrivateFlags2;
3736     int mPrivateFlags3;
3737 
3738     /**
3739      * This view's request for the visibility of the status bar.
3740      * @hide
3741      */
3742     @ViewDebug.ExportedProperty(flagMapping = {
3743         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3744                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3745                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3746         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3747                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3748                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3749         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3750                                 equals = SYSTEM_UI_FLAG_VISIBLE,
3751                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3752     }, formatToHexString = true)
3753     int mSystemUiVisibility;
3754 
3755     /**
3756      * Reference count for transient state.
3757      * @see #setHasTransientState(boolean)
3758      */
3759     int mTransientStateCount = 0;
3760 
3761     /**
3762      * Count of how many windows this view has been attached to.
3763      */
3764     int mWindowAttachCount;
3765 
3766     /**
3767      * The layout parameters associated with this view and used by the parent
3768      * {@link android.view.ViewGroup} to determine how this view should be
3769      * laid out.
3770      * {@hide}
3771      */
3772     protected ViewGroup.LayoutParams mLayoutParams;
3773 
3774     /**
3775      * The view flags hold various views states.
3776      * {@hide}
3777      */
3778     @ViewDebug.ExportedProperty(formatToHexString = true)
3779     int mViewFlags;
3780 
3781     static class TransformationInfo {
3782         /**
3783          * The transform matrix for the View. This transform is calculated internally
3784          * based on the translation, rotation, and scale properties.
3785          *
3786          * Do *not* use this variable directly; instead call getMatrix(), which will
3787          * load the value from the View's RenderNode.
3788          */
3789         private final Matrix mMatrix = new Matrix();
3790 
3791         /**
3792          * The inverse transform matrix for the View. This transform is calculated
3793          * internally based on the translation, rotation, and scale properties.
3794          *
3795          * Do *not* use this variable directly; instead call getInverseMatrix(),
3796          * which will load the value from the View's RenderNode.
3797          */
3798         private Matrix mInverseMatrix;
3799 
3800         /**
3801          * The opacity of the View. This is a value from 0 to 1, where 0 means
3802          * completely transparent and 1 means completely opaque.
3803          */
3804         @ViewDebug.ExportedProperty
3805         float mAlpha = 1f;
3806 
3807         /**
3808          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3809          * property only used by transitions, which is composited with the other alpha
3810          * values to calculate the final visual alpha value.
3811          */
3812         float mTransitionAlpha = 1f;
3813     }
3814 
3815     /** @hide */
3816     public TransformationInfo mTransformationInfo;
3817 
3818     /**
3819      * Current clip bounds. to which all drawing of this view are constrained.
3820      */
3821     Rect mClipBounds = null;
3822 
3823     private boolean mLastIsOpaque;
3824 
3825     /**
3826      * The distance in pixels from the left edge of this view's parent
3827      * to the left edge of this view.
3828      * {@hide}
3829      */
3830     @ViewDebug.ExportedProperty(category = "layout")
3831     protected int mLeft;
3832     /**
3833      * The distance in pixels from the left edge of this view's parent
3834      * to the right edge of this view.
3835      * {@hide}
3836      */
3837     @ViewDebug.ExportedProperty(category = "layout")
3838     protected int mRight;
3839     /**
3840      * The distance in pixels from the top edge of this view's parent
3841      * to the top edge of this view.
3842      * {@hide}
3843      */
3844     @ViewDebug.ExportedProperty(category = "layout")
3845     protected int mTop;
3846     /**
3847      * The distance in pixels from the top edge of this view's parent
3848      * to the bottom edge of this view.
3849      * {@hide}
3850      */
3851     @ViewDebug.ExportedProperty(category = "layout")
3852     protected int mBottom;
3853 
3854     /**
3855      * The offset, in pixels, by which the content of this view is scrolled
3856      * horizontally.
3857      * {@hide}
3858      */
3859     @ViewDebug.ExportedProperty(category = "scrolling")
3860     protected int mScrollX;
3861     /**
3862      * The offset, in pixels, by which the content of this view is scrolled
3863      * vertically.
3864      * {@hide}
3865      */
3866     @ViewDebug.ExportedProperty(category = "scrolling")
3867     protected int mScrollY;
3868 
3869     /**
3870      * The left padding in pixels, that is the distance in pixels between the
3871      * left edge of this view and the left edge of its content.
3872      * {@hide}
3873      */
3874     @ViewDebug.ExportedProperty(category = "padding")
3875     protected int mPaddingLeft = 0;
3876     /**
3877      * The right padding in pixels, that is the distance in pixels between the
3878      * right edge of this view and the right edge of its content.
3879      * {@hide}
3880      */
3881     @ViewDebug.ExportedProperty(category = "padding")
3882     protected int mPaddingRight = 0;
3883     /**
3884      * The top padding in pixels, that is the distance in pixels between the
3885      * top edge of this view and the top edge of its content.
3886      * {@hide}
3887      */
3888     @ViewDebug.ExportedProperty(category = "padding")
3889     protected int mPaddingTop;
3890     /**
3891      * The bottom padding in pixels, that is the distance in pixels between the
3892      * bottom edge of this view and the bottom edge of its content.
3893      * {@hide}
3894      */
3895     @ViewDebug.ExportedProperty(category = "padding")
3896     protected int mPaddingBottom;
3897 
3898     /**
3899      * The layout insets in pixels, that is the distance in pixels between the
3900      * visible edges of this view its bounds.
3901      */
3902     private Insets mLayoutInsets;
3903 
3904     /**
3905      * Briefly describes the view and is primarily used for accessibility support.
3906      */
3907     private CharSequence mContentDescription;
3908 
3909     /**
3910      * Specifies the id of a view for which this view serves as a label for
3911      * accessibility purposes.
3912      */
3913     private int mLabelForId = View.NO_ID;
3914 
3915     /**
3916      * Predicate for matching labeled view id with its label for
3917      * accessibility purposes.
3918      */
3919     private MatchLabelForPredicate mMatchLabelForPredicate;
3920 
3921     /**
3922      * Specifies a view before which this one is visited in accessibility traversal.
3923      */
3924     private int mAccessibilityTraversalBeforeId = NO_ID;
3925 
3926     /**
3927      * Specifies a view after which this one is visited in accessibility traversal.
3928      */
3929     private int mAccessibilityTraversalAfterId = NO_ID;
3930 
3931     /**
3932      * Predicate for matching a view by its id.
3933      */
3934     private MatchIdPredicate mMatchIdPredicate;
3935 
3936     /**
3937      * Cache the paddingRight set by the user to append to the scrollbar's size.
3938      *
3939      * @hide
3940      */
3941     @ViewDebug.ExportedProperty(category = "padding")
3942     protected int mUserPaddingRight;
3943 
3944     /**
3945      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3946      *
3947      * @hide
3948      */
3949     @ViewDebug.ExportedProperty(category = "padding")
3950     protected int mUserPaddingBottom;
3951 
3952     /**
3953      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3954      *
3955      * @hide
3956      */
3957     @ViewDebug.ExportedProperty(category = "padding")
3958     protected int mUserPaddingLeft;
3959 
3960     /**
3961      * Cache the paddingStart set by the user to append to the scrollbar's size.
3962      *
3963      */
3964     @ViewDebug.ExportedProperty(category = "padding")
3965     int mUserPaddingStart;
3966 
3967     /**
3968      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3969      *
3970      */
3971     @ViewDebug.ExportedProperty(category = "padding")
3972     int mUserPaddingEnd;
3973 
3974     /**
3975      * Cache initial left padding.
3976      *
3977      * @hide
3978      */
3979     int mUserPaddingLeftInitial;
3980 
3981     /**
3982      * Cache initial right padding.
3983      *
3984      * @hide
3985      */
3986     int mUserPaddingRightInitial;
3987 
3988     /**
3989      * Default undefined padding
3990      */
3991     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3992 
3993     /**
3994      * Cache if a left padding has been defined
3995      */
3996     private boolean mLeftPaddingDefined = false;
3997 
3998     /**
3999      * Cache if a right padding has been defined
4000      */
4001     private boolean mRightPaddingDefined = false;
4002 
4003     /**
4004      * @hide
4005      */
4006     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4007     /**
4008      * @hide
4009      */
4010     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4011 
4012     private LongSparseLongArray mMeasureCache;
4013 
4014     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4015     private Drawable mBackground;
4016     private TintInfo mBackgroundTint;
4017 
4018     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4019     private ForegroundInfo mForegroundInfo;
4020 
4021     private Drawable mScrollIndicatorDrawable;
4022 
4023     /**
4024      * RenderNode used for backgrounds.
4025      * <p>
4026      * When non-null and valid, this is expected to contain an up-to-date copy
4027      * of the background drawable. It is cleared on temporary detach, and reset
4028      * on cleanup.
4029      */
4030     private RenderNode mBackgroundRenderNode;
4031 
4032     private int mBackgroundResource;
4033     private boolean mBackgroundSizeChanged;
4034 
4035     /** The default focus highlight.
4036      * @see #mDefaultFocusHighlightEnabled
4037      * @see Drawable#hasFocusStateSpecified()
4038      */
4039     private Drawable mDefaultFocusHighlight;
4040     private Drawable mDefaultFocusHighlightCache;
4041     private boolean mDefaultFocusHighlightSizeChanged;
4042     /**
4043      * True if the default focus highlight is needed on the target device.
4044      */
4045     private static boolean sUseDefaultFocusHighlight;
4046 
4047     private String mTransitionName;
4048 
4049     static class TintInfo {
4050         ColorStateList mTintList;
4051         PorterDuff.Mode mTintMode;
4052         boolean mHasTintMode;
4053         boolean mHasTintList;
4054     }
4055 
4056     private static class ForegroundInfo {
4057         private Drawable mDrawable;
4058         private TintInfo mTintInfo;
4059         private int mGravity = Gravity.FILL;
4060         private boolean mInsidePadding = true;
4061         private boolean mBoundsChanged = true;
4062         private final Rect mSelfBounds = new Rect();
4063         private final Rect mOverlayBounds = new Rect();
4064     }
4065 
4066     static class ListenerInfo {
4067         /**
4068          * Listener used to dispatch focus change events.
4069          * This field should be made private, so it is hidden from the SDK.
4070          * {@hide}
4071          */
4072         protected OnFocusChangeListener mOnFocusChangeListener;
4073 
4074         /**
4075          * Listeners for layout change events.
4076          */
4077         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4078 
4079         protected OnScrollChangeListener mOnScrollChangeListener;
4080 
4081         /**
4082          * Listeners for attach events.
4083          */
4084         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4085 
4086         /**
4087          * Listener used to dispatch click events.
4088          * This field should be made private, so it is hidden from the SDK.
4089          * {@hide}
4090          */
4091         public OnClickListener mOnClickListener;
4092 
4093         /**
4094          * Listener used to dispatch long click events.
4095          * This field should be made private, so it is hidden from the SDK.
4096          * {@hide}
4097          */
4098         protected OnLongClickListener mOnLongClickListener;
4099 
4100         /**
4101          * Listener used to dispatch context click events. This field should be made private, so it
4102          * is hidden from the SDK.
4103          * {@hide}
4104          */
4105         protected OnContextClickListener mOnContextClickListener;
4106 
4107         /**
4108          * Listener used to build the context menu.
4109          * This field should be made private, so it is hidden from the SDK.
4110          * {@hide}
4111          */
4112         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4113 
4114         private OnKeyListener mOnKeyListener;
4115 
4116         private OnTouchListener mOnTouchListener;
4117 
4118         private OnHoverListener mOnHoverListener;
4119 
4120         private OnGenericMotionListener mOnGenericMotionListener;
4121 
4122         private OnDragListener mOnDragListener;
4123 
4124         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4125 
4126         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4127 
4128         OnCapturedPointerListener mOnCapturedPointerListener;
4129     }
4130 
4131     ListenerInfo mListenerInfo;
4132 
4133     private static class TooltipInfo {
4134         /**
4135          * Text to be displayed in a tooltip popup.
4136          */
4137         @Nullable
4138         CharSequence mTooltipText;
4139 
4140         /**
4141          * View-relative position of the tooltip anchor point.
4142          */
4143         int mAnchorX;
4144         int mAnchorY;
4145 
4146         /**
4147          * The tooltip popup.
4148          */
4149         @Nullable
4150         TooltipPopup mTooltipPopup;
4151 
4152         /**
4153          * Set to true if the tooltip was shown as a result of a long click.
4154          */
4155         boolean mTooltipFromLongClick;
4156 
4157         /**
4158          * Keep these Runnables so that they can be used to reschedule.
4159          */
4160         Runnable mShowTooltipRunnable;
4161         Runnable mHideTooltipRunnable;
4162     }
4163 
4164     TooltipInfo mTooltipInfo;
4165 
4166     // Temporary values used to hold (x,y) coordinates when delegating from the
4167     // two-arg performLongClick() method to the legacy no-arg version.
4168     private float mLongClickX = Float.NaN;
4169     private float mLongClickY = Float.NaN;
4170 
4171     /**
4172      * The application environment this view lives in.
4173      * This field should be made private, so it is hidden from the SDK.
4174      * {@hide}
4175      */
4176     @ViewDebug.ExportedProperty(deepExport = true)
4177     protected Context mContext;
4178 
4179     private final Resources mResources;
4180 
4181     private ScrollabilityCache mScrollCache;
4182 
4183     private int[] mDrawableState = null;
4184 
4185     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4186 
4187     /**
4188      * Animator that automatically runs based on state changes.
4189      */
4190     private StateListAnimator mStateListAnimator;
4191 
4192     /**
4193      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4194      * the user may specify which view to go to next.
4195      */
4196     private int mNextFocusLeftId = View.NO_ID;
4197 
4198     /**
4199      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4200      * the user may specify which view to go to next.
4201      */
4202     private int mNextFocusRightId = View.NO_ID;
4203 
4204     /**
4205      * When this view has focus and the next focus is {@link #FOCUS_UP},
4206      * the user may specify which view to go to next.
4207      */
4208     private int mNextFocusUpId = View.NO_ID;
4209 
4210     /**
4211      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4212      * the user may specify which view to go to next.
4213      */
4214     private int mNextFocusDownId = View.NO_ID;
4215 
4216     /**
4217      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4218      * the user may specify which view to go to next.
4219      */
4220     int mNextFocusForwardId = View.NO_ID;
4221 
4222     /**
4223      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4224      *
4225      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4226      */
4227     int mNextClusterForwardId = View.NO_ID;
4228 
4229     /**
4230      * Whether this View should use a default focus highlight when it gets focused but doesn't
4231      * have {@link android.R.attr#state_focused} defined in its background.
4232      */
4233     boolean mDefaultFocusHighlightEnabled = true;
4234 
4235     private CheckForLongPress mPendingCheckForLongPress;
4236     private CheckForTap mPendingCheckForTap = null;
4237     private PerformClick mPerformClick;
4238     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4239 
4240     private UnsetPressedState mUnsetPressedState;
4241 
4242     /**
4243      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4244      * up event while a long press is invoked as soon as the long press duration is reached, so
4245      * a long press could be performed before the tap is checked, in which case the tap's action
4246      * should not be invoked.
4247      */
4248     private boolean mHasPerformedLongPress;
4249 
4250     /**
4251      * Whether a context click button is currently pressed down. This is true when the stylus is
4252      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4253      * pressed. This is false once the button is released or if the stylus has been lifted.
4254      */
4255     private boolean mInContextButtonPress;
4256 
4257     /**
4258      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4259      * true after a stylus button press has occured, when the next up event should not be recognized
4260      * as a tap.
4261      */
4262     private boolean mIgnoreNextUpEvent;
4263 
4264     /**
4265      * The minimum height of the view. We'll try our best to have the height
4266      * of this view to at least this amount.
4267      */
4268     @ViewDebug.ExportedProperty(category = "measurement")
4269     private int mMinHeight;
4270 
4271     /**
4272      * The minimum width of the view. We'll try our best to have the width
4273      * of this view to at least this amount.
4274      */
4275     @ViewDebug.ExportedProperty(category = "measurement")
4276     private int mMinWidth;
4277 
4278     /**
4279      * The delegate to handle touch events that are physically in this view
4280      * but should be handled by another view.
4281      */
4282     private TouchDelegate mTouchDelegate = null;
4283 
4284     /**
4285      * Solid color to use as a background when creating the drawing cache. Enables
4286      * the cache to use 16 bit bitmaps instead of 32 bit.
4287      */
4288     private int mDrawingCacheBackgroundColor = 0;
4289 
4290     /**
4291      * Special tree observer used when mAttachInfo is null.
4292      */
4293     private ViewTreeObserver mFloatingTreeObserver;
4294 
4295     /**
4296      * Cache the touch slop from the context that created the view.
4297      */
4298     private int mTouchSlop;
4299 
4300     /**
4301      * Object that handles automatic animation of view properties.
4302      */
4303     private ViewPropertyAnimator mAnimator = null;
4304 
4305     /**
4306      * List of registered FrameMetricsObservers.
4307      */
4308     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4309 
4310     /**
4311      * Flag indicating that a drag can cross window boundaries.  When
4312      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4313      * with this flag set, all visible applications with targetSdkVersion >=
4314      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4315      * in the drag operation and receive the dragged content.
4316      *
4317      * <p>If this is the only flag set, then the drag recipient will only have access to text data
4318      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4319      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4320      */
4321     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4322 
4323     /**
4324      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4325      * request read access to the content URI(s) contained in the {@link ClipData} object.
4326      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4327      */
4328     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4329 
4330     /**
4331      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4332      * request write access to the content URI(s) contained in the {@link ClipData} object.
4333      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4334      */
4335     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4336 
4337     /**
4338      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4339      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4340      * reboots until explicitly revoked with
4341      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4342      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4343      */
4344     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4345             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4346 
4347     /**
4348      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4349      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4350      * match against the original granted URI.
4351      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4352      */
4353     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4354             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4355 
4356     /**
4357      * Flag indicating that the drag shadow will be opaque.  When
4358      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4359      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4360      */
4361     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4362 
4363     /**
4364      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4365      */
4366     private float mVerticalScrollFactor;
4367 
4368     /**
4369      * Position of the vertical scroll bar.
4370      */
4371     private int mVerticalScrollbarPosition;
4372 
4373     /**
4374      * Position the scroll bar at the default position as determined by the system.
4375      */
4376     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4377 
4378     /**
4379      * Position the scroll bar along the left edge.
4380      */
4381     public static final int SCROLLBAR_POSITION_LEFT = 1;
4382 
4383     /**
4384      * Position the scroll bar along the right edge.
4385      */
4386     public static final int SCROLLBAR_POSITION_RIGHT = 2;
4387 
4388     /**
4389      * Indicates that the view does not have a layer.
4390      *
4391      * @see #getLayerType()
4392      * @see #setLayerType(int, android.graphics.Paint)
4393      * @see #LAYER_TYPE_SOFTWARE
4394      * @see #LAYER_TYPE_HARDWARE
4395      */
4396     public static final int LAYER_TYPE_NONE = 0;
4397 
4398     /**
4399      * <p>Indicates that the view has a software layer. A software layer is backed
4400      * by a bitmap and causes the view to be rendered using Android's software
4401      * rendering pipeline, even if hardware acceleration is enabled.</p>
4402      *
4403      * <p>Software layers have various usages:</p>
4404      * <p>When the application is not using hardware acceleration, a software layer
4405      * is useful to apply a specific color filter and/or blending mode and/or
4406      * translucency to a view and all its children.</p>
4407      * <p>When the application is using hardware acceleration, a software layer
4408      * is useful to render drawing primitives not supported by the hardware
4409      * accelerated pipeline. It can also be used to cache a complex view tree
4410      * into a texture and reduce the complexity of drawing operations. For instance,
4411      * when animating a complex view tree with a translation, a software layer can
4412      * be used to render the view tree only once.</p>
4413      * <p>Software layers should be avoided when the affected view tree updates
4414      * often. Every update will require to re-render the software layer, which can
4415      * potentially be slow (particularly when hardware acceleration is turned on
4416      * since the layer will have to be uploaded into a hardware texture after every
4417      * update.)</p>
4418      *
4419      * @see #getLayerType()
4420      * @see #setLayerType(int, android.graphics.Paint)
4421      * @see #LAYER_TYPE_NONE
4422      * @see #LAYER_TYPE_HARDWARE
4423      */
4424     public static final int LAYER_TYPE_SOFTWARE = 1;
4425 
4426     /**
4427      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4428      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4429      * OpenGL hardware) and causes the view to be rendered using Android's hardware
4430      * rendering pipeline, but only if hardware acceleration is turned on for the
4431      * view hierarchy. When hardware acceleration is turned off, hardware layers
4432      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4433      *
4434      * <p>A hardware layer is useful to apply a specific color filter and/or
4435      * blending mode and/or translucency to a view and all its children.</p>
4436      * <p>A hardware layer can be used to cache a complex view tree into a
4437      * texture and reduce the complexity of drawing operations. For instance,
4438      * when animating a complex view tree with a translation, a hardware layer can
4439      * be used to render the view tree only once.</p>
4440      * <p>A hardware layer can also be used to increase the rendering quality when
4441      * rotation transformations are applied on a view. It can also be used to
4442      * prevent potential clipping issues when applying 3D transforms on a view.</p>
4443      *
4444      * @see #getLayerType()
4445      * @see #setLayerType(int, android.graphics.Paint)
4446      * @see #LAYER_TYPE_NONE
4447      * @see #LAYER_TYPE_SOFTWARE
4448      */
4449     public static final int LAYER_TYPE_HARDWARE = 2;
4450 
4451     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4452             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4453             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4454             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4455     })
4456     int mLayerType = LAYER_TYPE_NONE;
4457     Paint mLayerPaint;
4458 
4459     /**
4460      * Set to true when drawing cache is enabled and cannot be created.
4461      *
4462      * @hide
4463      */
4464     public boolean mCachingFailed;
4465     private Bitmap mDrawingCache;
4466     private Bitmap mUnscaledDrawingCache;
4467 
4468     /**
4469      * RenderNode holding View properties, potentially holding a DisplayList of View content.
4470      * <p>
4471      * When non-null and valid, this is expected to contain an up-to-date copy
4472      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4473      * cleanup.
4474      */
4475     final RenderNode mRenderNode;
4476 
4477     /**
4478      * Set to true when the view is sending hover accessibility events because it
4479      * is the innermost hovered view.
4480      */
4481     private boolean mSendingHoverAccessibilityEvents;
4482 
4483     /**
4484      * Delegate for injecting accessibility functionality.
4485      */
4486     AccessibilityDelegate mAccessibilityDelegate;
4487 
4488     /**
4489      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4490      * and add/remove objects to/from the overlay directly through the Overlay methods.
4491      */
4492     ViewOverlay mOverlay;
4493 
4494     /**
4495      * The currently active parent view for receiving delegated nested scrolling events.
4496      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4497      * by {@link #stopNestedScroll()} at the same point where we clear
4498      * requestDisallowInterceptTouchEvent.
4499      */
4500     private ViewParent mNestedScrollingParent;
4501 
4502     /**
4503      * Consistency verifier for debugging purposes.
4504      * @hide
4505      */
4506     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4507             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4508                     new InputEventConsistencyVerifier(this, 0) : null;
4509 
4510     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4511 
4512     private int[] mTempNestedScrollConsumed;
4513 
4514     /**
4515      * An overlay is going to draw this View instead of being drawn as part of this
4516      * View's parent. mGhostView is the View in the Overlay that must be invalidated
4517      * when this view is invalidated.
4518      */
4519     GhostView mGhostView;
4520 
4521     /**
4522      * Holds pairs of adjacent attribute data: attribute name followed by its value.
4523      * @hide
4524      */
4525     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4526     public String[] mAttributes;
4527 
4528     /**
4529      * Maps a Resource id to its name.
4530      */
4531     private static SparseArray<String> mAttributeMap;
4532 
4533     /**
4534      * Queue of pending runnables. Used to postpone calls to post() until this
4535      * view is attached and has a handler.
4536      */
4537     private HandlerActionQueue mRunQueue;
4538 
4539     /**
4540      * The pointer icon when the mouse hovers on this view. The default is null.
4541      */
4542     private PointerIcon mPointerIcon;
4543 
4544     /**
4545      * @hide
4546      */
4547     String mStartActivityRequestWho;
4548 
4549     @Nullable
4550     private RoundScrollbarRenderer mRoundScrollbarRenderer;
4551 
4552     /** Used to delay visibility updates sent to the autofill manager */
4553     private Handler mVisibilityChangeForAutofillHandler;
4554 
4555     /**
4556      * Simple constructor to use when creating a view from code.
4557      *
4558      * @param context The Context the view is running in, through which it can
4559      *        access the current theme, resources, etc.
4560      */
View(Context context)4561     public View(Context context) {
4562         mContext = context;
4563         mResources = context != null ? context.getResources() : null;
4564         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4565         // Set some flags defaults
4566         mPrivateFlags2 =
4567                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4568                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4569                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4570                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4571                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4572                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4573         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4574         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4575         mUserPaddingStart = UNDEFINED_PADDING;
4576         mUserPaddingEnd = UNDEFINED_PADDING;
4577         mRenderNode = RenderNode.create(getClass().getName(), this);
4578 
4579         if (!sCompatibilityDone && context != null) {
4580             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4581 
4582             // Older apps may need this compatibility hack for measurement.
4583             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4584 
4585             // Older apps expect onMeasure() to always be called on a layout pass, regardless
4586             // of whether a layout was requested on that View.
4587             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4588 
4589             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4590             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
4591 
4592             // In M and newer, our widgets can pass a "hint" value in the size
4593             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4594             // know what the expected parent size is going to be, so e.g. list items can size
4595             // themselves at 1/3 the size of their container. It breaks older apps though,
4596             // specifically apps that use some popular open source libraries.
4597             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4598 
4599             // Old versions of the platform would give different results from
4600             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4601             // modes, so we always need to run an additional EXACTLY pass.
4602             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4603 
4604             // Prior to N, layout params could change without requiring a
4605             // subsequent call to setLayoutParams() and they would usually
4606             // work. Partial layout breaks this assumption.
4607             sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4608 
4609             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4610             // On N+, we throw, but that breaks compatibility with apps that use these methods.
4611             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4612 
4613             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4614             // in apps so we target check it to avoid breaking existing apps.
4615             sPreserveMarginParamsInLayoutParamConversion =
4616                     targetSdkVersion >= Build.VERSION_CODES.N;
4617 
4618             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4619 
4620             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4621 
4622             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4623 
4624             sUseDefaultFocusHighlight = context.getResources().getBoolean(
4625                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
4626 
4627             sCompatibilityDone = true;
4628         }
4629     }
4630 
4631     /**
4632      * Constructor that is called when inflating a view from XML. This is called
4633      * when a view is being constructed from an XML file, supplying attributes
4634      * that were specified in the XML file. This version uses a default style of
4635      * 0, so the only attribute values applied are those in the Context's Theme
4636      * and the given AttributeSet.
4637      *
4638      * <p>
4639      * The method onFinishInflate() will be called after all children have been
4640      * added.
4641      *
4642      * @param context The Context the view is running in, through which it can
4643      *        access the current theme, resources, etc.
4644      * @param attrs The attributes of the XML tag that is inflating the view.
4645      * @see #View(Context, AttributeSet, int)
4646      */
4647     public View(Context context, @Nullable AttributeSet attrs) {
4648         this(context, attrs, 0);
4649     }
4650 
4651     /**
4652      * Perform inflation from XML and apply a class-specific base style from a
4653      * theme attribute. This constructor of View allows subclasses to use their
4654      * own base style when they are inflating. For example, a Button class's
4655      * constructor would call this version of the super class constructor and
4656      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4657      * allows the theme's button style to modify all of the base view attributes
4658      * (in particular its background) as well as the Button class's attributes.
4659      *
4660      * @param context The Context the view is running in, through which it can
4661      *        access the current theme, resources, etc.
4662      * @param attrs The attributes of the XML tag that is inflating the view.
4663      * @param defStyleAttr An attribute in the current theme that contains a
4664      *        reference to a style resource that supplies default values for
4665      *        the view. Can be 0 to not look for defaults.
4666      * @see #View(Context, AttributeSet)
4667      */
4668     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4669         this(context, attrs, defStyleAttr, 0);
4670     }
4671 
4672     /**
4673      * Perform inflation from XML and apply a class-specific base style from a
4674      * theme attribute or style resource. This constructor of View allows
4675      * subclasses to use their own base style when they are inflating.
4676      * <p>
4677      * When determining the final value of a particular attribute, there are
4678      * four inputs that come into play:
4679      * <ol>
4680      * <li>Any attribute values in the given AttributeSet.
4681      * <li>The style resource specified in the AttributeSet (named "style").
4682      * <li>The default style specified by <var>defStyleAttr</var>.
4683      * <li>The default style specified by <var>defStyleRes</var>.
4684      * <li>The base values in this theme.
4685      * </ol>
4686      * <p>
4687      * Each of these inputs is considered in-order, with the first listed taking
4688      * precedence over the following ones. In other words, if in the
4689      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4690      * , then the button's text will <em>always</em> be black, regardless of
4691      * what is specified in any of the styles.
4692      *
4693      * @param context The Context the view is running in, through which it can
4694      *        access the current theme, resources, etc.
4695      * @param attrs The attributes of the XML tag that is inflating the view.
4696      * @param defStyleAttr An attribute in the current theme that contains a
4697      *        reference to a style resource that supplies default values for
4698      *        the view. Can be 0 to not look for defaults.
4699      * @param defStyleRes A resource identifier of a style resource that
4700      *        supplies default values for the view, used only if
4701      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4702      *        to not look for defaults.
4703      * @see #View(Context, AttributeSet, int)
4704      */
4705     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4706         this(context);
4707 
4708         final TypedArray a = context.obtainStyledAttributes(
4709                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4710 
4711         if (mDebugViewAttributes) {
4712             saveAttributeData(attrs, a);
4713         }
4714 
4715         Drawable background = null;
4716 
4717         int leftPadding = -1;
4718         int topPadding = -1;
4719         int rightPadding = -1;
4720         int bottomPadding = -1;
4721         int startPadding = UNDEFINED_PADDING;
4722         int endPadding = UNDEFINED_PADDING;
4723 
4724         int padding = -1;
4725         int paddingHorizontal = -1;
4726         int paddingVertical = -1;
4727 
4728         int viewFlagValues = 0;
4729         int viewFlagMasks = 0;
4730 
4731         boolean setScrollContainer = false;
4732 
4733         int x = 0;
4734         int y = 0;
4735 
4736         float tx = 0;
4737         float ty = 0;
4738         float tz = 0;
4739         float elevation = 0;
4740         float rotation = 0;
4741         float rotationX = 0;
4742         float rotationY = 0;
4743         float sx = 1f;
4744         float sy = 1f;
4745         boolean transformSet = false;
4746 
4747         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4748         int overScrollMode = mOverScrollMode;
4749         boolean initializeScrollbars = false;
4750         boolean initializeScrollIndicators = false;
4751 
4752         boolean startPaddingDefined = false;
4753         boolean endPaddingDefined = false;
4754         boolean leftPaddingDefined = false;
4755         boolean rightPaddingDefined = false;
4756 
4757         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4758 
4759         // Set default values.
4760         viewFlagValues |= FOCUSABLE_AUTO;
4761         viewFlagMasks |= FOCUSABLE_AUTO;
4762 
4763         final int N = a.getIndexCount();
4764         for (int i = 0; i < N; i++) {
4765             int attr = a.getIndex(i);
4766             switch (attr) {
4767                 case com.android.internal.R.styleable.View_background:
4768                     background = a.getDrawable(attr);
4769                     break;
4770                 case com.android.internal.R.styleable.View_padding:
4771                     padding = a.getDimensionPixelSize(attr, -1);
4772                     mUserPaddingLeftInitial = padding;
4773                     mUserPaddingRightInitial = padding;
4774                     leftPaddingDefined = true;
4775                     rightPaddingDefined = true;
4776                     break;
4777                 case com.android.internal.R.styleable.View_paddingHorizontal:
4778                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4779                     mUserPaddingLeftInitial = paddingHorizontal;
4780                     mUserPaddingRightInitial = paddingHorizontal;
4781                     leftPaddingDefined = true;
4782                     rightPaddingDefined = true;
4783                     break;
4784                 case com.android.internal.R.styleable.View_paddingVertical:
4785                     paddingVertical = a.getDimensionPixelSize(attr, -1);
4786                     break;
4787                  case com.android.internal.R.styleable.View_paddingLeft:
4788                     leftPadding = a.getDimensionPixelSize(attr, -1);
4789                     mUserPaddingLeftInitial = leftPadding;
4790                     leftPaddingDefined = true;
4791                     break;
4792                 case com.android.internal.R.styleable.View_paddingTop:
4793                     topPadding = a.getDimensionPixelSize(attr, -1);
4794                     break;
4795                 case com.android.internal.R.styleable.View_paddingRight:
4796                     rightPadding = a.getDimensionPixelSize(attr, -1);
4797                     mUserPaddingRightInitial = rightPadding;
4798                     rightPaddingDefined = true;
4799                     break;
4800                 case com.android.internal.R.styleable.View_paddingBottom:
4801                     bottomPadding = a.getDimensionPixelSize(attr, -1);
4802                     break;
4803                 case com.android.internal.R.styleable.View_paddingStart:
4804                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4805                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4806                     break;
4807                 case com.android.internal.R.styleable.View_paddingEnd:
4808                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4809                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4810                     break;
4811                 case com.android.internal.R.styleable.View_scrollX:
4812                     x = a.getDimensionPixelOffset(attr, 0);
4813                     break;
4814                 case com.android.internal.R.styleable.View_scrollY:
4815                     y = a.getDimensionPixelOffset(attr, 0);
4816                     break;
4817                 case com.android.internal.R.styleable.View_alpha:
4818                     setAlpha(a.getFloat(attr, 1f));
4819                     break;
4820                 case com.android.internal.R.styleable.View_transformPivotX:
4821                     setPivotX(a.getDimension(attr, 0));
4822                     break;
4823                 case com.android.internal.R.styleable.View_transformPivotY:
4824                     setPivotY(a.getDimension(attr, 0));
4825                     break;
4826                 case com.android.internal.R.styleable.View_translationX:
4827                     tx = a.getDimension(attr, 0);
4828                     transformSet = true;
4829                     break;
4830                 case com.android.internal.R.styleable.View_translationY:
4831                     ty = a.getDimension(attr, 0);
4832                     transformSet = true;
4833                     break;
4834                 case com.android.internal.R.styleable.View_translationZ:
4835                     tz = a.getDimension(attr, 0);
4836                     transformSet = true;
4837                     break;
4838                 case com.android.internal.R.styleable.View_elevation:
4839                     elevation = a.getDimension(attr, 0);
4840                     transformSet = true;
4841                     break;
4842                 case com.android.internal.R.styleable.View_rotation:
4843                     rotation = a.getFloat(attr, 0);
4844                     transformSet = true;
4845                     break;
4846                 case com.android.internal.R.styleable.View_rotationX:
4847                     rotationX = a.getFloat(attr, 0);
4848                     transformSet = true;
4849                     break;
4850                 case com.android.internal.R.styleable.View_rotationY:
4851                     rotationY = a.getFloat(attr, 0);
4852                     transformSet = true;
4853                     break;
4854                 case com.android.internal.R.styleable.View_scaleX:
4855                     sx = a.getFloat(attr, 1f);
4856                     transformSet = true;
4857                     break;
4858                 case com.android.internal.R.styleable.View_scaleY:
4859                     sy = a.getFloat(attr, 1f);
4860                     transformSet = true;
4861                     break;
4862                 case com.android.internal.R.styleable.View_id:
4863                     mID = a.getResourceId(attr, NO_ID);
4864                     break;
4865                 case com.android.internal.R.styleable.View_tag:
4866                     mTag = a.getText(attr);
4867                     break;
4868                 case com.android.internal.R.styleable.View_fitsSystemWindows:
4869                     if (a.getBoolean(attr, false)) {
4870                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
4871                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4872                     }
4873                     break;
4874                 case com.android.internal.R.styleable.View_focusable:
4875                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4876                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4877                         viewFlagMasks |= FOCUSABLE_MASK;
4878                     }
4879                     break;
4880                 case com.android.internal.R.styleable.View_focusableInTouchMode:
4881                     if (a.getBoolean(attr, false)) {
4882                         // unset auto focus since focusableInTouchMode implies explicit focusable
4883                         viewFlagValues &= ~FOCUSABLE_AUTO;
4884                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4885                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4886                     }
4887                     break;
4888                 case com.android.internal.R.styleable.View_clickable:
4889                     if (a.getBoolean(attr, false)) {
4890                         viewFlagValues |= CLICKABLE;
4891                         viewFlagMasks |= CLICKABLE;
4892                     }
4893                     break;
4894                 case com.android.internal.R.styleable.View_longClickable:
4895                     if (a.getBoolean(attr, false)) {
4896                         viewFlagValues |= LONG_CLICKABLE;
4897                         viewFlagMasks |= LONG_CLICKABLE;
4898                     }
4899                     break;
4900                 case com.android.internal.R.styleable.View_contextClickable:
4901                     if (a.getBoolean(attr, false)) {
4902                         viewFlagValues |= CONTEXT_CLICKABLE;
4903                         viewFlagMasks |= CONTEXT_CLICKABLE;
4904                     }
4905                     break;
4906                 case com.android.internal.R.styleable.View_saveEnabled:
4907                     if (!a.getBoolean(attr, true)) {
4908                         viewFlagValues |= SAVE_DISABLED;
4909                         viewFlagMasks |= SAVE_DISABLED_MASK;
4910                     }
4911                     break;
4912                 case com.android.internal.R.styleable.View_duplicateParentState:
4913                     if (a.getBoolean(attr, false)) {
4914                         viewFlagValues |= DUPLICATE_PARENT_STATE;
4915                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
4916                     }
4917                     break;
4918                 case com.android.internal.R.styleable.View_visibility:
4919                     final int visibility = a.getInt(attr, 0);
4920                     if (visibility != 0) {
4921                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
4922                         viewFlagMasks |= VISIBILITY_MASK;
4923                     }
4924                     break;
4925                 case com.android.internal.R.styleable.View_layoutDirection:
4926                     // Clear any layout direction flags (included resolved bits) already set
4927                     mPrivateFlags2 &=
4928                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4929                     // Set the layout direction flags depending on the value of the attribute
4930                     final int layoutDirection = a.getInt(attr, -1);
4931                     final int value = (layoutDirection != -1) ?
4932                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4933                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4934                     break;
4935                 case com.android.internal.R.styleable.View_drawingCacheQuality:
4936                     final int cacheQuality = a.getInt(attr, 0);
4937                     if (cacheQuality != 0) {
4938                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4939                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4940                     }
4941                     break;
4942                 case com.android.internal.R.styleable.View_contentDescription:
4943                     setContentDescription(a.getString(attr));
4944                     break;
4945                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4946                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4947                     break;
4948                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4949                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4950                     break;
4951                 case com.android.internal.R.styleable.View_labelFor:
4952                     setLabelFor(a.getResourceId(attr, NO_ID));
4953                     break;
4954                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4955                     if (!a.getBoolean(attr, true)) {
4956                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4957                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4958                     }
4959                     break;
4960                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4961                     if (!a.getBoolean(attr, true)) {
4962                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4963                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4964                     }
4965                     break;
4966                 case R.styleable.View_scrollbars:
4967                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4968                     if (scrollbars != SCROLLBARS_NONE) {
4969                         viewFlagValues |= scrollbars;
4970                         viewFlagMasks |= SCROLLBARS_MASK;
4971                         initializeScrollbars = true;
4972                     }
4973                     break;
4974                 //noinspection deprecation
4975                 case R.styleable.View_fadingEdge:
4976                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4977                         // Ignore the attribute starting with ICS
4978                         break;
4979                     }
4980                     // With builds < ICS, fall through and apply fading edges
4981                 case R.styleable.View_requiresFadingEdge:
4982                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4983                     if (fadingEdge != FADING_EDGE_NONE) {
4984                         viewFlagValues |= fadingEdge;
4985                         viewFlagMasks |= FADING_EDGE_MASK;
4986                         initializeFadingEdgeInternal(a);
4987                     }
4988                     break;
4989                 case R.styleable.View_scrollbarStyle:
4990                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4991                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4992                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4993                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4994                     }
4995                     break;
4996                 case R.styleable.View_isScrollContainer:
4997                     setScrollContainer = true;
4998                     if (a.getBoolean(attr, false)) {
4999                         setScrollContainer(true);
5000                     }
5001                     break;
5002                 case com.android.internal.R.styleable.View_keepScreenOn:
5003                     if (a.getBoolean(attr, false)) {
5004                         viewFlagValues |= KEEP_SCREEN_ON;
5005                         viewFlagMasks |= KEEP_SCREEN_ON;
5006                     }
5007                     break;
5008                 case R.styleable.View_filterTouchesWhenObscured:
5009                     if (a.getBoolean(attr, false)) {
5010                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5011                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5012                     }
5013                     break;
5014                 case R.styleable.View_nextFocusLeft:
5015                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5016                     break;
5017                 case R.styleable.View_nextFocusRight:
5018                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5019                     break;
5020                 case R.styleable.View_nextFocusUp:
5021                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5022                     break;
5023                 case R.styleable.View_nextFocusDown:
5024                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5025                     break;
5026                 case R.styleable.View_nextFocusForward:
5027                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5028                     break;
5029                 case R.styleable.View_nextClusterForward:
5030                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5031                     break;
5032                 case R.styleable.View_minWidth:
5033                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5034                     break;
5035                 case R.styleable.View_minHeight:
5036                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5037                     break;
5038                 case R.styleable.View_onClick:
5039                     if (context.isRestricted()) {
5040                         throw new IllegalStateException("The android:onClick attribute cannot "
5041                                 + "be used within a restricted context");
5042                     }
5043 
5044                     final String handlerName = a.getString(attr);
5045                     if (handlerName != null) {
5046                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5047                     }
5048                     break;
5049                 case R.styleable.View_overScrollMode:
5050                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5051                     break;
5052                 case R.styleable.View_verticalScrollbarPosition:
5053                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5054                     break;
5055                 case R.styleable.View_layerType:
5056                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5057                     break;
5058                 case R.styleable.View_textDirection:
5059                     // Clear any text direction flag already set
5060                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5061                     // Set the text direction flags depending on the value of the attribute
5062                     final int textDirection = a.getInt(attr, -1);
5063                     if (textDirection != -1) {
5064                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5065                     }
5066                     break;
5067                 case R.styleable.View_textAlignment:
5068                     // Clear any text alignment flag already set
5069                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5070                     // Set the text alignment flag depending on the value of the attribute
5071                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5072                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5073                     break;
5074                 case R.styleable.View_importantForAccessibility:
5075                     setImportantForAccessibility(a.getInt(attr,
5076                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5077                     break;
5078                 case R.styleable.View_accessibilityLiveRegion:
5079                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5080                     break;
5081                 case R.styleable.View_transitionName:
5082                     setTransitionName(a.getString(attr));
5083                     break;
5084                 case R.styleable.View_nestedScrollingEnabled:
5085                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5086                     break;
5087                 case R.styleable.View_stateListAnimator:
5088                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5089                             a.getResourceId(attr, 0)));
5090                     break;
5091                 case R.styleable.View_backgroundTint:
5092                     // This will get applied later during setBackground().
5093                     if (mBackgroundTint == null) {
5094                         mBackgroundTint = new TintInfo();
5095                     }
5096                     mBackgroundTint.mTintList = a.getColorStateList(
5097                             R.styleable.View_backgroundTint);
5098                     mBackgroundTint.mHasTintList = true;
5099                     break;
5100                 case R.styleable.View_backgroundTintMode:
5101                     // This will get applied later during setBackground().
5102                     if (mBackgroundTint == null) {
5103                         mBackgroundTint = new TintInfo();
5104                     }
5105                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
5106                             R.styleable.View_backgroundTintMode, -1), null);
5107                     mBackgroundTint.mHasTintMode = true;
5108                     break;
5109                 case R.styleable.View_outlineProvider:
5110                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5111                             PROVIDER_BACKGROUND));
5112                     break;
5113                 case R.styleable.View_foreground:
5114                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5115                         setForeground(a.getDrawable(attr));
5116                     }
5117                     break;
5118                 case R.styleable.View_foregroundGravity:
5119                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5120                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5121                     }
5122                     break;
5123                 case R.styleable.View_foregroundTintMode:
5124                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5125                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5126                     }
5127                     break;
5128                 case R.styleable.View_foregroundTint:
5129                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5130                         setForegroundTintList(a.getColorStateList(attr));
5131                     }
5132                     break;
5133                 case R.styleable.View_foregroundInsidePadding:
5134                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5135                         if (mForegroundInfo == null) {
5136                             mForegroundInfo = new ForegroundInfo();
5137                         }
5138                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5139                                 mForegroundInfo.mInsidePadding);
5140                     }
5141                     break;
5142                 case R.styleable.View_scrollIndicators:
5143                     final int scrollIndicators =
5144                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5145                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5146                     if (scrollIndicators != 0) {
5147                         mPrivateFlags3 |= scrollIndicators;
5148                         initializeScrollIndicators = true;
5149                     }
5150                     break;
5151                 case R.styleable.View_pointerIcon:
5152                     final int resourceId = a.getResourceId(attr, 0);
5153                     if (resourceId != 0) {
5154                         setPointerIcon(PointerIcon.load(
5155                                 context.getResources(), resourceId));
5156                     } else {
5157                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5158                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5159                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5160                         }
5161                     }
5162                     break;
5163                 case R.styleable.View_forceHasOverlappingRendering:
5164                     if (a.peekValue(attr) != null) {
5165                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5166                     }
5167                     break;
5168                 case R.styleable.View_tooltipText:
5169                     setTooltipText(a.getText(attr));
5170                     break;
5171                 case R.styleable.View_keyboardNavigationCluster:
5172                     if (a.peekValue(attr) != null) {
5173                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5174                     }
5175                     break;
5176                 case R.styleable.View_focusedByDefault:
5177                     if (a.peekValue(attr) != null) {
5178                         setFocusedByDefault(a.getBoolean(attr, true));
5179                     }
5180                     break;
5181                 case R.styleable.View_autofillHints:
5182                     if (a.peekValue(attr) != null) {
5183                         CharSequence[] rawHints = null;
5184                         String rawString = null;
5185 
5186                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5187                             int resId = a.getResourceId(attr, 0);
5188 
5189                             try {
5190                                 rawHints = a.getTextArray(attr);
5191                             } catch (Resources.NotFoundException e) {
5192                                 rawString = getResources().getString(resId);
5193                             }
5194                         } else {
5195                             rawString = a.getString(attr);
5196                         }
5197 
5198                         if (rawHints == null) {
5199                             if (rawString == null) {
5200                                 throw new IllegalArgumentException(
5201                                         "Could not resolve autofillHints");
5202                             } else {
5203                                 rawHints = rawString.split(",");
5204                             }
5205                         }
5206 
5207                         String[] hints = new String[rawHints.length];
5208 
5209                         int numHints = rawHints.length;
5210                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5211                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5212                         }
5213                         setAutofillHints(hints);
5214                     }
5215                     break;
5216                 case R.styleable.View_importantForAutofill:
5217                     if (a.peekValue(attr) != null) {
5218                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5219                     }
5220                     break;
5221                 case R.styleable.View_defaultFocusHighlightEnabled:
5222                     if (a.peekValue(attr) != null) {
5223                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5224                     }
5225                     break;
5226             }
5227         }
5228 
5229         setOverScrollMode(overScrollMode);
5230 
5231         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5232         // the resolved layout direction). Those cached values will be used later during padding
5233         // resolution.
5234         mUserPaddingStart = startPadding;
5235         mUserPaddingEnd = endPadding;
5236 
5237         if (background != null) {
5238             setBackground(background);
5239         }
5240 
5241         // setBackground above will record that padding is currently provided by the background.
5242         // If we have padding specified via xml, record that here instead and use it.
5243         mLeftPaddingDefined = leftPaddingDefined;
5244         mRightPaddingDefined = rightPaddingDefined;
5245 
5246         if (padding >= 0) {
5247             leftPadding = padding;
5248             topPadding = padding;
5249             rightPadding = padding;
5250             bottomPadding = padding;
5251             mUserPaddingLeftInitial = padding;
5252             mUserPaddingRightInitial = padding;
5253         } else {
5254             if (paddingHorizontal >= 0) {
5255                 leftPadding = paddingHorizontal;
5256                 rightPadding = paddingHorizontal;
5257                 mUserPaddingLeftInitial = paddingHorizontal;
5258                 mUserPaddingRightInitial = paddingHorizontal;
5259             }
5260             if (paddingVertical >= 0) {
5261                 topPadding = paddingVertical;
5262                 bottomPadding = paddingVertical;
5263             }
5264         }
5265 
5266         if (isRtlCompatibilityMode()) {
5267             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5268             // left / right padding are used if defined (meaning here nothing to do). If they are not
5269             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5270             // start / end and resolve them as left / right (layout direction is not taken into account).
5271             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5272             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5273             // defined.
5274             if (!mLeftPaddingDefined && startPaddingDefined) {
5275                 leftPadding = startPadding;
5276             }
5277             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5278             if (!mRightPaddingDefined && endPaddingDefined) {
5279                 rightPadding = endPadding;
5280             }
5281             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5282         } else {
5283             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5284             // values defined. Otherwise, left /right values are used.
5285             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5286             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5287             // defined.
5288             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5289 
5290             if (mLeftPaddingDefined && !hasRelativePadding) {
5291                 mUserPaddingLeftInitial = leftPadding;
5292             }
5293             if (mRightPaddingDefined && !hasRelativePadding) {
5294                 mUserPaddingRightInitial = rightPadding;
5295             }
5296         }
5297 
5298         internalSetPadding(
5299                 mUserPaddingLeftInitial,
5300                 topPadding >= 0 ? topPadding : mPaddingTop,
5301                 mUserPaddingRightInitial,
5302                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5303 
5304         if (viewFlagMasks != 0) {
5305             setFlags(viewFlagValues, viewFlagMasks);
5306         }
5307 
5308         if (initializeScrollbars) {
5309             initializeScrollbarsInternal(a);
5310         }
5311 
5312         if (initializeScrollIndicators) {
5313             initializeScrollIndicatorsInternal();
5314         }
5315 
5316         a.recycle();
5317 
5318         // Needs to be called after mViewFlags is set
5319         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5320             recomputePadding();
5321         }
5322 
5323         if (x != 0 || y != 0) {
5324             scrollTo(x, y);
5325         }
5326 
5327         if (transformSet) {
5328             setTranslationX(tx);
5329             setTranslationY(ty);
5330             setTranslationZ(tz);
5331             setElevation(elevation);
5332             setRotation(rotation);
5333             setRotationX(rotationX);
5334             setRotationY(rotationY);
5335             setScaleX(sx);
5336             setScaleY(sy);
5337         }
5338 
5339         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5340             setScrollContainer(true);
5341         }
5342 
5343         computeOpaqueFlags();
5344     }
5345 
5346     /**
5347      * An implementation of OnClickListener that attempts to lazily load a
5348      * named click handling method from a parent or ancestor context.
5349      */
5350     private static class DeclaredOnClickListener implements OnClickListener {
5351         private final View mHostView;
5352         private final String mMethodName;
5353 
5354         private Method mResolvedMethod;
5355         private Context mResolvedContext;
5356 
5357         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5358             mHostView = hostView;
5359             mMethodName = methodName;
5360         }
5361 
5362         @Override
5363         public void onClick(@NonNull View v) {
5364             if (mResolvedMethod == null) {
5365                 resolveMethod(mHostView.getContext(), mMethodName);
5366             }
5367 
5368             try {
5369                 mResolvedMethod.invoke(mResolvedContext, v);
5370             } catch (IllegalAccessException e) {
5371                 throw new IllegalStateException(
5372                         "Could not execute non-public method for android:onClick", e);
5373             } catch (InvocationTargetException e) {
5374                 throw new IllegalStateException(
5375                         "Could not execute method for android:onClick", e);
5376             }
5377         }
5378 
5379         @NonNull
5380         private void resolveMethod(@Nullable Context context, @NonNull String name) {
5381             while (context != null) {
5382                 try {
5383                     if (!context.isRestricted()) {
5384                         final Method method = context.getClass().getMethod(mMethodName, View.class);
5385                         if (method != null) {
5386                             mResolvedMethod = method;
5387                             mResolvedContext = context;
5388                             return;
5389                         }
5390                     }
5391                 } catch (NoSuchMethodException e) {
5392                     // Failed to find method, keep searching up the hierarchy.
5393                 }
5394 
5395                 if (context instanceof ContextWrapper) {
5396                     context = ((ContextWrapper) context).getBaseContext();
5397                 } else {
5398                     // Can't search up the hierarchy, null out and fail.
5399                     context = null;
5400                 }
5401             }
5402 
5403             final int id = mHostView.getId();
5404             final String idText = id == NO_ID ? "" : " with id '"
5405                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5406             throw new IllegalStateException("Could not find method " + mMethodName
5407                     + "(View) in a parent or ancestor Context for android:onClick "
5408                     + "attribute defined on view " + mHostView.getClass() + idText);
5409         }
5410     }
5411 
5412     /**
5413      * Non-public constructor for use in testing
5414      */
5415     View() {
5416         mResources = null;
5417         mRenderNode = RenderNode.create(getClass().getName(), this);
5418     }
5419 
5420     final boolean debugDraw() {
5421         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5422     }
5423 
5424     private static SparseArray<String> getAttributeMap() {
5425         if (mAttributeMap == null) {
5426             mAttributeMap = new SparseArray<>();
5427         }
5428         return mAttributeMap;
5429     }
5430 
5431     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5432         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5433         final int indexCount = t.getIndexCount();
5434         final String[] attributes = new String[(attrsCount + indexCount) * 2];
5435 
5436         int i = 0;
5437 
5438         // Store raw XML attributes.
5439         for (int j = 0; j < attrsCount; ++j) {
5440             attributes[i] = attrs.getAttributeName(j);
5441             attributes[i + 1] = attrs.getAttributeValue(j);
5442             i += 2;
5443         }
5444 
5445         // Store resolved styleable attributes.
5446         final Resources res = t.getResources();
5447         final SparseArray<String> attributeMap = getAttributeMap();
5448         for (int j = 0; j < indexCount; ++j) {
5449             final int index = t.getIndex(j);
5450             if (!t.hasValueOrEmpty(index)) {
5451                 // Value is undefined. Skip it.
5452                 continue;
5453             }
5454 
5455             final int resourceId = t.getResourceId(index, 0);
5456             if (resourceId == 0) {
5457                 // Value is not a reference. Skip it.
5458                 continue;
5459             }
5460 
5461             String resourceName = attributeMap.get(resourceId);
5462             if (resourceName == null) {
5463                 try {
5464                     resourceName = res.getResourceName(resourceId);
5465                 } catch (Resources.NotFoundException e) {
5466                     resourceName = "0x" + Integer.toHexString(resourceId);
5467                 }
5468                 attributeMap.put(resourceId, resourceName);
5469             }
5470 
5471             attributes[i] = resourceName;
5472             attributes[i + 1] = t.getString(index);
5473             i += 2;
5474         }
5475 
5476         // Trim to fit contents.
5477         final String[] trimmed = new String[i];
5478         System.arraycopy(attributes, 0, trimmed, 0, i);
5479         mAttributes = trimmed;
5480     }
5481 
5482     public String toString() {
5483         StringBuilder out = new StringBuilder(128);
5484         out.append(getClass().getName());
5485         out.append('{');
5486         out.append(Integer.toHexString(System.identityHashCode(this)));
5487         out.append(' ');
5488         switch (mViewFlags&VISIBILITY_MASK) {
5489             case VISIBLE: out.append('V'); break;
5490             case INVISIBLE: out.append('I'); break;
5491             case GONE: out.append('G'); break;
5492             default: out.append('.'); break;
5493         }
5494         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5495         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5496         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5497         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5498         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5499         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5500         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5501         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5502         out.append(' ');
5503         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5504         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5505         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5506         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5507             out.append('p');
5508         } else {
5509             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5510         }
5511         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5512         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5513         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5514         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5515         out.append(' ');
5516         out.append(mLeft);
5517         out.append(',');
5518         out.append(mTop);
5519         out.append('-');
5520         out.append(mRight);
5521         out.append(',');
5522         out.append(mBottom);
5523         final int id = getId();
5524         if (id != NO_ID) {
5525             out.append(" #");
5526             out.append(Integer.toHexString(id));
5527             final Resources r = mResources;
5528             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5529                 try {
5530                     String pkgname;
5531                     switch (id&0xff000000) {
5532                         case 0x7f000000:
5533                             pkgname="app";
5534                             break;
5535                         case 0x01000000:
5536                             pkgname="android";
5537                             break;
5538                         default:
5539                             pkgname = r.getResourcePackageName(id);
5540                             break;
5541                     }
5542                     String typename = r.getResourceTypeName(id);
5543                     String entryname = r.getResourceEntryName(id);
5544                     out.append(" ");
5545                     out.append(pkgname);
5546                     out.append(":");
5547                     out.append(typename);
5548                     out.append("/");
5549                     out.append(entryname);
5550                 } catch (Resources.NotFoundException e) {
5551                 }
5552             }
5553         }
5554         out.append("}");
5555         return out.toString();
5556     }
5557 
5558     /**
5559      * <p>
5560      * Initializes the fading edges from a given set of styled attributes. This
5561      * method should be called by subclasses that need fading edges and when an
5562      * instance of these subclasses is created programmatically rather than
5563      * being inflated from XML. This method is automatically called when the XML
5564      * is inflated.
5565      * </p>
5566      *
5567      * @param a the styled attributes set to initialize the fading edges from
5568      *
5569      * @removed
5570      */
5571     protected void initializeFadingEdge(TypedArray a) {
5572         // This method probably shouldn't have been included in the SDK to begin with.
5573         // It relies on 'a' having been initialized using an attribute filter array that is
5574         // not publicly available to the SDK. The old method has been renamed
5575         // to initializeFadingEdgeInternal and hidden for framework use only;
5576         // this one initializes using defaults to make it safe to call for apps.
5577 
5578         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5579 
5580         initializeFadingEdgeInternal(arr);
5581 
5582         arr.recycle();
5583     }
5584 
5585     /**
5586      * <p>
5587      * Initializes the fading edges from a given set of styled attributes. This
5588      * method should be called by subclasses that need fading edges and when an
5589      * instance of these subclasses is created programmatically rather than
5590      * being inflated from XML. This method is automatically called when the XML
5591      * is inflated.
5592      * </p>
5593      *
5594      * @param a the styled attributes set to initialize the fading edges from
5595      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5596      */
5597     protected void initializeFadingEdgeInternal(TypedArray a) {
5598         initScrollCache();
5599 
5600         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5601                 R.styleable.View_fadingEdgeLength,
5602                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5603     }
5604 
5605     /**
5606      * Returns the size of the vertical faded edges used to indicate that more
5607      * content in this view is visible.
5608      *
5609      * @return The size in pixels of the vertical faded edge or 0 if vertical
5610      *         faded edges are not enabled for this view.
5611      * @attr ref android.R.styleable#View_fadingEdgeLength
5612      */
5613     public int getVerticalFadingEdgeLength() {
5614         if (isVerticalFadingEdgeEnabled()) {
5615             ScrollabilityCache cache = mScrollCache;
5616             if (cache != null) {
5617                 return cache.fadingEdgeLength;
5618             }
5619         }
5620         return 0;
5621     }
5622 
5623     /**
5624      * Set the size of the faded edge used to indicate that more content in this
5625      * view is available.  Will not change whether the fading edge is enabled; use
5626      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5627      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5628      * for the vertical or horizontal fading edges.
5629      *
5630      * @param length The size in pixels of the faded edge used to indicate that more
5631      *        content in this view is visible.
5632      */
5633     public void setFadingEdgeLength(int length) {
5634         initScrollCache();
5635         mScrollCache.fadingEdgeLength = length;
5636     }
5637 
5638     /**
5639      * Returns the size of the horizontal faded edges used to indicate that more
5640      * content in this view is visible.
5641      *
5642      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5643      *         faded edges are not enabled for this view.
5644      * @attr ref android.R.styleable#View_fadingEdgeLength
5645      */
5646     public int getHorizontalFadingEdgeLength() {
5647         if (isHorizontalFadingEdgeEnabled()) {
5648             ScrollabilityCache cache = mScrollCache;
5649             if (cache != null) {
5650                 return cache.fadingEdgeLength;
5651             }
5652         }
5653         return 0;
5654     }
5655 
5656     /**
5657      * Returns the width of the vertical scrollbar.
5658      *
5659      * @return The width in pixels of the vertical scrollbar or 0 if there
5660      *         is no vertical scrollbar.
5661      */
5662     public int getVerticalScrollbarWidth() {
5663         ScrollabilityCache cache = mScrollCache;
5664         if (cache != null) {
5665             ScrollBarDrawable scrollBar = cache.scrollBar;
5666             if (scrollBar != null) {
5667                 int size = scrollBar.getSize(true);
5668                 if (size <= 0) {
5669                     size = cache.scrollBarSize;
5670                 }
5671                 return size;
5672             }
5673             return 0;
5674         }
5675         return 0;
5676     }
5677 
5678     /**
5679      * Returns the height of the horizontal scrollbar.
5680      *
5681      * @return The height in pixels of the horizontal scrollbar or 0 if
5682      *         there is no horizontal scrollbar.
5683      */
5684     protected int getHorizontalScrollbarHeight() {
5685         ScrollabilityCache cache = mScrollCache;
5686         if (cache != null) {
5687             ScrollBarDrawable scrollBar = cache.scrollBar;
5688             if (scrollBar != null) {
5689                 int size = scrollBar.getSize(false);
5690                 if (size <= 0) {
5691                     size = cache.scrollBarSize;
5692                 }
5693                 return size;
5694             }
5695             return 0;
5696         }
5697         return 0;
5698     }
5699 
5700     /**
5701      * <p>
5702      * Initializes the scrollbars from a given set of styled attributes. This
5703      * method should be called by subclasses that need scrollbars and when an
5704      * instance of these subclasses is created programmatically rather than
5705      * being inflated from XML. This method is automatically called when the XML
5706      * is inflated.
5707      * </p>
5708      *
5709      * @param a the styled attributes set to initialize the scrollbars from
5710      *
5711      * @removed
5712      */
5713     protected void initializeScrollbars(TypedArray a) {
5714         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5715         // using the View filter array which is not available to the SDK. As such, internal
5716         // framework usage now uses initializeScrollbarsInternal and we grab a default
5717         // TypedArray with the right filter instead here.
5718         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5719 
5720         initializeScrollbarsInternal(arr);
5721 
5722         // We ignored the method parameter. Recycle the one we actually did use.
5723         arr.recycle();
5724     }
5725 
5726     /**
5727      * <p>
5728      * Initializes the scrollbars from a given set of styled attributes. This
5729      * method should be called by subclasses that need scrollbars and when an
5730      * instance of these subclasses is created programmatically rather than
5731      * being inflated from XML. This method is automatically called when the XML
5732      * is inflated.
5733      * </p>
5734      *
5735      * @param a the styled attributes set to initialize the scrollbars from
5736      * @hide
5737      */
5738     protected void initializeScrollbarsInternal(TypedArray a) {
5739         initScrollCache();
5740 
5741         final ScrollabilityCache scrollabilityCache = mScrollCache;
5742 
5743         if (scrollabilityCache.scrollBar == null) {
5744             scrollabilityCache.scrollBar = new ScrollBarDrawable();
5745             scrollabilityCache.scrollBar.setState(getDrawableState());
5746             scrollabilityCache.scrollBar.setCallback(this);
5747         }
5748 
5749         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5750 
5751         if (!fadeScrollbars) {
5752             scrollabilityCache.state = ScrollabilityCache.ON;
5753         }
5754         scrollabilityCache.fadeScrollBars = fadeScrollbars;
5755 
5756 
5757         scrollabilityCache.scrollBarFadeDuration = a.getInt(
5758                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5759                         .getScrollBarFadeDuration());
5760         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5761                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
5762                 ViewConfiguration.getScrollDefaultDelay());
5763 
5764 
5765         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5766                 com.android.internal.R.styleable.View_scrollbarSize,
5767                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
5768 
5769         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5770         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5771 
5772         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5773         if (thumb != null) {
5774             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5775         }
5776 
5777         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5778                 false);
5779         if (alwaysDraw) {
5780             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5781         }
5782 
5783         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5784         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5785 
5786         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5787         if (thumb != null) {
5788             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5789         }
5790 
5791         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5792                 false);
5793         if (alwaysDraw) {
5794             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5795         }
5796 
5797         // Apply layout direction to the new Drawables if needed
5798         final int layoutDirection = getLayoutDirection();
5799         if (track != null) {
5800             track.setLayoutDirection(layoutDirection);
5801         }
5802         if (thumb != null) {
5803             thumb.setLayoutDirection(layoutDirection);
5804         }
5805 
5806         // Re-apply user/background padding so that scrollbar(s) get added
5807         resolvePadding();
5808     }
5809 
5810     private void initializeScrollIndicatorsInternal() {
5811         // Some day maybe we'll break this into top/left/start/etc. and let the
5812         // client control it. Until then, you can have any scroll indicator you
5813         // want as long as it's a 1dp foreground-colored rectangle.
5814         if (mScrollIndicatorDrawable == null) {
5815             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5816         }
5817     }
5818 
5819     /**
5820      * <p>
5821      * Initalizes the scrollability cache if necessary.
5822      * </p>
5823      */
5824     private void initScrollCache() {
5825         if (mScrollCache == null) {
5826             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5827         }
5828     }
5829 
5830     private ScrollabilityCache getScrollCache() {
5831         initScrollCache();
5832         return mScrollCache;
5833     }
5834 
5835     /**
5836      * Set the position of the vertical scroll bar. Should be one of
5837      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5838      * {@link #SCROLLBAR_POSITION_RIGHT}.
5839      *
5840      * @param position Where the vertical scroll bar should be positioned.
5841      */
5842     public void setVerticalScrollbarPosition(int position) {
5843         if (mVerticalScrollbarPosition != position) {
5844             mVerticalScrollbarPosition = position;
5845             computeOpaqueFlags();
5846             resolvePadding();
5847         }
5848     }
5849 
5850     /**
5851      * @return The position where the vertical scroll bar will show, if applicable.
5852      * @see #setVerticalScrollbarPosition(int)
5853      */
5854     public int getVerticalScrollbarPosition() {
5855         return mVerticalScrollbarPosition;
5856     }
5857 
5858     boolean isOnScrollbar(float x, float y) {
5859         if (mScrollCache == null) {
5860             return false;
5861         }
5862         x += getScrollX();
5863         y += getScrollY();
5864         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5865             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5866             getVerticalScrollBarBounds(null, touchBounds);
5867             if (touchBounds.contains((int) x, (int) y)) {
5868                 return true;
5869             }
5870         }
5871         if (isHorizontalScrollBarEnabled()) {
5872             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5873             getHorizontalScrollBarBounds(null, touchBounds);
5874             if (touchBounds.contains((int) x, (int) y)) {
5875                 return true;
5876             }
5877         }
5878         return false;
5879     }
5880 
5881     boolean isOnScrollbarThumb(float x, float y) {
5882         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5883     }
5884 
5885     private boolean isOnVerticalScrollbarThumb(float x, float y) {
5886         if (mScrollCache == null) {
5887             return false;
5888         }
5889         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5890             x += getScrollX();
5891             y += getScrollY();
5892             final Rect bounds = mScrollCache.mScrollBarBounds;
5893             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5894             getVerticalScrollBarBounds(bounds, touchBounds);
5895             final int range = computeVerticalScrollRange();
5896             final int offset = computeVerticalScrollOffset();
5897             final int extent = computeVerticalScrollExtent();
5898             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5899                     extent, range);
5900             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5901                     extent, range, offset);
5902             final int thumbTop = bounds.top + thumbOffset;
5903             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5904             if (x >= touchBounds.left && x <= touchBounds.right
5905                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5906                 return true;
5907             }
5908         }
5909         return false;
5910     }
5911 
5912     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5913         if (mScrollCache == null) {
5914             return false;
5915         }
5916         if (isHorizontalScrollBarEnabled()) {
5917             x += getScrollX();
5918             y += getScrollY();
5919             final Rect bounds = mScrollCache.mScrollBarBounds;
5920             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5921             getHorizontalScrollBarBounds(bounds, touchBounds);
5922             final int range = computeHorizontalScrollRange();
5923             final int offset = computeHorizontalScrollOffset();
5924             final int extent = computeHorizontalScrollExtent();
5925             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5926                     extent, range);
5927             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5928                     extent, range, offset);
5929             final int thumbLeft = bounds.left + thumbOffset;
5930             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5931             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5932                     && y >= touchBounds.top && y <= touchBounds.bottom) {
5933                 return true;
5934             }
5935         }
5936         return false;
5937     }
5938 
5939     boolean isDraggingScrollBar() {
5940         return mScrollCache != null
5941                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5942     }
5943 
5944     /**
5945      * Sets the state of all scroll indicators.
5946      * <p>
5947      * See {@link #setScrollIndicators(int, int)} for usage information.
5948      *
5949      * @param indicators a bitmask of indicators that should be enabled, or
5950      *                   {@code 0} to disable all indicators
5951      * @see #setScrollIndicators(int, int)
5952      * @see #getScrollIndicators()
5953      * @attr ref android.R.styleable#View_scrollIndicators
5954      */
5955     public void setScrollIndicators(@ScrollIndicators int indicators) {
5956         setScrollIndicators(indicators,
5957                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5958     }
5959 
5960     /**
5961      * Sets the state of the scroll indicators specified by the mask. To change
5962      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5963      * <p>
5964      * When a scroll indicator is enabled, it will be displayed if the view
5965      * can scroll in the direction of the indicator.
5966      * <p>
5967      * Multiple indicator types may be enabled or disabled by passing the
5968      * logical OR of the desired types. If multiple types are specified, they
5969      * will all be set to the same enabled state.
5970      * <p>
5971      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5972      *
5973      * @param indicators the indicator direction, or the logical OR of multiple
5974      *             indicator directions. One or more of:
5975      *             <ul>
5976      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5977      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5978      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5979      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5980      *               <li>{@link #SCROLL_INDICATOR_START}</li>
5981      *               <li>{@link #SCROLL_INDICATOR_END}</li>
5982      *             </ul>
5983      * @see #setScrollIndicators(int)
5984      * @see #getScrollIndicators()
5985      * @attr ref android.R.styleable#View_scrollIndicators
5986      */
5987     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5988         // Shift and sanitize mask.
5989         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5990         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5991 
5992         // Shift and mask indicators.
5993         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5994         indicators &= mask;
5995 
5996         // Merge with non-masked flags.
5997         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5998 
5999         if (mPrivateFlags3 != updatedFlags) {
6000             mPrivateFlags3 = updatedFlags;
6001 
6002             if (indicators != 0) {
6003                 initializeScrollIndicatorsInternal();
6004             }
6005             invalidate();
6006         }
6007     }
6008 
6009     /**
6010      * Returns a bitmask representing the enabled scroll indicators.
6011      * <p>
6012      * For example, if the top and left scroll indicators are enabled and all
6013      * other indicators are disabled, the return value will be
6014      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
6015      * <p>
6016      * To check whether the bottom scroll indicator is enabled, use the value
6017      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
6018      *
6019      * @return a bitmask representing the enabled scroll indicators
6020      */
6021     @ScrollIndicators
6022     public int getScrollIndicators() {
6023         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
6024                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6025     }
6026 
6027     ListenerInfo getListenerInfo() {
6028         if (mListenerInfo != null) {
6029             return mListenerInfo;
6030         }
6031         mListenerInfo = new ListenerInfo();
6032         return mListenerInfo;
6033     }
6034 
6035     /**
6036      * Register a callback to be invoked when the scroll X or Y positions of
6037      * this view change.
6038      * <p>
6039      * <b>Note:</b> Some views handle scrolling independently from View and may
6040      * have their own separate listeners for scroll-type events. For example,
6041      * {@link android.widget.ListView ListView} allows clients to register an
6042      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
6043      * to listen for changes in list scroll position.
6044      *
6045      * @param l The listener to notify when the scroll X or Y position changes.
6046      * @see android.view.View#getScrollX()
6047      * @see android.view.View#getScrollY()
6048      */
6049     public void setOnScrollChangeListener(OnScrollChangeListener l) {
6050         getListenerInfo().mOnScrollChangeListener = l;
6051     }
6052 
6053     /**
6054      * Register a callback to be invoked when focus of this view changed.
6055      *
6056      * @param l The callback that will run.
6057      */
6058     public void setOnFocusChangeListener(OnFocusChangeListener l) {
6059         getListenerInfo().mOnFocusChangeListener = l;
6060     }
6061 
6062     /**
6063      * Add a listener that will be called when the bounds of the view change due to
6064      * layout processing.
6065      *
6066      * @param listener The listener that will be called when layout bounds change.
6067      */
6068     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6069         ListenerInfo li = getListenerInfo();
6070         if (li.mOnLayoutChangeListeners == null) {
6071             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6072         }
6073         if (!li.mOnLayoutChangeListeners.contains(listener)) {
6074             li.mOnLayoutChangeListeners.add(listener);
6075         }
6076     }
6077 
6078     /**
6079      * Remove a listener for layout changes.
6080      *
6081      * @param listener The listener for layout bounds change.
6082      */
6083     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6084         ListenerInfo li = mListenerInfo;
6085         if (li == null || li.mOnLayoutChangeListeners == null) {
6086             return;
6087         }
6088         li.mOnLayoutChangeListeners.remove(listener);
6089     }
6090 
6091     /**
6092      * Add a listener for attach state changes.
6093      *
6094      * This listener will be called whenever this view is attached or detached
6095      * from a window. Remove the listener using
6096      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6097      *
6098      * @param listener Listener to attach
6099      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6100      */
6101     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6102         ListenerInfo li = getListenerInfo();
6103         if (li.mOnAttachStateChangeListeners == null) {
6104             li.mOnAttachStateChangeListeners
6105                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6106         }
6107         li.mOnAttachStateChangeListeners.add(listener);
6108     }
6109 
6110     /**
6111      * Remove a listener for attach state changes. The listener will receive no further
6112      * notification of window attach/detach events.
6113      *
6114      * @param listener Listener to remove
6115      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6116      */
6117     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6118         ListenerInfo li = mListenerInfo;
6119         if (li == null || li.mOnAttachStateChangeListeners == null) {
6120             return;
6121         }
6122         li.mOnAttachStateChangeListeners.remove(listener);
6123     }
6124 
6125     /**
6126      * Returns the focus-change callback registered for this view.
6127      *
6128      * @return The callback, or null if one is not registered.
6129      */
6130     public OnFocusChangeListener getOnFocusChangeListener() {
6131         ListenerInfo li = mListenerInfo;
6132         return li != null ? li.mOnFocusChangeListener : null;
6133     }
6134 
6135     /**
6136      * Register a callback to be invoked when this view is clicked. If this view is not
6137      * clickable, it becomes clickable.
6138      *
6139      * @param l The callback that will run
6140      *
6141      * @see #setClickable(boolean)
6142      */
6143     public void setOnClickListener(@Nullable OnClickListener l) {
6144         if (!isClickable()) {
6145             setClickable(true);
6146         }
6147         getListenerInfo().mOnClickListener = l;
6148     }
6149 
6150     /**
6151      * Return whether this view has an attached OnClickListener.  Returns
6152      * true if there is a listener, false if there is none.
6153      */
6154     public boolean hasOnClickListeners() {
6155         ListenerInfo li = mListenerInfo;
6156         return (li != null && li.mOnClickListener != null);
6157     }
6158 
6159     /**
6160      * Register a callback to be invoked when this view is clicked and held. If this view is not
6161      * long clickable, it becomes long clickable.
6162      *
6163      * @param l The callback that will run
6164      *
6165      * @see #setLongClickable(boolean)
6166      */
6167     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6168         if (!isLongClickable()) {
6169             setLongClickable(true);
6170         }
6171         getListenerInfo().mOnLongClickListener = l;
6172     }
6173 
6174     /**
6175      * Register a callback to be invoked when this view is context clicked. If the view is not
6176      * context clickable, it becomes context clickable.
6177      *
6178      * @param l The callback that will run
6179      * @see #setContextClickable(boolean)
6180      */
6181     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6182         if (!isContextClickable()) {
6183             setContextClickable(true);
6184         }
6185         getListenerInfo().mOnContextClickListener = l;
6186     }
6187 
6188     /**
6189      * Register a callback to be invoked when the context menu for this view is
6190      * being built. If this view is not long clickable, it becomes long clickable.
6191      *
6192      * @param l The callback that will run
6193      *
6194      */
6195     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6196         if (!isLongClickable()) {
6197             setLongClickable(true);
6198         }
6199         getListenerInfo().mOnCreateContextMenuListener = l;
6200     }
6201 
6202     /**
6203      * Set an observer to collect stats for each frame rendered for this view.
6204      *
6205      * @hide
6206      */
6207     public void addFrameMetricsListener(Window window,
6208             Window.OnFrameMetricsAvailableListener listener,
6209             Handler handler) {
6210         if (mAttachInfo != null) {
6211             if (mAttachInfo.mThreadedRenderer != null) {
6212                 if (mFrameMetricsObservers == null) {
6213                     mFrameMetricsObservers = new ArrayList<>();
6214                 }
6215 
6216                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6217                         handler.getLooper(), listener);
6218                 mFrameMetricsObservers.add(fmo);
6219                 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6220             } else {
6221                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6222             }
6223         } else {
6224             if (mFrameMetricsObservers == null) {
6225                 mFrameMetricsObservers = new ArrayList<>();
6226             }
6227 
6228             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6229                     handler.getLooper(), listener);
6230             mFrameMetricsObservers.add(fmo);
6231         }
6232     }
6233 
6234     /**
6235      * Remove observer configured to collect frame stats for this view.
6236      *
6237      * @hide
6238      */
6239     public void removeFrameMetricsListener(
6240             Window.OnFrameMetricsAvailableListener listener) {
6241         ThreadedRenderer renderer = getThreadedRenderer();
6242         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6243         if (fmo == null) {
6244             throw new IllegalArgumentException(
6245                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
6246         }
6247 
6248         if (mFrameMetricsObservers != null) {
6249             mFrameMetricsObservers.remove(fmo);
6250             if (renderer != null) {
6251                 renderer.removeFrameMetricsObserver(fmo);
6252             }
6253         }
6254     }
6255 
6256     private void registerPendingFrameMetricsObservers() {
6257         if (mFrameMetricsObservers != null) {
6258             ThreadedRenderer renderer = getThreadedRenderer();
6259             if (renderer != null) {
6260                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6261                     renderer.addFrameMetricsObserver(fmo);
6262                 }
6263             } else {
6264                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6265             }
6266         }
6267     }
6268 
6269     private FrameMetricsObserver findFrameMetricsObserver(
6270             Window.OnFrameMetricsAvailableListener listener) {
6271         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6272             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6273             if (observer.mListener == listener) {
6274                 return observer;
6275             }
6276         }
6277 
6278         return null;
6279     }
6280 
6281     /**
6282      * Call this view's OnClickListener, if it is defined.  Performs all normal
6283      * actions associated with clicking: reporting accessibility event, playing
6284      * a sound, etc.
6285      *
6286      * @return True there was an assigned OnClickListener that was called, false
6287      *         otherwise is returned.
6288      */
6289     public boolean performClick() {
6290         final boolean result;
6291         final ListenerInfo li = mListenerInfo;
6292         if (li != null && li.mOnClickListener != null) {
6293             playSoundEffect(SoundEffectConstants.CLICK);
6294             li.mOnClickListener.onClick(this);
6295             result = true;
6296         } else {
6297             result = false;
6298         }
6299 
6300         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6301 
6302         notifyEnterOrExitForAutoFillIfNeeded(true);
6303 
6304         return result;
6305     }
6306 
6307     /**
6308      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6309      * this only calls the listener, and does not do any associated clicking
6310      * actions like reporting an accessibility event.
6311      *
6312      * @return True there was an assigned OnClickListener that was called, false
6313      *         otherwise is returned.
6314      */
6315     public boolean callOnClick() {
6316         ListenerInfo li = mListenerInfo;
6317         if (li != null && li.mOnClickListener != null) {
6318             li.mOnClickListener.onClick(this);
6319             return true;
6320         }
6321         return false;
6322     }
6323 
6324     /**
6325      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6326      * context menu if the OnLongClickListener did not consume the event.
6327      *
6328      * @return {@code true} if one of the above receivers consumed the event,
6329      *         {@code false} otherwise
6330      */
6331     public boolean performLongClick() {
6332         return performLongClickInternal(mLongClickX, mLongClickY);
6333     }
6334 
6335     /**
6336      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6337      * context menu if the OnLongClickListener did not consume the event,
6338      * anchoring it to an (x,y) coordinate.
6339      *
6340      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6341      *          to disable anchoring
6342      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6343      *          to disable anchoring
6344      * @return {@code true} if one of the above receivers consumed the event,
6345      *         {@code false} otherwise
6346      */
6347     public boolean performLongClick(float x, float y) {
6348         mLongClickX = x;
6349         mLongClickY = y;
6350         final boolean handled = performLongClick();
6351         mLongClickX = Float.NaN;
6352         mLongClickY = Float.NaN;
6353         return handled;
6354     }
6355 
6356     /**
6357      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6358      * context menu if the OnLongClickListener did not consume the event,
6359      * optionally anchoring it to an (x,y) coordinate.
6360      *
6361      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6362      *          to disable anchoring
6363      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6364      *          to disable anchoring
6365      * @return {@code true} if one of the above receivers consumed the event,
6366      *         {@code false} otherwise
6367      */
6368     private boolean performLongClickInternal(float x, float y) {
6369         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6370 
6371         boolean handled = false;
6372         final ListenerInfo li = mListenerInfo;
6373         if (li != null && li.mOnLongClickListener != null) {
6374             handled = li.mOnLongClickListener.onLongClick(View.this);
6375         }
6376         if (!handled) {
6377             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6378             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6379         }
6380         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6381             if (!handled) {
6382                 handled = showLongClickTooltip((int) x, (int) y);
6383             }
6384         }
6385         if (handled) {
6386             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6387         }
6388         return handled;
6389     }
6390 
6391     /**
6392      * Call this view's OnContextClickListener, if it is defined.
6393      *
6394      * @param x the x coordinate of the context click
6395      * @param y the y coordinate of the context click
6396      * @return True if there was an assigned OnContextClickListener that consumed the event, false
6397      *         otherwise.
6398      */
6399     public boolean performContextClick(float x, float y) {
6400         return performContextClick();
6401     }
6402 
6403     /**
6404      * Call this view's OnContextClickListener, if it is defined.
6405      *
6406      * @return True if there was an assigned OnContextClickListener that consumed the event, false
6407      *         otherwise.
6408      */
6409     public boolean performContextClick() {
6410         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6411 
6412         boolean handled = false;
6413         ListenerInfo li = mListenerInfo;
6414         if (li != null && li.mOnContextClickListener != null) {
6415             handled = li.mOnContextClickListener.onContextClick(View.this);
6416         }
6417         if (handled) {
6418             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6419         }
6420         return handled;
6421     }
6422 
6423     /**
6424      * Performs button-related actions during a touch down event.
6425      *
6426      * @param event The event.
6427      * @return True if the down was consumed.
6428      *
6429      * @hide
6430      */
6431     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6432         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6433             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6434             showContextMenu(event.getX(), event.getY());
6435             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6436             return true;
6437         }
6438         return false;
6439     }
6440 
6441     /**
6442      * Shows the context menu for this view.
6443      *
6444      * @return {@code true} if the context menu was shown, {@code false}
6445      *         otherwise
6446      * @see #showContextMenu(float, float)
6447      */
6448     public boolean showContextMenu() {
6449         return getParent().showContextMenuForChild(this);
6450     }
6451 
6452     /**
6453      * Shows the context menu for this view anchored to the specified
6454      * view-relative coordinate.
6455      *
6456      * @param x the X coordinate in pixels relative to the view to which the
6457      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6458      * @param y the Y coordinate in pixels relative to the view to which the
6459      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6460      * @return {@code true} if the context menu was shown, {@code false}
6461      *         otherwise
6462      */
6463     public boolean showContextMenu(float x, float y) {
6464         return getParent().showContextMenuForChild(this, x, y);
6465     }
6466 
6467     /**
6468      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6469      *
6470      * @param callback Callback that will control the lifecycle of the action mode
6471      * @return The new action mode if it is started, null otherwise
6472      *
6473      * @see ActionMode
6474      * @see #startActionMode(android.view.ActionMode.Callback, int)
6475      */
6476     public ActionMode startActionMode(ActionMode.Callback callback) {
6477         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6478     }
6479 
6480     /**
6481      * Start an action mode with the given type.
6482      *
6483      * @param callback Callback that will control the lifecycle of the action mode
6484      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6485      * @return The new action mode if it is started, null otherwise
6486      *
6487      * @see ActionMode
6488      */
6489     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6490         ViewParent parent = getParent();
6491         if (parent == null) return null;
6492         try {
6493             return parent.startActionModeForChild(this, callback, type);
6494         } catch (AbstractMethodError ame) {
6495             // Older implementations of custom views might not implement this.
6496             return parent.startActionModeForChild(this, callback);
6497         }
6498     }
6499 
6500     /**
6501      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6502      * Context, creating a unique View identifier to retrieve the result.
6503      *
6504      * @param intent The Intent to be started.
6505      * @param requestCode The request code to use.
6506      * @hide
6507      */
6508     public void startActivityForResult(Intent intent, int requestCode) {
6509         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6510         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6511     }
6512 
6513     /**
6514      * If this View corresponds to the calling who, dispatches the activity result.
6515      * @param who The identifier for the targeted View to receive the result.
6516      * @param requestCode The integer request code originally supplied to
6517      *                    startActivityForResult(), allowing you to identify who this
6518      *                    result came from.
6519      * @param resultCode The integer result code returned by the child activity
6520      *                   through its setResult().
6521      * @param data An Intent, which can return result data to the caller
6522      *               (various data can be attached to Intent "extras").
6523      * @return {@code true} if the activity result was dispatched.
6524      * @hide
6525      */
6526     public boolean dispatchActivityResult(
6527             String who, int requestCode, int resultCode, Intent data) {
6528         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6529             onActivityResult(requestCode, resultCode, data);
6530             mStartActivityRequestWho = null;
6531             return true;
6532         }
6533         return false;
6534     }
6535 
6536     /**
6537      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6538      *
6539      * @param requestCode The integer request code originally supplied to
6540      *                    startActivityForResult(), allowing you to identify who this
6541      *                    result came from.
6542      * @param resultCode The integer result code returned by the child activity
6543      *                   through its setResult().
6544      * @param data An Intent, which can return result data to the caller
6545      *               (various data can be attached to Intent "extras").
6546      * @hide
6547      */
6548     public void onActivityResult(int requestCode, int resultCode, Intent data) {
6549         // Do nothing.
6550     }
6551 
6552     /**
6553      * Register a callback to be invoked when a hardware key is pressed in this view.
6554      * Key presses in software input methods will generally not trigger the methods of
6555      * this listener.
6556      * @param l the key listener to attach to this view
6557      */
6558     public void setOnKeyListener(OnKeyListener l) {
6559         getListenerInfo().mOnKeyListener = l;
6560     }
6561 
6562     /**
6563      * Register a callback to be invoked when a touch event is sent to this view.
6564      * @param l the touch listener to attach to this view
6565      */
6566     public void setOnTouchListener(OnTouchListener l) {
6567         getListenerInfo().mOnTouchListener = l;
6568     }
6569 
6570     /**
6571      * Register a callback to be invoked when a generic motion event is sent to this view.
6572      * @param l the generic motion listener to attach to this view
6573      */
6574     public void setOnGenericMotionListener(OnGenericMotionListener l) {
6575         getListenerInfo().mOnGenericMotionListener = l;
6576     }
6577 
6578     /**
6579      * Register a callback to be invoked when a hover event is sent to this view.
6580      * @param l the hover listener to attach to this view
6581      */
6582     public void setOnHoverListener(OnHoverListener l) {
6583         getListenerInfo().mOnHoverListener = l;
6584     }
6585 
6586     /**
6587      * Register a drag event listener callback object for this View. The parameter is
6588      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6589      * View, the system calls the
6590      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6591      * @param l An implementation of {@link android.view.View.OnDragListener}.
6592      */
6593     public void setOnDragListener(OnDragListener l) {
6594         getListenerInfo().mOnDragListener = l;
6595     }
6596 
6597     /**
6598      * Give this view focus. This will cause
6599      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6600      *
6601      * Note: this does not check whether this {@link View} should get focus, it just
6602      * gives it focus no matter what.  It should only be called internally by framework
6603      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6604      *
6605      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6606      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6607      *        focus moved when requestFocus() is called. It may not always
6608      *        apply, in which case use the default View.FOCUS_DOWN.
6609      * @param previouslyFocusedRect The rectangle of the view that had focus
6610      *        prior in this View's coordinate system.
6611      */
6612     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6613         if (DBG) {
6614             System.out.println(this + " requestFocus()");
6615         }
6616 
6617         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6618             mPrivateFlags |= PFLAG_FOCUSED;
6619 
6620             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6621 
6622             if (mParent != null) {
6623                 mParent.requestChildFocus(this, this);
6624                 updateFocusedInCluster(oldFocus, direction);
6625             }
6626 
6627             if (mAttachInfo != null) {
6628                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6629             }
6630 
6631             onFocusChanged(true, direction, previouslyFocusedRect);
6632             refreshDrawableState();
6633         }
6634     }
6635 
6636     /**
6637      * Sets this view's preference for reveal behavior when it gains focus.
6638      *
6639      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6640      * this view would prefer to be brought fully into view when it gains focus.
6641      * For example, a text field that a user is meant to type into. Other views such
6642      * as scrolling containers may prefer to opt-out of this behavior.</p>
6643      *
6644      * <p>The default value for views is true, though subclasses may change this
6645      * based on their preferred behavior.</p>
6646      *
6647      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6648      *
6649      * @see #getRevealOnFocusHint()
6650      */
6651     public final void setRevealOnFocusHint(boolean revealOnFocus) {
6652         if (revealOnFocus) {
6653             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6654         } else {
6655             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6656         }
6657     }
6658 
6659     /**
6660      * Returns this view's preference for reveal behavior when it gains focus.
6661      *
6662      * <p>When this method returns true for a child view requesting focus, ancestor
6663      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6664      * should make a best effort to make the newly focused child fully visible to the user.
6665      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6666      * other properties affecting visibility to the user as part of the focus change.</p>
6667      *
6668      * @return true if this view would prefer to become fully visible when it gains focus,
6669      *         false if it would prefer not to disrupt scroll positioning
6670      *
6671      * @see #setRevealOnFocusHint(boolean)
6672      */
6673     public final boolean getRevealOnFocusHint() {
6674         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6675     }
6676 
6677     /**
6678      * Populates <code>outRect</code> with the hotspot bounds. By default,
6679      * the hotspot bounds are identical to the screen bounds.
6680      *
6681      * @param outRect rect to populate with hotspot bounds
6682      * @hide Only for internal use by views and widgets.
6683      */
6684     public void getHotspotBounds(Rect outRect) {
6685         final Drawable background = getBackground();
6686         if (background != null) {
6687             background.getHotspotBounds(outRect);
6688         } else {
6689             getBoundsOnScreen(outRect);
6690         }
6691     }
6692 
6693     /**
6694      * Request that a rectangle of this view be visible on the screen,
6695      * scrolling if necessary just enough.
6696      *
6697      * <p>A View should call this if it maintains some notion of which part
6698      * of its content is interesting.  For example, a text editing view
6699      * should call this when its cursor moves.
6700      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6701      * It should not be affected by which part of the View is currently visible or its scroll
6702      * position.
6703      *
6704      * @param rectangle The rectangle in the View's content coordinate space
6705      * @return Whether any parent scrolled.
6706      */
6707     public boolean requestRectangleOnScreen(Rect rectangle) {
6708         return requestRectangleOnScreen(rectangle, false);
6709     }
6710 
6711     /**
6712      * Request that a rectangle of this view be visible on the screen,
6713      * scrolling if necessary just enough.
6714      *
6715      * <p>A View should call this if it maintains some notion of which part
6716      * of its content is interesting.  For example, a text editing view
6717      * should call this when its cursor moves.
6718      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6719      * It should not be affected by which part of the View is currently visible or its scroll
6720      * position.
6721      * <p>When <code>immediate</code> is set to true, scrolling will not be
6722      * animated.
6723      *
6724      * @param rectangle The rectangle in the View's content coordinate space
6725      * @param immediate True to forbid animated scrolling, false otherwise
6726      * @return Whether any parent scrolled.
6727      */
6728     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6729         if (mParent == null) {
6730             return false;
6731         }
6732 
6733         View child = this;
6734 
6735         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6736         position.set(rectangle);
6737 
6738         ViewParent parent = mParent;
6739         boolean scrolled = false;
6740         while (parent != null) {
6741             rectangle.set((int) position.left, (int) position.top,
6742                     (int) position.right, (int) position.bottom);
6743 
6744             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6745 
6746             if (!(parent instanceof View)) {
6747                 break;
6748             }
6749 
6750             // move it from child's content coordinate space to parent's content coordinate space
6751             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6752 
6753             child = (View) parent;
6754             parent = child.getParent();
6755         }
6756 
6757         return scrolled;
6758     }
6759 
6760     /**
6761      * Called when this view wants to give up focus. If focus is cleared
6762      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6763      * <p>
6764      * <strong>Note:</strong> When a View clears focus the framework is trying
6765      * to give focus to the first focusable View from the top. Hence, if this
6766      * View is the first from the top that can take focus, then all callbacks
6767      * related to clearing focus will be invoked after which the framework will
6768      * give focus to this view.
6769      * </p>
6770      */
6771     public void clearFocus() {
6772         if (DBG) {
6773             System.out.println(this + " clearFocus()");
6774         }
6775 
6776         clearFocusInternal(null, true, true);
6777     }
6778 
6779     /**
6780      * Clears focus from the view, optionally propagating the change up through
6781      * the parent hierarchy and requesting that the root view place new focus.
6782      *
6783      * @param propagate whether to propagate the change up through the parent
6784      *            hierarchy
6785      * @param refocus when propagate is true, specifies whether to request the
6786      *            root view place new focus
6787      */
6788     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6789         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6790             mPrivateFlags &= ~PFLAG_FOCUSED;
6791 
6792             if (propagate && mParent != null) {
6793                 mParent.clearChildFocus(this);
6794             }
6795 
6796             onFocusChanged(false, 0, null);
6797             refreshDrawableState();
6798 
6799             if (propagate && (!refocus || !rootViewRequestFocus())) {
6800                 notifyGlobalFocusCleared(this);
6801             }
6802         }
6803     }
6804 
6805     void notifyGlobalFocusCleared(View oldFocus) {
6806         if (oldFocus != null && mAttachInfo != null) {
6807             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6808         }
6809     }
6810 
6811     boolean rootViewRequestFocus() {
6812         final View root = getRootView();
6813         return root != null && root.requestFocus();
6814     }
6815 
6816     /**
6817      * Called internally by the view system when a new view is getting focus.
6818      * This is what clears the old focus.
6819      * <p>
6820      * <b>NOTE:</b> The parent view's focused child must be updated manually
6821      * after calling this method. Otherwise, the view hierarchy may be left in
6822      * an inconstent state.
6823      */
6824     void unFocus(View focused) {
6825         if (DBG) {
6826             System.out.println(this + " unFocus()");
6827         }
6828 
6829         clearFocusInternal(focused, false, false);
6830     }
6831 
6832     /**
6833      * Returns true if this view has focus itself, or is the ancestor of the
6834      * view that has focus.
6835      *
6836      * @return True if this view has or contains focus, false otherwise.
6837      */
6838     @ViewDebug.ExportedProperty(category = "focus")
6839     public boolean hasFocus() {
6840         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6841     }
6842 
6843     /**
6844      * Returns true if this view is focusable or if it contains a reachable View
6845      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6846      * is a view whose parents do not block descendants focus.
6847      * Only {@link #VISIBLE} views are considered focusable.
6848      *
6849      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6850      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6851      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6852      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6853      * {@code false} for views not explicitly marked as focusable.
6854      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6855      * behavior.</p>
6856      *
6857      * @return {@code true} if the view is focusable or if the view contains a focusable
6858      *         view, {@code false} otherwise
6859      *
6860      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6861      * @see ViewGroup#getTouchscreenBlocksFocus()
6862      * @see #hasExplicitFocusable()
6863      */
6864     public boolean hasFocusable() {
6865         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6866     }
6867 
6868     /**
6869      * Returns true if this view is focusable or if it contains a reachable View
6870      * for which {@link #hasExplicitFocusable()} returns {@code true}.
6871      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6872      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6873      * {@link #FOCUSABLE} are considered focusable.
6874      *
6875      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6876      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6877      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6878      * to focusable will not.</p>
6879      *
6880      * @return {@code true} if the view is focusable or if the view contains a focusable
6881      *         view, {@code false} otherwise
6882      *
6883      * @see #hasFocusable()
6884      */
6885     public boolean hasExplicitFocusable() {
6886         return hasFocusable(false, true);
6887     }
6888 
6889     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6890         if (!isFocusableInTouchMode()) {
6891             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6892                 final ViewGroup g = (ViewGroup) p;
6893                 if (g.shouldBlockFocusForTouchscreen()) {
6894                     return false;
6895                 }
6896             }
6897         }
6898 
6899         // Invisible and gone views are never focusable.
6900         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6901             return false;
6902         }
6903 
6904         // Only use effective focusable value when allowed.
6905         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6906             return true;
6907         }
6908 
6909         return false;
6910     }
6911 
6912     /**
6913      * Called by the view system when the focus state of this view changes.
6914      * When the focus change event is caused by directional navigation, direction
6915      * and previouslyFocusedRect provide insight into where the focus is coming from.
6916      * When overriding, be sure to call up through to the super class so that
6917      * the standard focus handling will occur.
6918      *
6919      * @param gainFocus True if the View has focus; false otherwise.
6920      * @param direction The direction focus has moved when requestFocus()
6921      *                  is called to give this view focus. Values are
6922      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6923      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6924      *                  It may not always apply, in which case use the default.
6925      * @param previouslyFocusedRect The rectangle, in this view's coordinate
6926      *        system, of the previously focused view.  If applicable, this will be
6927      *        passed in as finer grained information about where the focus is coming
6928      *        from (in addition to direction).  Will be <code>null</code> otherwise.
6929      */
6930     @CallSuper
6931     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6932             @Nullable Rect previouslyFocusedRect) {
6933         if (gainFocus) {
6934             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6935         } else {
6936             notifyViewAccessibilityStateChangedIfNeeded(
6937                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6938         }
6939 
6940         // Here we check whether we still need the default focus highlight, and switch it on/off.
6941         switchDefaultFocusHighlight();
6942 
6943         InputMethodManager imm = InputMethodManager.peekInstance();
6944         if (!gainFocus) {
6945             if (isPressed()) {
6946                 setPressed(false);
6947             }
6948             if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6949                 imm.focusOut(this);
6950             }
6951             onFocusLost();
6952         } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6953             imm.focusIn(this);
6954         }
6955 
6956         invalidate(true);
6957         ListenerInfo li = mListenerInfo;
6958         if (li != null && li.mOnFocusChangeListener != null) {
6959             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6960         }
6961 
6962         if (mAttachInfo != null) {
6963             mAttachInfo.mKeyDispatchState.reset(this);
6964         }
6965 
6966         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6967     }
6968 
6969     private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6970         if (isAutofillable() && isAttachedToWindow()) {
6971             AutofillManager afm = getAutofillManager();
6972             if (afm != null) {
6973                 if (enter && hasWindowFocus() && isFocused()) {
6974                     // We have not been laid out yet, hence cannot evaluate
6975                     // whether this view is visible to the user, we will do
6976                     // the evaluation once layout is complete.
6977                     if (!isLaidOut()) {
6978                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
6979                     } else if (isVisibleToUser()) {
6980                         afm.notifyViewEntered(this);
6981                     }
6982                 } else if (!hasWindowFocus() || !isFocused()) {
6983                     afm.notifyViewExited(this);
6984                 }
6985             }
6986         }
6987     }
6988 
6989     /**
6990      * Sends an accessibility event of the given type. If accessibility is
6991      * not enabled this method has no effect. The default implementation calls
6992      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6993      * to populate information about the event source (this View), then calls
6994      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6995      * populate the text content of the event source including its descendants,
6996      * and last calls
6997      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6998      * on its parent to request sending of the event to interested parties.
6999      * <p>
7000      * If an {@link AccessibilityDelegate} has been specified via calling
7001      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7002      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
7003      * responsible for handling this call.
7004      * </p>
7005      *
7006      * @param eventType The type of the event to send, as defined by several types from
7007      * {@link android.view.accessibility.AccessibilityEvent}, such as
7008      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
7009      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
7010      *
7011      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7012      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7013      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
7014      * @see AccessibilityDelegate
7015      */
7016     public void sendAccessibilityEvent(int eventType) {
7017         if (mAccessibilityDelegate != null) {
7018             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
7019         } else {
7020             sendAccessibilityEventInternal(eventType);
7021         }
7022     }
7023 
7024     /**
7025      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
7026      * {@link AccessibilityEvent} to make an announcement which is related to some
7027      * sort of a context change for which none of the events representing UI transitions
7028      * is a good fit. For example, announcing a new page in a book. If accessibility
7029      * is not enabled this method does nothing.
7030      *
7031      * @param text The announcement text.
7032      */
7033     public void announceForAccessibility(CharSequence text) {
7034         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
7035             AccessibilityEvent event = AccessibilityEvent.obtain(
7036                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
7037             onInitializeAccessibilityEvent(event);
7038             event.getText().add(text);
7039             event.setContentDescription(null);
7040             mParent.requestSendAccessibilityEvent(this, event);
7041         }
7042     }
7043 
7044     /**
7045      * @see #sendAccessibilityEvent(int)
7046      *
7047      * Note: Called from the default {@link AccessibilityDelegate}.
7048      *
7049      * @hide
7050      */
7051     public void sendAccessibilityEventInternal(int eventType) {
7052         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7053             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
7054         }
7055     }
7056 
7057     /**
7058      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
7059      * takes as an argument an empty {@link AccessibilityEvent} and does not
7060      * perform a check whether accessibility is enabled.
7061      * <p>
7062      * If an {@link AccessibilityDelegate} has been specified via calling
7063      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7064      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
7065      * is responsible for handling this call.
7066      * </p>
7067      *
7068      * @param event The event to send.
7069      *
7070      * @see #sendAccessibilityEvent(int)
7071      */
7072     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
7073         if (mAccessibilityDelegate != null) {
7074             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7075         } else {
7076             sendAccessibilityEventUncheckedInternal(event);
7077         }
7078     }
7079 
7080     /**
7081      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7082      *
7083      * Note: Called from the default {@link AccessibilityDelegate}.
7084      *
7085      * @hide
7086      */
7087     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
7088         if (!isShown()) {
7089             return;
7090         }
7091         onInitializeAccessibilityEvent(event);
7092         // Only a subset of accessibility events populates text content.
7093         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
7094             dispatchPopulateAccessibilityEvent(event);
7095         }
7096         // In the beginning we called #isShown(), so we know that getParent() is not null.
7097         ViewParent parent = getParent();
7098         if (parent != null) {
7099             getParent().requestSendAccessibilityEvent(this, event);
7100         }
7101     }
7102 
7103     /**
7104      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
7105      * to its children for adding their text content to the event. Note that the
7106      * event text is populated in a separate dispatch path since we add to the
7107      * event not only the text of the source but also the text of all its descendants.
7108      * A typical implementation will call
7109      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
7110      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7111      * on each child. Override this method if custom population of the event text
7112      * content is required.
7113      * <p>
7114      * If an {@link AccessibilityDelegate} has been specified via calling
7115      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7116      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
7117      * is responsible for handling this call.
7118      * </p>
7119      * <p>
7120      * <em>Note:</em> Accessibility events of certain types are not dispatched for
7121      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
7122      * </p>
7123      *
7124      * @param event The event.
7125      *
7126      * @return True if the event population was completed.
7127      */
7128     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7129         if (mAccessibilityDelegate != null) {
7130             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
7131         } else {
7132             return dispatchPopulateAccessibilityEventInternal(event);
7133         }
7134     }
7135 
7136     /**
7137      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7138      *
7139      * Note: Called from the default {@link AccessibilityDelegate}.
7140      *
7141      * @hide
7142      */
7143     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7144         onPopulateAccessibilityEvent(event);
7145         return false;
7146     }
7147 
7148     /**
7149      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7150      * giving a chance to this View to populate the accessibility event with its
7151      * text content. While this method is free to modify event
7152      * attributes other than text content, doing so should normally be performed in
7153      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7154      * <p>
7155      * Example: Adding formatted date string to an accessibility event in addition
7156      *          to the text added by the super implementation:
7157      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7158      *     super.onPopulateAccessibilityEvent(event);
7159      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7160      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7161      *         mCurrentDate.getTimeInMillis(), flags);
7162      *     event.getText().add(selectedDateUtterance);
7163      * }</pre>
7164      * <p>
7165      * If an {@link AccessibilityDelegate} has been specified via calling
7166      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7167      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7168      * is responsible for handling this call.
7169      * </p>
7170      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7171      * information to the event, in case the default implementation has basic information to add.
7172      * </p>
7173      *
7174      * @param event The accessibility event which to populate.
7175      *
7176      * @see #sendAccessibilityEvent(int)
7177      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7178      */
7179     @CallSuper
7180     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7181         if (mAccessibilityDelegate != null) {
7182             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7183         } else {
7184             onPopulateAccessibilityEventInternal(event);
7185         }
7186     }
7187 
7188     /**
7189      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7190      *
7191      * Note: Called from the default {@link AccessibilityDelegate}.
7192      *
7193      * @hide
7194      */
7195     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7196     }
7197 
7198     /**
7199      * Initializes an {@link AccessibilityEvent} with information about
7200      * this View which is the event source. In other words, the source of
7201      * an accessibility event is the view whose state change triggered firing
7202      * the event.
7203      * <p>
7204      * Example: Setting the password property of an event in addition
7205      *          to properties set by the super implementation:
7206      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7207      *     super.onInitializeAccessibilityEvent(event);
7208      *     event.setPassword(true);
7209      * }</pre>
7210      * <p>
7211      * If an {@link AccessibilityDelegate} has been specified via calling
7212      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7213      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7214      * is responsible for handling this call.
7215      * </p>
7216      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7217      * information to the event, in case the default implementation has basic information to add.
7218      * </p>
7219      * @param event The event to initialize.
7220      *
7221      * @see #sendAccessibilityEvent(int)
7222      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7223      */
7224     @CallSuper
7225     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7226         if (mAccessibilityDelegate != null) {
7227             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7228         } else {
7229             onInitializeAccessibilityEventInternal(event);
7230         }
7231     }
7232 
7233     /**
7234      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7235      *
7236      * Note: Called from the default {@link AccessibilityDelegate}.
7237      *
7238      * @hide
7239      */
7240     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7241         event.setSource(this);
7242         event.setClassName(getAccessibilityClassName());
7243         event.setPackageName(getContext().getPackageName());
7244         event.setEnabled(isEnabled());
7245         event.setContentDescription(mContentDescription);
7246 
7247         switch (event.getEventType()) {
7248             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7249                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
7250                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7251                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7252                 event.setItemCount(focusablesTempList.size());
7253                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7254                 if (mAttachInfo != null) {
7255                     focusablesTempList.clear();
7256                 }
7257             } break;
7258             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7259                 CharSequence text = getIterableTextForAccessibility();
7260                 if (text != null && text.length() > 0) {
7261                     event.setFromIndex(getAccessibilitySelectionStart());
7262                     event.setToIndex(getAccessibilitySelectionEnd());
7263                     event.setItemCount(text.length());
7264                 }
7265             } break;
7266         }
7267     }
7268 
7269     /**
7270      * Returns an {@link AccessibilityNodeInfo} representing this view from the
7271      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7272      * This method is responsible for obtaining an accessibility node info from a
7273      * pool of reusable instances and calling
7274      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7275      * initialize the former.
7276      * <p>
7277      * Note: The client is responsible for recycling the obtained instance by calling
7278      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7279      * </p>
7280      *
7281      * @return A populated {@link AccessibilityNodeInfo}.
7282      *
7283      * @see AccessibilityNodeInfo
7284      */
7285     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7286         if (mAccessibilityDelegate != null) {
7287             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7288         } else {
7289             return createAccessibilityNodeInfoInternal();
7290         }
7291     }
7292 
7293     /**
7294      * @see #createAccessibilityNodeInfo()
7295      *
7296      * @hide
7297      */
7298     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7299         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7300         if (provider != null) {
7301             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7302         } else {
7303             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7304             onInitializeAccessibilityNodeInfo(info);
7305             return info;
7306         }
7307     }
7308 
7309     /**
7310      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7311      * The base implementation sets:
7312      * <ul>
7313      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7314      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7315      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7316      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7317      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7318      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7319      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7320      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7321      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7322      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7323      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7324      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7325      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7326      * </ul>
7327      * <p>
7328      * Subclasses should override this method, call the super implementation,
7329      * and set additional attributes.
7330      * </p>
7331      * <p>
7332      * If an {@link AccessibilityDelegate} has been specified via calling
7333      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7334      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7335      * is responsible for handling this call.
7336      * </p>
7337      *
7338      * @param info The instance to initialize.
7339      */
7340     @CallSuper
7341     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7342         if (mAccessibilityDelegate != null) {
7343             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7344         } else {
7345             onInitializeAccessibilityNodeInfoInternal(info);
7346         }
7347     }
7348 
7349     /**
7350      * Gets the location of this view in screen coordinates.
7351      *
7352      * @param outRect The output location
7353      * @hide
7354      */
7355     public void getBoundsOnScreen(Rect outRect) {
7356         getBoundsOnScreen(outRect, false);
7357     }
7358 
7359     /**
7360      * Gets the location of this view in screen coordinates.
7361      *
7362      * @param outRect The output location
7363      * @param clipToParent Whether to clip child bounds to the parent ones.
7364      * @hide
7365      */
7366     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7367         if (mAttachInfo == null) {
7368             return;
7369         }
7370 
7371         RectF position = mAttachInfo.mTmpTransformRect;
7372         position.set(0, 0, mRight - mLeft, mBottom - mTop);
7373         mapRectFromViewToScreenCoords(position, clipToParent);
7374         outRect.set(Math.round(position.left), Math.round(position.top),
7375                 Math.round(position.right), Math.round(position.bottom));
7376     }
7377 
7378     /**
7379      * Map a rectangle from view-relative coordinates to screen-relative coordinates
7380      *
7381      * @param rect The rectangle to be mapped
7382      * @param clipToParent Whether to clip child bounds to the parent ones.
7383      * @hide
7384      */
7385     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7386         if (!hasIdentityMatrix()) {
7387             getMatrix().mapRect(rect);
7388         }
7389 
7390         rect.offset(mLeft, mTop);
7391 
7392         ViewParent parent = mParent;
7393         while (parent instanceof View) {
7394             View parentView = (View) parent;
7395 
7396             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7397 
7398             if (clipToParent) {
7399                 rect.left = Math.max(rect.left, 0);
7400                 rect.top = Math.max(rect.top, 0);
7401                 rect.right = Math.min(rect.right, parentView.getWidth());
7402                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7403             }
7404 
7405             if (!parentView.hasIdentityMatrix()) {
7406                 parentView.getMatrix().mapRect(rect);
7407             }
7408 
7409             rect.offset(parentView.mLeft, parentView.mTop);
7410 
7411             parent = parentView.mParent;
7412         }
7413 
7414         if (parent instanceof ViewRootImpl) {
7415             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7416             rect.offset(0, -viewRootImpl.mCurScrollY);
7417         }
7418 
7419         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7420     }
7421 
7422     /**
7423      * Return the class name of this object to be used for accessibility purposes.
7424      * Subclasses should only override this if they are implementing something that
7425      * should be seen as a completely new class of view when used by accessibility,
7426      * unrelated to the class it is deriving from.  This is used to fill in
7427      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7428      */
7429     public CharSequence getAccessibilityClassName() {
7430         return View.class.getName();
7431     }
7432 
7433     /**
7434      * Called when assist structure is being retrieved from a view as part of
7435      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7436      * @param structure Fill in with structured view data.  The default implementation
7437      * fills in all data that can be inferred from the view itself.
7438      */
7439     public void onProvideStructure(ViewStructure structure) {
7440         onProvideStructureForAssistOrAutofill(structure, false, 0);
7441     }
7442 
7443     /**
7444      * Populates a {@link ViewStructure} to fullfil an autofill request.
7445      *
7446      * <p>The structure should contain at least the following properties:
7447      * <ul>
7448      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
7449      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
7450      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
7451      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
7452      * </ul>
7453      *
7454      * <p>It's also recommended to set the following properties - the more properties the structure
7455      * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
7456      * using the structure:
7457      *
7458      * <ul>
7459      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
7460      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
7461      *       view can only be filled with predefined values (typically used when the autofill type
7462      *       is {@link #AUTOFILL_TYPE_LIST}).
7463      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
7464      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
7465      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
7466      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
7467      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
7468      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
7469      *   <li>For views representing text fields, text properties such as the text itself
7470      *       ({@link ViewStructure#setText(CharSequence)}), text hints
7471      *       ({@link ViewStructure#setHint(CharSequence)}, input type
7472      *       ({@link ViewStructure#setInputType(int)}),
7473      *   <li>For views representing HTML nodes, its web domain
7474      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
7475      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
7476      * </ul>
7477      *
7478      * <p>The default implementation of this method already sets most of these properties based on
7479      * related {@link View} methods (for example, the autofill id is set using
7480      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
7481      * and views in the standard Android widgets library also override it to set their
7482      * relevant properties (for example, {@link android.widget.TextView} already sets the text
7483      * properties), so it's recommended to only override this method
7484      * (and call {@code super.onProvideAutofillStructure()}) when:
7485      *
7486      * <ul>
7487      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7488      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7489      *   <li>The view can only be autofilled with predefined options, so it can call
7490      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
7491      * </ul>
7492      *
7493      * <p><b>Note:</b> The {@code left} and {@code top} values set in
7494      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
7495      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
7496      *
7497      * <p>Views support the Autofill Framework mainly by:
7498      * <ul>
7499      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7500      *   <li>Notifying the Android System when the view value changed by calling
7501      *       {@link AutofillManager#notifyValueChanged(View)}.
7502      *   <li>Implementing the methods that autofill the view.
7503      * </ul>
7504      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
7505      * for the latter.
7506      *
7507      * @param structure fill in with structured view data for autofill purposes.
7508      * @param flags optional flags.
7509      *
7510      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7511      */
7512     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
7513         onProvideStructureForAssistOrAutofill(structure, true, flags);
7514     }
7515 
7516     private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7517             boolean forAutofill, @AutofillFlags int flags) {
7518         final int id = mID;
7519         if (id != NO_ID && !isViewIdGenerated(id)) {
7520             String pkg, type, entry;
7521             try {
7522                 final Resources res = getResources();
7523                 entry = res.getResourceEntryName(id);
7524                 type = res.getResourceTypeName(id);
7525                 pkg = res.getResourcePackageName(id);
7526             } catch (Resources.NotFoundException e) {
7527                 entry = type = pkg = null;
7528             }
7529             structure.setId(id, pkg, type, entry);
7530         } else {
7531             structure.setId(id, null, null, null);
7532         }
7533 
7534         if (forAutofill) {
7535             final @AutofillType int autofillType = getAutofillType();
7536             // Don't need to fill autofill info if view does not support it.
7537             // For example, only TextViews that are editable support autofill
7538             if (autofillType != AUTOFILL_TYPE_NONE) {
7539                 structure.setAutofillType(autofillType);
7540                 structure.setAutofillHints(getAutofillHints());
7541                 structure.setAutofillValue(getAutofillValue());
7542             }
7543         }
7544 
7545         int ignoredParentLeft = 0;
7546         int ignoredParentTop = 0;
7547         if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
7548             View parentGroup = null;
7549 
7550             ViewParent viewParent = getParent();
7551             if (viewParent instanceof View) {
7552                 parentGroup = (View) viewParent;
7553             }
7554 
7555             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
7556                 ignoredParentLeft += parentGroup.mLeft;
7557                 ignoredParentTop += parentGroup.mTop;
7558 
7559                 viewParent = parentGroup.getParent();
7560                 if (viewParent instanceof View) {
7561                     parentGroup = (View) viewParent;
7562                 } else {
7563                     break;
7564                 }
7565             }
7566         }
7567 
7568         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
7569                 mRight - mLeft, mBottom - mTop);
7570         if (!forAutofill) {
7571             if (!hasIdentityMatrix()) {
7572                 structure.setTransformation(getMatrix());
7573             }
7574             structure.setElevation(getZ());
7575         }
7576         structure.setVisibility(getVisibility());
7577         structure.setEnabled(isEnabled());
7578         if (isClickable()) {
7579             structure.setClickable(true);
7580         }
7581         if (isFocusable()) {
7582             structure.setFocusable(true);
7583         }
7584         if (isFocused()) {
7585             structure.setFocused(true);
7586         }
7587         if (isAccessibilityFocused()) {
7588             structure.setAccessibilityFocused(true);
7589         }
7590         if (isSelected()) {
7591             structure.setSelected(true);
7592         }
7593         if (isActivated()) {
7594             structure.setActivated(true);
7595         }
7596         if (isLongClickable()) {
7597             structure.setLongClickable(true);
7598         }
7599         if (this instanceof Checkable) {
7600             structure.setCheckable(true);
7601             if (((Checkable)this).isChecked()) {
7602                 structure.setChecked(true);
7603             }
7604         }
7605         if (isOpaque()) {
7606             structure.setOpaque(true);
7607         }
7608         if (isContextClickable()) {
7609             structure.setContextClickable(true);
7610         }
7611         structure.setClassName(getAccessibilityClassName().toString());
7612         structure.setContentDescription(getContentDescription());
7613     }
7614 
7615     /**
7616      * Called when assist structure is being retrieved from a view as part of
7617      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7618      * generate additional virtual structure under this view.  The defaullt implementation
7619      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7620      * view's virtual accessibility nodes, if any.  You can override this for a more
7621      * optimal implementation providing this data.
7622      */
7623     public void onProvideVirtualStructure(ViewStructure structure) {
7624         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7625         if (provider != null) {
7626             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7627             structure.setChildCount(1);
7628             ViewStructure root = structure.newChild(0);
7629             populateVirtualStructure(root, provider, info);
7630             info.recycle();
7631         }
7632     }
7633 
7634     /**
7635      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
7636      * request.
7637      *
7638      * <p>This method should be used when the view manages a virtual structure under this view. For
7639      * example, a view that draws input fields using {@link #draw(Canvas)}.
7640      *
7641      * <p>When implementing this method, subclasses must follow the rules below:
7642      *
7643      * <ul>
7644      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
7645      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
7646      *       identifying the children in the virtual structure.
7647      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
7648      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
7649      *       autofill performance.
7650      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7651      *       children.
7652      *   <li>Set the autofill properties of the child structure as defined by
7653      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
7654      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
7655      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
7656      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7657      *       when the focused virtual child changed.
7658      *   <li>Call
7659      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
7660      *       when the value of a virtual child changed.
7661      *   <li>Call
7662      *    {@link
7663      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
7664      *       when the visibility of a virtual child changed.
7665      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
7666      *       changed and the current context should be committed (for example, when the user tapped
7667      *       a {@code SUBMIT} button in an HTML page).
7668      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
7669      *       changed and the current context should be canceled (for example, when the user tapped
7670      *       a {@code CANCEL} button in an HTML page).
7671      *   <li>Provide ways for users to manually request autofill by calling
7672      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
7673      *   <li>The {@code left} and {@code top} values set in
7674      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
7675      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
7676      *       structure.
7677      * </ul>
7678      *
7679      * <p>Views with virtual children support the Autofill Framework mainly by:
7680      * <ul>
7681      *   <li>Providing the metadata defining what the virtual children mean and how they can be
7682      *       autofilled.
7683      *   <li>Implementing the methods that autofill the virtual children.
7684      * </ul>
7685      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
7686      * for the latter.
7687      *
7688      * @param structure fill in with virtual children data for autofill purposes.
7689      * @param flags optional flags.
7690      *
7691      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7692      */
7693     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7694     }
7695 
7696     /**
7697      * Automatically fills the content of this view with the {@code value}.
7698      *
7699      * <p>Views support the Autofill Framework mainly by:
7700      * <ul>
7701      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7702      *   <li>Implementing the methods that autofill the view.
7703      * </ul>
7704      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
7705      * this method is responsible for latter.
7706      *
7707      * <p>This method does nothing by default, but when overridden it typically:
7708      * <ol>
7709      *   <li>Checks if the provided value matches the expected type (which is defined by
7710      *       {@link #getAutofillType()}).
7711      *   <li>Checks if the view is editable - if it isn't, it should return right away.
7712      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
7713      *   <li>Pass the actual value to the equivalent setter in the view.
7714      * </ol>
7715      *
7716      * <p>For example, a text-field view could implement the method this way:
7717      *
7718      * <pre class="prettyprint">
7719      * &#64;Override
7720      * public void autofill(AutofillValue value) {
7721      *   if (!value.isText() || !this.isEditable()) {
7722      *      return;
7723      *   }
7724      *   CharSequence text = value.getTextValue();
7725      *   if (text != null) {
7726      *     this.setText(text);
7727      *   }
7728      * }
7729      * </pre>
7730      *
7731      * <p>If the value is updated asynchronously, the next call to
7732      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
7733      * changed to the autofilled value. If not, the view will not be considered autofilled.
7734      *
7735      * <p><b>Note:</b> After this method is called, the value returned by
7736      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
7737      * view will not be highlighted as autofilled.
7738      *
7739      * @param value value to be autofilled.
7740      */
7741     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7742     }
7743 
7744     /**
7745      * Automatically fills the content of the virtual children within this view.
7746      *
7747      * <p>Views with virtual children support the Autofill Framework mainly by:
7748      * <ul>
7749      *   <li>Providing the metadata defining what the virtual children mean and how they can be
7750      *       autofilled.
7751      *   <li>Implementing the methods that autofill the virtual children.
7752      * </ul>
7753      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
7754      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
7755      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
7756      *
7757      * <p>If a child value is updated asynchronously, the next call to
7758      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
7759      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
7760      * considered autofilled.
7761      *
7762      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
7763      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
7764      * changes.
7765      *
7766      * @param values map of values to be autofilled, keyed by virtual child id.
7767      *
7768      * @attr ref android.R.styleable#Theme_autofilledHighlight
7769      */
7770     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7771     }
7772 
7773     /**
7774      * Gets the unique identifier of this view in the screen, for autofill purposes.
7775      *
7776      * @return The View's autofill id.
7777      */
7778     public final AutofillId getAutofillId() {
7779         if (mAutofillId == null) {
7780             // The autofill id needs to be unique, but its value doesn't matter,
7781             // so it's better to reuse the accessibility id to save space.
7782             mAutofillId = new AutofillId(getAutofillViewId());
7783         }
7784         return mAutofillId;
7785     }
7786 
7787     /**
7788      * Describes the autofill type of this view, so an
7789      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
7790      * when autofilling the view.
7791      *
7792      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
7793      * support the Autofill Framework.
7794      *
7795      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
7796      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
7797      *
7798      * @see #onProvideAutofillStructure(ViewStructure, int)
7799      * @see #autofill(AutofillValue)
7800      */
7801     public @AutofillType int getAutofillType() {
7802         return AUTOFILL_TYPE_NONE;
7803     }
7804 
7805     /**
7806      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
7807      * to autofill the view with the user's data.
7808      *
7809      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
7810      *
7811      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
7812      * {@code null} if no hints were set.
7813      *
7814      * @attr ref android.R.styleable#View_autofillHints
7815      */
7816     @ViewDebug.ExportedProperty()
7817     @Nullable public String[] getAutofillHints() {
7818         return mAutofillHints;
7819     }
7820 
7821     /**
7822      * @hide
7823      */
7824     public boolean isAutofilled() {
7825         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7826     }
7827 
7828     /**
7829      * Gets the {@link View}'s current autofill value.
7830      *
7831      * <p>By default returns {@code null}, but subclasses should override it and return an
7832      * appropriate value to properly support the Autofill Framework.
7833      *
7834      * @see #onProvideAutofillStructure(ViewStructure, int)
7835      * @see #autofill(AutofillValue)
7836      */
7837     @Nullable
7838     public AutofillValue getAutofillValue() {
7839         return null;
7840     }
7841 
7842     /**
7843      * Gets the mode for determining whether this view is important for autofill.
7844      *
7845      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
7846      * info about this mode.
7847      *
7848      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7849      * {@link #setImportantForAutofill(int)}.
7850      *
7851      * @attr ref android.R.styleable#View_importantForAutofill
7852      */
7853     @ViewDebug.ExportedProperty(mapping = {
7854             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7855             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7856             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7857             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7858                 to = "yesExcludeDescendants"),
7859             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7860                 to = "noExcludeDescendants")})
7861     public @AutofillImportance int getImportantForAutofill() {
7862         return (mPrivateFlags3
7863                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7864     }
7865 
7866     /**
7867      * Sets the mode for determining whether this view is considered important for autofill.
7868      *
7869      * <p>The platform determines the importance for autofill automatically but you
7870      * can use this method to customize the behavior. For example:
7871      *
7872      * <ol>
7873      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
7874      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7875      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
7876      *       view of an activity containing a spreadhseet editor), it should be
7877      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7878      *   <li>When the view content is relevant for autofill but its children aren't (for example,
7879      *       a credit card expiration date represented by a custom view that overrides the proper
7880      *       autofill methods and has 2 children representing the month and year), it should
7881      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
7882      * </ol>
7883      *
7884      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7885      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
7886      * children) will be always be considered not important; for example, when the user explicitly
7887      * makes an autofill request, all views are considered important. See
7888      * {@link #isImportantForAutofill()} for more details about how the View's importance for
7889      * autofill is used.
7890      *
7891      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7892      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7893      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7894      *
7895      * @attr ref android.R.styleable#View_importantForAutofill
7896      */
7897     public void setImportantForAutofill(@AutofillImportance int mode) {
7898         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7899         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7900                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7901     }
7902 
7903     /**
7904      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7905      * associated with this view is considered important for autofill purposes.
7906      *
7907      * <p>Generally speaking, a view is important for autofill if:
7908      * <ol>
7909      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
7910      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
7911      *     determine how other views can be autofilled.
7912      * <ol>
7913      *
7914      * <p>For example, view containers should typically return {@code false} for performance reasons
7915      * (since the important info is provided by their children), but if its properties have relevant
7916      * information (for example, a resource id called {@code credentials}, it should return
7917      * {@code true}. On the other hand, views representing labels or editable fields should
7918      * typically return {@code true}, but in some cases they could return {@code false}
7919      * (for example, if they're part of a "Captcha" mechanism).
7920      *
7921      * <p>The value returned by this method depends on the value returned by
7922      * {@link #getImportantForAutofill()}:
7923      *
7924      * <ol>
7925      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
7926      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
7927      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7928      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
7929      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
7930      *       that can return {@code true} in some cases (like a container with a resource id),
7931      *       but {@code false} in most.
7932      *   <li>otherwise, it returns {@code false}.
7933      * </ol>
7934      *
7935      * <p>When a view is considered important for autofill:
7936      * <ul>
7937      *   <li>The view might automatically trigger an autofill request when focused on.
7938      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
7939      *       request.
7940      * </ul>
7941      *
7942      * <p>On the other hand, when a view is considered not important for autofill:
7943      * <ul>
7944      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
7945      *       request through {@link AutofillManager#requestAutofill(View)}.
7946      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
7947      *       autofill request, unless the request has the
7948      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
7949      * </ul>
7950      *
7951      * @return whether the view is considered important for autofill.
7952      *
7953      * @see #setImportantForAutofill(int)
7954      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7955      * @see #IMPORTANT_FOR_AUTOFILL_YES
7956      * @see #IMPORTANT_FOR_AUTOFILL_NO
7957      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7958      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7959      * @see AutofillManager#requestAutofill(View)
7960      */
7961     public final boolean isImportantForAutofill() {
7962         // Check parent mode to ensure we're not hidden.
7963         ViewParent parent = mParent;
7964         while (parent instanceof View) {
7965             final int parentImportance = ((View) parent).getImportantForAutofill();
7966             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7967                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
7968                 return false;
7969             }
7970             parent = parent.getParent();
7971         }
7972 
7973         final int importance = getImportantForAutofill();
7974 
7975         // First, check the explicit states.
7976         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7977                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
7978             return true;
7979         }
7980         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7981                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
7982             return false;
7983         }
7984 
7985         // Then use some heuristics to handle AUTO.
7986 
7987         // Always include views that have an explicit resource id.
7988         final int id = mID;
7989         if (id != NO_ID && !isViewIdGenerated(id)) {
7990             final Resources res = getResources();
7991             String entry = null;
7992             String pkg = null;
7993             try {
7994                 entry = res.getResourceEntryName(id);
7995                 pkg = res.getResourcePackageName(id);
7996             } catch (Resources.NotFoundException e) {
7997                 // ignore
7998             }
7999             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
8000                 return true;
8001             }
8002         }
8003 
8004         // Otherwise, assume it's not important...
8005         return false;
8006     }
8007 
8008     @Nullable
8009     private AutofillManager getAutofillManager() {
8010         return mContext.getSystemService(AutofillManager.class);
8011     }
8012 
8013     private boolean isAutofillable() {
8014         return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
8015                 && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
8016     }
8017 
8018     private void populateVirtualStructure(ViewStructure structure,
8019             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
8020         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
8021                 null, null, null);
8022         Rect rect = structure.getTempRect();
8023         info.getBoundsInParent(rect);
8024         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
8025         structure.setVisibility(VISIBLE);
8026         structure.setEnabled(info.isEnabled());
8027         if (info.isClickable()) {
8028             structure.setClickable(true);
8029         }
8030         if (info.isFocusable()) {
8031             structure.setFocusable(true);
8032         }
8033         if (info.isFocused()) {
8034             structure.setFocused(true);
8035         }
8036         if (info.isAccessibilityFocused()) {
8037             structure.setAccessibilityFocused(true);
8038         }
8039         if (info.isSelected()) {
8040             structure.setSelected(true);
8041         }
8042         if (info.isLongClickable()) {
8043             structure.setLongClickable(true);
8044         }
8045         if (info.isCheckable()) {
8046             structure.setCheckable(true);
8047             if (info.isChecked()) {
8048                 structure.setChecked(true);
8049             }
8050         }
8051         if (info.isContextClickable()) {
8052             structure.setContextClickable(true);
8053         }
8054         CharSequence cname = info.getClassName();
8055         structure.setClassName(cname != null ? cname.toString() : null);
8056         structure.setContentDescription(info.getContentDescription());
8057         if ((info.getText() != null || info.getError() != null)) {
8058             structure.setText(info.getText(), info.getTextSelectionStart(),
8059                     info.getTextSelectionEnd());
8060         }
8061         final int NCHILDREN = info.getChildCount();
8062         if (NCHILDREN > 0) {
8063             structure.setChildCount(NCHILDREN);
8064             for (int i=0; i<NCHILDREN; i++) {
8065                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
8066                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
8067                 ViewStructure child = structure.newChild(i);
8068                 populateVirtualStructure(child, provider, cinfo);
8069                 cinfo.recycle();
8070             }
8071         }
8072     }
8073 
8074     /**
8075      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
8076      * implementation calls {@link #onProvideStructure} and
8077      * {@link #onProvideVirtualStructure}.
8078      */
8079     public void dispatchProvideStructure(ViewStructure structure) {
8080         dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
8081     }
8082 
8083     /**
8084      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
8085      * when an Assist structure is being created as part of an autofill request.
8086      *
8087      * <p>The default implementation does the following:
8088      * <ul>
8089      *   <li>Sets the {@link AutofillId} in the structure.
8090      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
8091      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
8092      * </ul>
8093      *
8094      * <p>Typically, this method should only be overridden by subclasses that provide a view
8095      * hierarchy (such as {@link ViewGroup}) - other classes should override
8096      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
8097      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
8098      *
8099      * <p>When overridden, it must:
8100      *
8101      * <ul>
8102      *   <li>Either call
8103      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
8104      *       set the {@link AutofillId} in the structure (for example, by calling
8105      *       {@code structure.setAutofillId(getAutofillId())}).
8106      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
8107      *       set, all views in the structure should be considered important for autofill,
8108      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
8109      *       respect this flag to provide a better user experience - this flag is typically used
8110      *       when an user explicitly requested autofill. If the flag is not set,
8111      *       then only views marked as important for autofill should be included in the
8112      *       structure - skipping non-important views optimizes the overall autofill performance.
8113      * </ul>
8114      *
8115      * @param structure fill in with structured view data for autofill purposes.
8116      * @param flags optional flags.
8117      *
8118      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8119      */
8120     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
8121             @AutofillFlags int flags) {
8122         dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
8123     }
8124 
8125     private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
8126             boolean forAutofill, @AutofillFlags int flags) {
8127         if (forAutofill) {
8128             structure.setAutofillId(getAutofillId());
8129             onProvideAutofillStructure(structure, flags);
8130             onProvideAutofillVirtualStructure(structure, flags);
8131         } else if (!isAssistBlocked()) {
8132             onProvideStructure(structure);
8133             onProvideVirtualStructure(structure);
8134         } else {
8135             structure.setClassName(getAccessibilityClassName().toString());
8136             structure.setAssistBlocked(true);
8137         }
8138     }
8139 
8140     /**
8141      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
8142      *
8143      * Note: Called from the default {@link AccessibilityDelegate}.
8144      *
8145      * @hide
8146      */
8147     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
8148         if (mAttachInfo == null) {
8149             return;
8150         }
8151 
8152         Rect bounds = mAttachInfo.mTmpInvalRect;
8153 
8154         getDrawingRect(bounds);
8155         info.setBoundsInParent(bounds);
8156 
8157         getBoundsOnScreen(bounds, true);
8158         info.setBoundsInScreen(bounds);
8159 
8160         ViewParent parent = getParentForAccessibility();
8161         if (parent instanceof View) {
8162             info.setParent((View) parent);
8163         }
8164 
8165         if (mID != View.NO_ID) {
8166             View rootView = getRootView();
8167             if (rootView == null) {
8168                 rootView = this;
8169             }
8170 
8171             View label = rootView.findLabelForView(this, mID);
8172             if (label != null) {
8173                 info.setLabeledBy(label);
8174             }
8175 
8176             if ((mAttachInfo.mAccessibilityFetchFlags
8177                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
8178                     && Resources.resourceHasPackage(mID)) {
8179                 try {
8180                     String viewId = getResources().getResourceName(mID);
8181                     info.setViewIdResourceName(viewId);
8182                 } catch (Resources.NotFoundException nfe) {
8183                     /* ignore */
8184                 }
8185             }
8186         }
8187 
8188         if (mLabelForId != View.NO_ID) {
8189             View rootView = getRootView();
8190             if (rootView == null) {
8191                 rootView = this;
8192             }
8193             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
8194             if (labeled != null) {
8195                 info.setLabelFor(labeled);
8196             }
8197         }
8198 
8199         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
8200             View rootView = getRootView();
8201             if (rootView == null) {
8202                 rootView = this;
8203             }
8204             View next = rootView.findViewInsideOutShouldExist(this,
8205                     mAccessibilityTraversalBeforeId);
8206             if (next != null && next.includeForAccessibility()) {
8207                 info.setTraversalBefore(next);
8208             }
8209         }
8210 
8211         if (mAccessibilityTraversalAfterId != View.NO_ID) {
8212             View rootView = getRootView();
8213             if (rootView == null) {
8214                 rootView = this;
8215             }
8216             View next = rootView.findViewInsideOutShouldExist(this,
8217                     mAccessibilityTraversalAfterId);
8218             if (next != null && next.includeForAccessibility()) {
8219                 info.setTraversalAfter(next);
8220             }
8221         }
8222 
8223         info.setVisibleToUser(isVisibleToUser());
8224 
8225         info.setImportantForAccessibility(isImportantForAccessibility());
8226         info.setPackageName(mContext.getPackageName());
8227         info.setClassName(getAccessibilityClassName());
8228         info.setContentDescription(getContentDescription());
8229 
8230         info.setEnabled(isEnabled());
8231         info.setClickable(isClickable());
8232         info.setFocusable(isFocusable());
8233         info.setFocused(isFocused());
8234         info.setAccessibilityFocused(isAccessibilityFocused());
8235         info.setSelected(isSelected());
8236         info.setLongClickable(isLongClickable());
8237         info.setContextClickable(isContextClickable());
8238         info.setLiveRegion(getAccessibilityLiveRegion());
8239 
8240         // TODO: These make sense only if we are in an AdapterView but all
8241         // views can be selected. Maybe from accessibility perspective
8242         // we should report as selectable view in an AdapterView.
8243         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
8244         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
8245 
8246         if (isFocusable()) {
8247             if (isFocused()) {
8248                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
8249             } else {
8250                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
8251             }
8252         }
8253 
8254         if (!isAccessibilityFocused()) {
8255             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
8256         } else {
8257             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
8258         }
8259 
8260         if (isClickable() && isEnabled()) {
8261             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
8262         }
8263 
8264         if (isLongClickable() && isEnabled()) {
8265             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
8266         }
8267 
8268         if (isContextClickable() && isEnabled()) {
8269             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
8270         }
8271 
8272         CharSequence text = getIterableTextForAccessibility();
8273         if (text != null && text.length() > 0) {
8274             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
8275 
8276             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
8277             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
8278             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
8279             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
8280                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
8281                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
8282         }
8283 
8284         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
8285         populateAccessibilityNodeInfoDrawingOrderInParent(info);
8286     }
8287 
8288     /**
8289      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
8290      * additional data.
8291      * <p>
8292      * This method only needs overloading if the node is marked as having extra data available.
8293      * </p>
8294      *
8295      * @param info The info to which to add the extra data. Never {@code null}.
8296      * @param extraDataKey A key specifying the type of extra data to add to the info. The
8297      *                     extra data should be added to the {@link Bundle} returned by
8298      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
8299      *                     {@code null}.
8300      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
8301      *                  {@code null} if the service provided no arguments.
8302      *
8303      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
8304      */
8305     public void addExtraDataToAccessibilityNodeInfo(
8306             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
8307             @Nullable Bundle arguments) {
8308     }
8309 
8310     /**
8311      * Determine the order in which this view will be drawn relative to its siblings for a11y
8312      *
8313      * @param info The info whose drawing order should be populated
8314      */
8315     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8316         /*
8317          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8318          * drawing order may not be well-defined, and some Views with custom drawing order may
8319          * not be initialized sufficiently to respond properly getChildDrawingOrder.
8320          */
8321         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8322             info.setDrawingOrder(0);
8323             return;
8324         }
8325         int drawingOrderInParent = 1;
8326         // Iterate up the hierarchy if parents are not important for a11y
8327         View viewAtDrawingLevel = this;
8328         final ViewParent parent = getParentForAccessibility();
8329         while (viewAtDrawingLevel != parent) {
8330             final ViewParent currentParent = viewAtDrawingLevel.getParent();
8331             if (!(currentParent instanceof ViewGroup)) {
8332                 // Should only happen for the Decor
8333                 drawingOrderInParent = 0;
8334                 break;
8335             } else {
8336                 final ViewGroup parentGroup = (ViewGroup) currentParent;
8337                 final int childCount = parentGroup.getChildCount();
8338                 if (childCount > 1) {
8339                     List<View> preorderedList = parentGroup.buildOrderedChildList();
8340                     if (preorderedList != null) {
8341                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8342                         for (int i = 0; i < childDrawIndex; i++) {
8343                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8344                         }
8345                     } else {
8346                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8347                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8348                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8349                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
8350                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8351                         if (childDrawIndex != 0) {
8352                             for (int i = 0; i < numChildrenToIterate; i++) {
8353                                 final int otherDrawIndex = (customOrder ?
8354                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
8355                                 if (otherDrawIndex < childDrawIndex) {
8356                                     drawingOrderInParent +=
8357                                             numViewsForAccessibility(parentGroup.getChildAt(i));
8358                                 }
8359                             }
8360                         }
8361                     }
8362                 }
8363             }
8364             viewAtDrawingLevel = (View) currentParent;
8365         }
8366         info.setDrawingOrder(drawingOrderInParent);
8367     }
8368 
numViewsForAccessibility(View view)8369     private static int numViewsForAccessibility(View view) {
8370         if (view != null) {
8371             if (view.includeForAccessibility()) {
8372                 return 1;
8373             } else if (view instanceof ViewGroup) {
8374                 return ((ViewGroup) view).getNumChildrenForAccessibility();
8375             }
8376         }
8377         return 0;
8378     }
8379 
findLabelForView(View view, int labeledId)8380     private View findLabelForView(View view, int labeledId) {
8381         if (mMatchLabelForPredicate == null) {
8382             mMatchLabelForPredicate = new MatchLabelForPredicate();
8383         }
8384         mMatchLabelForPredicate.mLabeledId = labeledId;
8385         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8386     }
8387 
8388     /**
8389      * Computes whether this view is visible to the user. Such a view is
8390      * attached, visible, all its predecessors are visible, it is not clipped
8391      * entirely by its predecessors, and has an alpha greater than zero.
8392      *
8393      * @return Whether the view is visible on the screen.
8394      *
8395      * @hide
8396      */
isVisibleToUser()8397     protected boolean isVisibleToUser() {
8398         return isVisibleToUser(null);
8399     }
8400 
8401     /**
8402      * Computes whether the given portion of this view is visible to the user.
8403      * Such a view is attached, visible, all its predecessors are visible,
8404      * has an alpha greater than zero, and the specified portion is not
8405      * clipped entirely by its predecessors.
8406      *
8407      * @param boundInView the portion of the view to test; coordinates should be relative; may be
8408      *                    <code>null</code>, and the entire view will be tested in this case.
8409      *                    When <code>true</code> is returned by the function, the actual visible
8410      *                    region will be stored in this parameter; that is, if boundInView is fully
8411      *                    contained within the view, no modification will be made, otherwise regions
8412      *                    outside of the visible area of the view will be clipped.
8413      *
8414      * @return Whether the specified portion of the view is visible on the screen.
8415      *
8416      * @hide
8417      */
isVisibleToUser(Rect boundInView)8418     protected boolean isVisibleToUser(Rect boundInView) {
8419         if (mAttachInfo != null) {
8420             // Attached to invisible window means this view is not visible.
8421             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8422                 return false;
8423             }
8424             // An invisible predecessor or one with alpha zero means
8425             // that this view is not visible to the user.
8426             Object current = this;
8427             while (current instanceof View) {
8428                 View view = (View) current;
8429                 // We have attach info so this view is attached and there is no
8430                 // need to check whether we reach to ViewRootImpl on the way up.
8431                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8432                         view.getVisibility() != VISIBLE) {
8433                     return false;
8434                 }
8435                 current = view.mParent;
8436             }
8437             // Check if the view is entirely covered by its predecessors.
8438             Rect visibleRect = mAttachInfo.mTmpInvalRect;
8439             Point offset = mAttachInfo.mPoint;
8440             if (!getGlobalVisibleRect(visibleRect, offset)) {
8441                 return false;
8442             }
8443             // Check if the visible portion intersects the rectangle of interest.
8444             if (boundInView != null) {
8445                 visibleRect.offset(-offset.x, -offset.y);
8446                 return boundInView.intersect(visibleRect);
8447             }
8448             return true;
8449         }
8450         return false;
8451     }
8452 
8453     /**
8454      * Returns the delegate for implementing accessibility support via
8455      * composition. For more details see {@link AccessibilityDelegate}.
8456      *
8457      * @return The delegate, or null if none set.
8458      *
8459      * @hide
8460      */
getAccessibilityDelegate()8461     public AccessibilityDelegate getAccessibilityDelegate() {
8462         return mAccessibilityDelegate;
8463     }
8464 
8465     /**
8466      * Sets a delegate for implementing accessibility support via composition
8467      * (as opposed to inheritance). For more details, see
8468      * {@link AccessibilityDelegate}.
8469      * <p>
8470      * <strong>Note:</strong> On platform versions prior to
8471      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8472      * views in the {@code android.widget.*} package are called <i>before</i>
8473      * host methods. This prevents certain properties such as class name from
8474      * being modified by overriding
8475      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8476      * as any changes will be overwritten by the host class.
8477      * <p>
8478      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8479      * methods are called <i>after</i> host methods, which all properties to be
8480      * modified without being overwritten by the host class.
8481      *
8482      * @param delegate the object to which accessibility method calls should be
8483      *                 delegated
8484      * @see AccessibilityDelegate
8485      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)8486     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8487         mAccessibilityDelegate = delegate;
8488     }
8489 
8490     /**
8491      * Gets the provider for managing a virtual view hierarchy rooted at this View
8492      * and reported to {@link android.accessibilityservice.AccessibilityService}s
8493      * that explore the window content.
8494      * <p>
8495      * If this method returns an instance, this instance is responsible for managing
8496      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8497      * View including the one representing the View itself. Similarly the returned
8498      * instance is responsible for performing accessibility actions on any virtual
8499      * view or the root view itself.
8500      * </p>
8501      * <p>
8502      * If an {@link AccessibilityDelegate} has been specified via calling
8503      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8504      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8505      * is responsible for handling this call.
8506      * </p>
8507      *
8508      * @return The provider.
8509      *
8510      * @see AccessibilityNodeProvider
8511      */
getAccessibilityNodeProvider()8512     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8513         if (mAccessibilityDelegate != null) {
8514             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8515         } else {
8516             return null;
8517         }
8518     }
8519 
8520     /**
8521      * Gets the unique identifier of this view on the screen for accessibility purposes.
8522      *
8523      * @return The view accessibility id.
8524      *
8525      * @hide
8526      */
getAccessibilityViewId()8527     public int getAccessibilityViewId() {
8528         if (mAccessibilityViewId == NO_ID) {
8529             mAccessibilityViewId = sNextAccessibilityViewId++;
8530         }
8531         return mAccessibilityViewId;
8532     }
8533 
8534     /**
8535      * Gets the unique identifier of this view on the screen for autofill purposes.
8536      *
8537      * @return The view autofill id.
8538      *
8539      * @hide
8540      */
getAutofillViewId()8541     public int getAutofillViewId() {
8542         if (mAutofillViewId == NO_ID) {
8543             mAutofillViewId = mContext.getNextAutofillId();
8544         }
8545         return mAutofillViewId;
8546     }
8547 
8548     /**
8549      * Gets the unique identifier of the window in which this View reseides.
8550      *
8551      * @return The window accessibility id.
8552      *
8553      * @hide
8554      */
getAccessibilityWindowId()8555     public int getAccessibilityWindowId() {
8556         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8557                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8558     }
8559 
8560     /**
8561      * Returns the {@link View}'s content description.
8562      * <p>
8563      * <strong>Note:</strong> Do not override this method, as it will have no
8564      * effect on the content description presented to accessibility services.
8565      * You must call {@link #setContentDescription(CharSequence)} to modify the
8566      * content description.
8567      *
8568      * @return the content description
8569      * @see #setContentDescription(CharSequence)
8570      * @attr ref android.R.styleable#View_contentDescription
8571      */
8572     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()8573     public CharSequence getContentDescription() {
8574         return mContentDescription;
8575     }
8576 
8577     /**
8578      * Sets the {@link View}'s content description.
8579      * <p>
8580      * A content description briefly describes the view and is primarily used
8581      * for accessibility support to determine how a view should be presented to
8582      * the user. In the case of a view with no textual representation, such as
8583      * {@link android.widget.ImageButton}, a useful content description
8584      * explains what the view does. For example, an image button with a phone
8585      * icon that is used to place a call may use "Call" as its content
8586      * description. An image of a floppy disk that is used to save a file may
8587      * use "Save".
8588      *
8589      * @param contentDescription The content description.
8590      * @see #getContentDescription()
8591      * @attr ref android.R.styleable#View_contentDescription
8592      */
8593     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)8594     public void setContentDescription(CharSequence contentDescription) {
8595         if (mContentDescription == null) {
8596             if (contentDescription == null) {
8597                 return;
8598             }
8599         } else if (mContentDescription.equals(contentDescription)) {
8600             return;
8601         }
8602         mContentDescription = contentDescription;
8603         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8604         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8605             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8606             notifySubtreeAccessibilityStateChangedIfNeeded();
8607         } else {
8608             notifyViewAccessibilityStateChangedIfNeeded(
8609                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8610         }
8611     }
8612 
8613     /**
8614      * Sets the id of a view before which this one is visited in accessibility traversal.
8615      * A screen-reader must visit the content of this view before the content of the one
8616      * it precedes. For example, if view B is set to be before view A, then a screen-reader
8617      * will traverse the entire content of B before traversing the entire content of A,
8618      * regardles of what traversal strategy it is using.
8619      * <p>
8620      * Views that do not have specified before/after relationships are traversed in order
8621      * determined by the screen-reader.
8622      * </p>
8623      * <p>
8624      * Setting that this view is before a view that is not important for accessibility
8625      * or if this view is not important for accessibility will have no effect as the
8626      * screen-reader is not aware of unimportant views.
8627      * </p>
8628      *
8629      * @param beforeId The id of a view this one precedes in accessibility traversal.
8630      *
8631      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8632      *
8633      * @see #setImportantForAccessibility(int)
8634      */
8635     @RemotableViewMethod
setAccessibilityTraversalBefore(int beforeId)8636     public void setAccessibilityTraversalBefore(int beforeId) {
8637         if (mAccessibilityTraversalBeforeId == beforeId) {
8638             return;
8639         }
8640         mAccessibilityTraversalBeforeId = beforeId;
8641         notifyViewAccessibilityStateChangedIfNeeded(
8642                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8643     }
8644 
8645     /**
8646      * Gets the id of a view before which this one is visited in accessibility traversal.
8647      *
8648      * @return The id of a view this one precedes in accessibility traversal if
8649      *         specified, otherwise {@link #NO_ID}.
8650      *
8651      * @see #setAccessibilityTraversalBefore(int)
8652      */
getAccessibilityTraversalBefore()8653     public int getAccessibilityTraversalBefore() {
8654         return mAccessibilityTraversalBeforeId;
8655     }
8656 
8657     /**
8658      * Sets the id of a view after which this one is visited in accessibility traversal.
8659      * A screen-reader must visit the content of the other view before the content of this
8660      * one. For example, if view B is set to be after view A, then a screen-reader
8661      * will traverse the entire content of A before traversing the entire content of B,
8662      * regardles of what traversal strategy it is using.
8663      * <p>
8664      * Views that do not have specified before/after relationships are traversed in order
8665      * determined by the screen-reader.
8666      * </p>
8667      * <p>
8668      * Setting that this view is after a view that is not important for accessibility
8669      * or if this view is not important for accessibility will have no effect as the
8670      * screen-reader is not aware of unimportant views.
8671      * </p>
8672      *
8673      * @param afterId The id of a view this one succedees in accessibility traversal.
8674      *
8675      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8676      *
8677      * @see #setImportantForAccessibility(int)
8678      */
8679     @RemotableViewMethod
setAccessibilityTraversalAfter(int afterId)8680     public void setAccessibilityTraversalAfter(int afterId) {
8681         if (mAccessibilityTraversalAfterId == afterId) {
8682             return;
8683         }
8684         mAccessibilityTraversalAfterId = afterId;
8685         notifyViewAccessibilityStateChangedIfNeeded(
8686                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8687     }
8688 
8689     /**
8690      * Gets the id of a view after which this one is visited in accessibility traversal.
8691      *
8692      * @return The id of a view this one succeedes in accessibility traversal if
8693      *         specified, otherwise {@link #NO_ID}.
8694      *
8695      * @see #setAccessibilityTraversalAfter(int)
8696      */
getAccessibilityTraversalAfter()8697     public int getAccessibilityTraversalAfter() {
8698         return mAccessibilityTraversalAfterId;
8699     }
8700 
8701     /**
8702      * Gets the id of a view for which this view serves as a label for
8703      * accessibility purposes.
8704      *
8705      * @return The labeled view id.
8706      */
8707     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()8708     public int getLabelFor() {
8709         return mLabelForId;
8710     }
8711 
8712     /**
8713      * Sets the id of a view for which this view serves as a label for
8714      * accessibility purposes.
8715      *
8716      * @param id The labeled view id.
8717      */
8718     @RemotableViewMethod
setLabelFor(@dRes int id)8719     public void setLabelFor(@IdRes int id) {
8720         if (mLabelForId == id) {
8721             return;
8722         }
8723         mLabelForId = id;
8724         if (mLabelForId != View.NO_ID
8725                 && mID == View.NO_ID) {
8726             mID = generateViewId();
8727         }
8728         notifyViewAccessibilityStateChangedIfNeeded(
8729                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8730     }
8731 
8732     /**
8733      * Invoked whenever this view loses focus, either by losing window focus or by losing
8734      * focus within its window. This method can be used to clear any state tied to the
8735      * focus. For instance, if a button is held pressed with the trackball and the window
8736      * loses focus, this method can be used to cancel the press.
8737      *
8738      * Subclasses of View overriding this method should always call super.onFocusLost().
8739      *
8740      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8741      * @see #onWindowFocusChanged(boolean)
8742      *
8743      * @hide pending API council approval
8744      */
8745     @CallSuper
onFocusLost()8746     protected void onFocusLost() {
8747         resetPressedState();
8748     }
8749 
resetPressedState()8750     private void resetPressedState() {
8751         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8752             return;
8753         }
8754 
8755         if (isPressed()) {
8756             setPressed(false);
8757 
8758             if (!mHasPerformedLongPress) {
8759                 removeLongPressCallback();
8760             }
8761         }
8762     }
8763 
8764     /**
8765      * Returns true if this view has focus
8766      *
8767      * @return True if this view has focus, false otherwise.
8768      */
8769     @ViewDebug.ExportedProperty(category = "focus")
isFocused()8770     public boolean isFocused() {
8771         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8772     }
8773 
8774     /**
8775      * Find the view in the hierarchy rooted at this view that currently has
8776      * focus.
8777      *
8778      * @return The view that currently has focus, or null if no focused view can
8779      *         be found.
8780      */
findFocus()8781     public View findFocus() {
8782         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8783     }
8784 
8785     /**
8786      * Indicates whether this view is one of the set of scrollable containers in
8787      * its window.
8788      *
8789      * @return whether this view is one of the set of scrollable containers in
8790      * its window
8791      *
8792      * @attr ref android.R.styleable#View_isScrollContainer
8793      */
isScrollContainer()8794     public boolean isScrollContainer() {
8795         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8796     }
8797 
8798     /**
8799      * Change whether this view is one of the set of scrollable containers in
8800      * its window.  This will be used to determine whether the window can
8801      * resize or must pan when a soft input area is open -- scrollable
8802      * containers allow the window to use resize mode since the container
8803      * will appropriately shrink.
8804      *
8805      * @attr ref android.R.styleable#View_isScrollContainer
8806      */
setScrollContainer(boolean isScrollContainer)8807     public void setScrollContainer(boolean isScrollContainer) {
8808         if (isScrollContainer) {
8809             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8810                 mAttachInfo.mScrollContainers.add(this);
8811                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8812             }
8813             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8814         } else {
8815             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8816                 mAttachInfo.mScrollContainers.remove(this);
8817             }
8818             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8819         }
8820     }
8821 
8822     /**
8823      * Returns the quality of the drawing cache.
8824      *
8825      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8826      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8827      *
8828      * @see #setDrawingCacheQuality(int)
8829      * @see #setDrawingCacheEnabled(boolean)
8830      * @see #isDrawingCacheEnabled()
8831      *
8832      * @attr ref android.R.styleable#View_drawingCacheQuality
8833      */
8834     @DrawingCacheQuality
getDrawingCacheQuality()8835     public int getDrawingCacheQuality() {
8836         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8837     }
8838 
8839     /**
8840      * Set the drawing cache quality of this view. This value is used only when the
8841      * drawing cache is enabled
8842      *
8843      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8844      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8845      *
8846      * @see #getDrawingCacheQuality()
8847      * @see #setDrawingCacheEnabled(boolean)
8848      * @see #isDrawingCacheEnabled()
8849      *
8850      * @attr ref android.R.styleable#View_drawingCacheQuality
8851      */
setDrawingCacheQuality(@rawingCacheQuality int quality)8852     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8853         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8854     }
8855 
8856     /**
8857      * Returns whether the screen should remain on, corresponding to the current
8858      * value of {@link #KEEP_SCREEN_ON}.
8859      *
8860      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8861      *
8862      * @see #setKeepScreenOn(boolean)
8863      *
8864      * @attr ref android.R.styleable#View_keepScreenOn
8865      */
getKeepScreenOn()8866     public boolean getKeepScreenOn() {
8867         return (mViewFlags & KEEP_SCREEN_ON) != 0;
8868     }
8869 
8870     /**
8871      * Controls whether the screen should remain on, modifying the
8872      * value of {@link #KEEP_SCREEN_ON}.
8873      *
8874      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8875      *
8876      * @see #getKeepScreenOn()
8877      *
8878      * @attr ref android.R.styleable#View_keepScreenOn
8879      */
setKeepScreenOn(boolean keepScreenOn)8880     public void setKeepScreenOn(boolean keepScreenOn) {
8881         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8882     }
8883 
8884     /**
8885      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8886      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8887      *
8888      * @attr ref android.R.styleable#View_nextFocusLeft
8889      */
getNextFocusLeftId()8890     public int getNextFocusLeftId() {
8891         return mNextFocusLeftId;
8892     }
8893 
8894     /**
8895      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8896      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8897      * decide automatically.
8898      *
8899      * @attr ref android.R.styleable#View_nextFocusLeft
8900      */
setNextFocusLeftId(int nextFocusLeftId)8901     public void setNextFocusLeftId(int nextFocusLeftId) {
8902         mNextFocusLeftId = nextFocusLeftId;
8903     }
8904 
8905     /**
8906      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8907      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8908      *
8909      * @attr ref android.R.styleable#View_nextFocusRight
8910      */
getNextFocusRightId()8911     public int getNextFocusRightId() {
8912         return mNextFocusRightId;
8913     }
8914 
8915     /**
8916      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8917      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8918      * decide automatically.
8919      *
8920      * @attr ref android.R.styleable#View_nextFocusRight
8921      */
setNextFocusRightId(int nextFocusRightId)8922     public void setNextFocusRightId(int nextFocusRightId) {
8923         mNextFocusRightId = nextFocusRightId;
8924     }
8925 
8926     /**
8927      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8928      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8929      *
8930      * @attr ref android.R.styleable#View_nextFocusUp
8931      */
getNextFocusUpId()8932     public int getNextFocusUpId() {
8933         return mNextFocusUpId;
8934     }
8935 
8936     /**
8937      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8938      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8939      * decide automatically.
8940      *
8941      * @attr ref android.R.styleable#View_nextFocusUp
8942      */
setNextFocusUpId(int nextFocusUpId)8943     public void setNextFocusUpId(int nextFocusUpId) {
8944         mNextFocusUpId = nextFocusUpId;
8945     }
8946 
8947     /**
8948      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8949      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8950      *
8951      * @attr ref android.R.styleable#View_nextFocusDown
8952      */
getNextFocusDownId()8953     public int getNextFocusDownId() {
8954         return mNextFocusDownId;
8955     }
8956 
8957     /**
8958      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8959      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8960      * decide automatically.
8961      *
8962      * @attr ref android.R.styleable#View_nextFocusDown
8963      */
setNextFocusDownId(int nextFocusDownId)8964     public void setNextFocusDownId(int nextFocusDownId) {
8965         mNextFocusDownId = nextFocusDownId;
8966     }
8967 
8968     /**
8969      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8970      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8971      *
8972      * @attr ref android.R.styleable#View_nextFocusForward
8973      */
getNextFocusForwardId()8974     public int getNextFocusForwardId() {
8975         return mNextFocusForwardId;
8976     }
8977 
8978     /**
8979      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8980      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8981      * decide automatically.
8982      *
8983      * @attr ref android.R.styleable#View_nextFocusForward
8984      */
setNextFocusForwardId(int nextFocusForwardId)8985     public void setNextFocusForwardId(int nextFocusForwardId) {
8986         mNextFocusForwardId = nextFocusForwardId;
8987     }
8988 
8989     /**
8990      * Gets the id of the root of the next keyboard navigation cluster.
8991      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8992      * decide automatically.
8993      *
8994      * @attr ref android.R.styleable#View_nextClusterForward
8995      */
getNextClusterForwardId()8996     public int getNextClusterForwardId() {
8997         return mNextClusterForwardId;
8998     }
8999 
9000     /**
9001      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
9002      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
9003      * decide automatically.
9004      *
9005      * @attr ref android.R.styleable#View_nextClusterForward
9006      */
setNextClusterForwardId(int nextClusterForwardId)9007     public void setNextClusterForwardId(int nextClusterForwardId) {
9008         mNextClusterForwardId = nextClusterForwardId;
9009     }
9010 
9011     /**
9012      * Returns the visibility of this view and all of its ancestors
9013      *
9014      * @return True if this view and all of its ancestors are {@link #VISIBLE}
9015      */
isShown()9016     public boolean isShown() {
9017         View current = this;
9018         //noinspection ConstantConditions
9019         do {
9020             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9021                 return false;
9022             }
9023             ViewParent parent = current.mParent;
9024             if (parent == null) {
9025                 return false; // We are not attached to the view root
9026             }
9027             if (!(parent instanceof View)) {
9028                 return true;
9029             }
9030             current = (View) parent;
9031         } while (current != null);
9032 
9033         return false;
9034     }
9035 
9036     /**
9037      * Called by the view hierarchy when the content insets for a window have
9038      * changed, to allow it to adjust its content to fit within those windows.
9039      * The content insets tell you the space that the status bar, input method,
9040      * and other system windows infringe on the application's window.
9041      *
9042      * <p>You do not normally need to deal with this function, since the default
9043      * window decoration given to applications takes care of applying it to the
9044      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
9045      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
9046      * and your content can be placed under those system elements.  You can then
9047      * use this method within your view hierarchy if you have parts of your UI
9048      * which you would like to ensure are not being covered.
9049      *
9050      * <p>The default implementation of this method simply applies the content
9051      * insets to the view's padding, consuming that content (modifying the
9052      * insets to be 0), and returning true.  This behavior is off by default, but can
9053      * be enabled through {@link #setFitsSystemWindows(boolean)}.
9054      *
9055      * <p>This function's traversal down the hierarchy is depth-first.  The same content
9056      * insets object is propagated down the hierarchy, so any changes made to it will
9057      * be seen by all following views (including potentially ones above in
9058      * the hierarchy since this is a depth-first traversal).  The first view
9059      * that returns true will abort the entire traversal.
9060      *
9061      * <p>The default implementation works well for a situation where it is
9062      * used with a container that covers the entire window, allowing it to
9063      * apply the appropriate insets to its content on all edges.  If you need
9064      * a more complicated layout (such as two different views fitting system
9065      * windows, one on the top of the window, and one on the bottom),
9066      * you can override the method and handle the insets however you would like.
9067      * Note that the insets provided by the framework are always relative to the
9068      * far edges of the window, not accounting for the location of the called view
9069      * within that window.  (In fact when this method is called you do not yet know
9070      * where the layout will place the view, as it is done before layout happens.)
9071      *
9072      * <p>Note: unlike many View methods, there is no dispatch phase to this
9073      * call.  If you are overriding it in a ViewGroup and want to allow the
9074      * call to continue to your children, you must be sure to call the super
9075      * implementation.
9076      *
9077      * <p>Here is a sample layout that makes use of fitting system windows
9078      * to have controls for a video view placed inside of the window decorations
9079      * that it hides and shows.  This can be used with code like the second
9080      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
9081      *
9082      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
9083      *
9084      * @param insets Current content insets of the window.  Prior to
9085      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
9086      * the insets or else you and Android will be unhappy.
9087      *
9088      * @return {@code true} if this view applied the insets and it should not
9089      * continue propagating further down the hierarchy, {@code false} otherwise.
9090      * @see #getFitsSystemWindows()
9091      * @see #setFitsSystemWindows(boolean)
9092      * @see #setSystemUiVisibility(int)
9093      *
9094      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
9095      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
9096      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
9097      * to implement handling their own insets.
9098      */
9099     @Deprecated
fitSystemWindows(Rect insets)9100     protected boolean fitSystemWindows(Rect insets) {
9101         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
9102             if (insets == null) {
9103                 // Null insets by definition have already been consumed.
9104                 // This call cannot apply insets since there are none to apply,
9105                 // so return false.
9106                 return false;
9107             }
9108             // If we're not in the process of dispatching the newer apply insets call,
9109             // that means we're not in the compatibility path. Dispatch into the newer
9110             // apply insets path and take things from there.
9111             try {
9112                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
9113                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
9114             } finally {
9115                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
9116             }
9117         } else {
9118             // We're being called from the newer apply insets path.
9119             // Perform the standard fallback behavior.
9120             return fitSystemWindowsInt(insets);
9121         }
9122     }
9123 
fitSystemWindowsInt(Rect insets)9124     private boolean fitSystemWindowsInt(Rect insets) {
9125         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
9126             mUserPaddingStart = UNDEFINED_PADDING;
9127             mUserPaddingEnd = UNDEFINED_PADDING;
9128             Rect localInsets = sThreadLocal.get();
9129             if (localInsets == null) {
9130                 localInsets = new Rect();
9131                 sThreadLocal.set(localInsets);
9132             }
9133             boolean res = computeFitSystemWindows(insets, localInsets);
9134             mUserPaddingLeftInitial = localInsets.left;
9135             mUserPaddingRightInitial = localInsets.right;
9136             internalSetPadding(localInsets.left, localInsets.top,
9137                     localInsets.right, localInsets.bottom);
9138             return res;
9139         }
9140         return false;
9141     }
9142 
9143     /**
9144      * Called when the view should apply {@link WindowInsets} according to its internal policy.
9145      *
9146      * <p>This method should be overridden by views that wish to apply a policy different from or
9147      * in addition to the default behavior. Clients that wish to force a view subtree
9148      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
9149      *
9150      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
9151      * it will be called during dispatch instead of this method. The listener may optionally
9152      * call this method from its own implementation if it wishes to apply the view's default
9153      * insets policy in addition to its own.</p>
9154      *
9155      * <p>Implementations of this method should either return the insets parameter unchanged
9156      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
9157      * that this view applied itself. This allows new inset types added in future platform
9158      * versions to pass through existing implementations unchanged without being erroneously
9159      * consumed.</p>
9160      *
9161      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
9162      * property is set then the view will consume the system window insets and apply them
9163      * as padding for the view.</p>
9164      *
9165      * @param insets Insets to apply
9166      * @return The supplied insets with any applied insets consumed
9167      */
onApplyWindowInsets(WindowInsets insets)9168     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
9169         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
9170             // We weren't called from within a direct call to fitSystemWindows,
9171             // call into it as a fallback in case we're in a class that overrides it
9172             // and has logic to perform.
9173             if (fitSystemWindows(insets.getSystemWindowInsets())) {
9174                 return insets.consumeSystemWindowInsets();
9175             }
9176         } else {
9177             // We were called from within a direct call to fitSystemWindows.
9178             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
9179                 return insets.consumeSystemWindowInsets();
9180             }
9181         }
9182         return insets;
9183     }
9184 
9185     /**
9186      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
9187      * window insets to this view. The listener's
9188      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
9189      * method will be called instead of the view's
9190      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
9191      *
9192      * @param listener Listener to set
9193      *
9194      * @see #onApplyWindowInsets(WindowInsets)
9195      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)9196     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
9197         getListenerInfo().mOnApplyWindowInsetsListener = listener;
9198     }
9199 
9200     /**
9201      * Request to apply the given window insets to this view or another view in its subtree.
9202      *
9203      * <p>This method should be called by clients wishing to apply insets corresponding to areas
9204      * obscured by window decorations or overlays. This can include the status and navigation bars,
9205      * action bars, input methods and more. New inset categories may be added in the future.
9206      * The method returns the insets provided minus any that were applied by this view or its
9207      * children.</p>
9208      *
9209      * <p>Clients wishing to provide custom behavior should override the
9210      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
9211      * {@link OnApplyWindowInsetsListener} via the
9212      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
9213      * method.</p>
9214      *
9215      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
9216      * </p>
9217      *
9218      * @param insets Insets to apply
9219      * @return The provided insets minus the insets that were consumed
9220      */
dispatchApplyWindowInsets(WindowInsets insets)9221     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
9222         try {
9223             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
9224             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
9225                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
9226             } else {
9227                 return onApplyWindowInsets(insets);
9228             }
9229         } finally {
9230             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
9231         }
9232     }
9233 
9234     /**
9235      * Compute the view's coordinate within the surface.
9236      *
9237      * <p>Computes the coordinates of this view in its surface. The argument
9238      * must be an array of two integers. After the method returns, the array
9239      * contains the x and y location in that order.</p>
9240      * @hide
9241      * @param location an array of two integers in which to hold the coordinates
9242      */
getLocationInSurface(@ize2) int[] location)9243     public void getLocationInSurface(@Size(2) int[] location) {
9244         getLocationInWindow(location);
9245         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
9246             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
9247             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
9248         }
9249     }
9250 
9251     /**
9252      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
9253      * only available if the view is attached.
9254      *
9255      * @return WindowInsets from the top of the view hierarchy or null if View is detached
9256      */
getRootWindowInsets()9257     public WindowInsets getRootWindowInsets() {
9258         if (mAttachInfo != null) {
9259             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
9260         }
9261         return null;
9262     }
9263 
9264     /**
9265      * @hide Compute the insets that should be consumed by this view and the ones
9266      * that should propagate to those under it.
9267      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)9268     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
9269         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9270                 || mAttachInfo == null
9271                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
9272                         && !mAttachInfo.mOverscanRequested)) {
9273             outLocalInsets.set(inoutInsets);
9274             inoutInsets.set(0, 0, 0, 0);
9275             return true;
9276         } else {
9277             // The application wants to take care of fitting system window for
9278             // the content...  however we still need to take care of any overscan here.
9279             final Rect overscan = mAttachInfo.mOverscanInsets;
9280             outLocalInsets.set(overscan);
9281             inoutInsets.left -= overscan.left;
9282             inoutInsets.top -= overscan.top;
9283             inoutInsets.right -= overscan.right;
9284             inoutInsets.bottom -= overscan.bottom;
9285             return false;
9286         }
9287     }
9288 
9289     /**
9290      * Compute insets that should be consumed by this view and the ones that should propagate
9291      * to those under it.
9292      *
9293      * @param in Insets currently being processed by this View, likely received as a parameter
9294      *           to {@link #onApplyWindowInsets(WindowInsets)}.
9295      * @param outLocalInsets A Rect that will receive the insets that should be consumed
9296      *                       by this view
9297      * @return Insets that should be passed along to views under this one
9298      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)9299     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
9300         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9301                 || mAttachInfo == null
9302                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
9303             outLocalInsets.set(in.getSystemWindowInsets());
9304             return in.consumeSystemWindowInsets();
9305         } else {
9306             outLocalInsets.set(0, 0, 0, 0);
9307             return in;
9308         }
9309     }
9310 
9311     /**
9312      * Sets whether or not this view should account for system screen decorations
9313      * such as the status bar and inset its content; that is, controlling whether
9314      * the default implementation of {@link #fitSystemWindows(Rect)} will be
9315      * executed.  See that method for more details.
9316      *
9317      * <p>Note that if you are providing your own implementation of
9318      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
9319      * flag to true -- your implementation will be overriding the default
9320      * implementation that checks this flag.
9321      *
9322      * @param fitSystemWindows If true, then the default implementation of
9323      * {@link #fitSystemWindows(Rect)} will be executed.
9324      *
9325      * @attr ref android.R.styleable#View_fitsSystemWindows
9326      * @see #getFitsSystemWindows()
9327      * @see #fitSystemWindows(Rect)
9328      * @see #setSystemUiVisibility(int)
9329      */
setFitsSystemWindows(boolean fitSystemWindows)9330     public void setFitsSystemWindows(boolean fitSystemWindows) {
9331         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9332     }
9333 
9334     /**
9335      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9336      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9337      * will be executed.
9338      *
9339      * @return {@code true} if the default implementation of
9340      * {@link #fitSystemWindows(Rect)} will be executed.
9341      *
9342      * @attr ref android.R.styleable#View_fitsSystemWindows
9343      * @see #setFitsSystemWindows(boolean)
9344      * @see #fitSystemWindows(Rect)
9345      * @see #setSystemUiVisibility(int)
9346      */
9347     @ViewDebug.ExportedProperty
getFitsSystemWindows()9348     public boolean getFitsSystemWindows() {
9349         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9350     }
9351 
9352     /** @hide */
fitsSystemWindows()9353     public boolean fitsSystemWindows() {
9354         return getFitsSystemWindows();
9355     }
9356 
9357     /**
9358      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9359      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9360      */
9361     @Deprecated
requestFitSystemWindows()9362     public void requestFitSystemWindows() {
9363         if (mParent != null) {
9364             mParent.requestFitSystemWindows();
9365         }
9366     }
9367 
9368     /**
9369      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9370      */
requestApplyInsets()9371     public void requestApplyInsets() {
9372         requestFitSystemWindows();
9373     }
9374 
9375     /**
9376      * For use by PhoneWindow to make its own system window fitting optional.
9377      * @hide
9378      */
makeOptionalFitsSystemWindows()9379     public void makeOptionalFitsSystemWindows() {
9380         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9381     }
9382 
9383     /**
9384      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9385      * treat them as such.
9386      * @hide
9387      */
getOutsets(Rect outOutsetRect)9388     public void getOutsets(Rect outOutsetRect) {
9389         if (mAttachInfo != null) {
9390             outOutsetRect.set(mAttachInfo.mOutsets);
9391         } else {
9392             outOutsetRect.setEmpty();
9393         }
9394     }
9395 
9396     /**
9397      * Returns the visibility status for this view.
9398      *
9399      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9400      * @attr ref android.R.styleable#View_visibility
9401      */
9402     @ViewDebug.ExportedProperty(mapping = {
9403         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9404         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9405         @ViewDebug.IntToString(from = GONE,      to = "GONE")
9406     })
9407     @Visibility
getVisibility()9408     public int getVisibility() {
9409         return mViewFlags & VISIBILITY_MASK;
9410     }
9411 
9412     /**
9413      * Set the visibility state of this view.
9414      *
9415      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9416      * @attr ref android.R.styleable#View_visibility
9417      */
9418     @RemotableViewMethod
setVisibility(@isibility int visibility)9419     public void setVisibility(@Visibility int visibility) {
9420         setFlags(visibility, VISIBILITY_MASK);
9421     }
9422 
9423     /**
9424      * Returns the enabled status for this view. The interpretation of the
9425      * enabled state varies by subclass.
9426      *
9427      * @return True if this view is enabled, false otherwise.
9428      */
9429     @ViewDebug.ExportedProperty
isEnabled()9430     public boolean isEnabled() {
9431         return (mViewFlags & ENABLED_MASK) == ENABLED;
9432     }
9433 
9434     /**
9435      * Set the enabled state of this view. The interpretation of the enabled
9436      * state varies by subclass.
9437      *
9438      * @param enabled True if this view is enabled, false otherwise.
9439      */
9440     @RemotableViewMethod
setEnabled(boolean enabled)9441     public void setEnabled(boolean enabled) {
9442         if (enabled == isEnabled()) return;
9443 
9444         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9445 
9446         /*
9447          * The View most likely has to change its appearance, so refresh
9448          * the drawable state.
9449          */
9450         refreshDrawableState();
9451 
9452         // Invalidate too, since the default behavior for views is to be
9453         // be drawn at 50% alpha rather than to change the drawable.
9454         invalidate(true);
9455 
9456         if (!enabled) {
9457             cancelPendingInputEvents();
9458         }
9459     }
9460 
9461     /**
9462      * Set whether this view can receive the focus.
9463      * <p>
9464      * Setting this to false will also ensure that this view is not focusable
9465      * in touch mode.
9466      *
9467      * @param focusable If true, this view can receive the focus.
9468      *
9469      * @see #setFocusableInTouchMode(boolean)
9470      * @see #setFocusable(int)
9471      * @attr ref android.R.styleable#View_focusable
9472      */
setFocusable(boolean focusable)9473     public void setFocusable(boolean focusable) {
9474         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9475     }
9476 
9477     /**
9478      * Sets whether this view can receive focus.
9479      * <p>
9480      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9481      * automatically based on the view's interactivity. This is the default.
9482      * <p>
9483      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9484      * in touch mode.
9485      *
9486      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9487      *                  or {@link #FOCUSABLE_AUTO}.
9488      * @see #setFocusableInTouchMode(boolean)
9489      * @attr ref android.R.styleable#View_focusable
9490      */
setFocusable(@ocusable int focusable)9491     public void setFocusable(@Focusable int focusable) {
9492         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9493             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9494         }
9495         setFlags(focusable, FOCUSABLE_MASK);
9496     }
9497 
9498     /**
9499      * Set whether this view can receive focus while in touch mode.
9500      *
9501      * Setting this to true will also ensure that this view is focusable.
9502      *
9503      * @param focusableInTouchMode If true, this view can receive the focus while
9504      *   in touch mode.
9505      *
9506      * @see #setFocusable(boolean)
9507      * @attr ref android.R.styleable#View_focusableInTouchMode
9508      */
setFocusableInTouchMode(boolean focusableInTouchMode)9509     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9510         // Focusable in touch mode should always be set before the focusable flag
9511         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9512         // which, in touch mode, will not successfully request focus on this view
9513         // because the focusable in touch mode flag is not set
9514         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9515 
9516         // Clear FOCUSABLE_AUTO if set.
9517         if (focusableInTouchMode) {
9518             // Clears FOCUSABLE_AUTO if set.
9519             setFlags(FOCUSABLE, FOCUSABLE_MASK);
9520         }
9521     }
9522 
9523     /**
9524      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
9525      * to autofill the view with the user's data.
9526      *
9527      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
9528      * For example, if the application accepts either an username or email address to identify
9529      * an user.
9530      *
9531      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
9532      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
9533      * constants such as:
9534      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
9535      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
9536      * {@link #AUTOFILL_HINT_NAME},
9537      * {@link #AUTOFILL_HINT_PHONE},
9538      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
9539      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
9540      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
9541      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
9542      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
9543      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
9544      *
9545      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9546      * @attr ref android.R.styleable#View_autofillHints
9547      */
setAutofillHints(@ullable String... autofillHints)9548     public void setAutofillHints(@Nullable String... autofillHints) {
9549         if (autofillHints == null || autofillHints.length == 0) {
9550             mAutofillHints = null;
9551         } else {
9552             mAutofillHints = autofillHints;
9553         }
9554     }
9555 
9556     /**
9557      * @hide
9558      */
9559     @TestApi
setAutofilled(boolean isAutofilled)9560     public void setAutofilled(boolean isAutofilled) {
9561         boolean wasChanged = isAutofilled != isAutofilled();
9562 
9563         if (wasChanged) {
9564             if (isAutofilled) {
9565                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9566             } else {
9567                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9568             }
9569 
9570             invalidate();
9571         }
9572     }
9573 
9574     /**
9575      * Set whether this view should have sound effects enabled for events such as
9576      * clicking and touching.
9577      *
9578      * <p>You may wish to disable sound effects for a view if you already play sounds,
9579      * for instance, a dial key that plays dtmf tones.
9580      *
9581      * @param soundEffectsEnabled whether sound effects are enabled for this view.
9582      * @see #isSoundEffectsEnabled()
9583      * @see #playSoundEffect(int)
9584      * @attr ref android.R.styleable#View_soundEffectsEnabled
9585      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)9586     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9587         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9588     }
9589 
9590     /**
9591      * @return whether this view should have sound effects enabled for events such as
9592      *     clicking and touching.
9593      *
9594      * @see #setSoundEffectsEnabled(boolean)
9595      * @see #playSoundEffect(int)
9596      * @attr ref android.R.styleable#View_soundEffectsEnabled
9597      */
9598     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()9599     public boolean isSoundEffectsEnabled() {
9600         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9601     }
9602 
9603     /**
9604      * Set whether this view should have haptic feedback for events such as
9605      * long presses.
9606      *
9607      * <p>You may wish to disable haptic feedback if your view already controls
9608      * its own haptic feedback.
9609      *
9610      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9611      * @see #isHapticFeedbackEnabled()
9612      * @see #performHapticFeedback(int)
9613      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9614      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)9615     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9616         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9617     }
9618 
9619     /**
9620      * @return whether this view should have haptic feedback enabled for events
9621      * long presses.
9622      *
9623      * @see #setHapticFeedbackEnabled(boolean)
9624      * @see #performHapticFeedback(int)
9625      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9626      */
9627     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()9628     public boolean isHapticFeedbackEnabled() {
9629         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9630     }
9631 
9632     /**
9633      * Returns the layout direction for this view.
9634      *
9635      * @return One of {@link #LAYOUT_DIRECTION_LTR},
9636      *   {@link #LAYOUT_DIRECTION_RTL},
9637      *   {@link #LAYOUT_DIRECTION_INHERIT} or
9638      *   {@link #LAYOUT_DIRECTION_LOCALE}.
9639      *
9640      * @attr ref android.R.styleable#View_layoutDirection
9641      *
9642      * @hide
9643      */
9644     @ViewDebug.ExportedProperty(category = "layout", mapping = {
9645         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9646         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9647         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9648         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9649     })
9650     @LayoutDir
getRawLayoutDirection()9651     public int getRawLayoutDirection() {
9652         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9653     }
9654 
9655     /**
9656      * Set the layout direction for this view. This will propagate a reset of layout direction
9657      * resolution to the view's children and resolve layout direction for this view.
9658      *
9659      * @param layoutDirection the layout direction to set. Should be one of:
9660      *
9661      * {@link #LAYOUT_DIRECTION_LTR},
9662      * {@link #LAYOUT_DIRECTION_RTL},
9663      * {@link #LAYOUT_DIRECTION_INHERIT},
9664      * {@link #LAYOUT_DIRECTION_LOCALE}.
9665      *
9666      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9667      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9668      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9669      *
9670      * @attr ref android.R.styleable#View_layoutDirection
9671      */
9672     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)9673     public void setLayoutDirection(@LayoutDir int layoutDirection) {
9674         if (getRawLayoutDirection() != layoutDirection) {
9675             // Reset the current layout direction and the resolved one
9676             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9677             resetRtlProperties();
9678             // Set the new layout direction (filtered)
9679             mPrivateFlags2 |=
9680                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9681             // We need to resolve all RTL properties as they all depend on layout direction
9682             resolveRtlPropertiesIfNeeded();
9683             requestLayout();
9684             invalidate(true);
9685         }
9686     }
9687 
9688     /**
9689      * Returns the resolved layout direction for this view.
9690      *
9691      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9692      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9693      *
9694      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9695      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9696      *
9697      * @attr ref android.R.styleable#View_layoutDirection
9698      */
9699     @ViewDebug.ExportedProperty(category = "layout", mapping = {
9700         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9701         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9702     })
9703     @ResolvedLayoutDir
getLayoutDirection()9704     public int getLayoutDirection() {
9705         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9706         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9707             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9708             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9709         }
9710         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9711                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9712     }
9713 
9714     /**
9715      * Indicates whether or not this view's layout is right-to-left. This is resolved from
9716      * layout attribute and/or the inherited value from the parent
9717      *
9718      * @return true if the layout is right-to-left.
9719      *
9720      * @hide
9721      */
9722     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()9723     public boolean isLayoutRtl() {
9724         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9725     }
9726 
9727     /**
9728      * Indicates whether the view is currently tracking transient state that the
9729      * app should not need to concern itself with saving and restoring, but that
9730      * the framework should take special note to preserve when possible.
9731      *
9732      * <p>A view with transient state cannot be trivially rebound from an external
9733      * data source, such as an adapter binding item views in a list. This may be
9734      * because the view is performing an animation, tracking user selection
9735      * of content, or similar.</p>
9736      *
9737      * @return true if the view has transient state
9738      */
9739     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()9740     public boolean hasTransientState() {
9741         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9742     }
9743 
9744     /**
9745      * Set whether this view is currently tracking transient state that the
9746      * framework should attempt to preserve when possible. This flag is reference counted,
9747      * so every call to setHasTransientState(true) should be paired with a later call
9748      * to setHasTransientState(false).
9749      *
9750      * <p>A view with transient state cannot be trivially rebound from an external
9751      * data source, such as an adapter binding item views in a list. This may be
9752      * because the view is performing an animation, tracking user selection
9753      * of content, or similar.</p>
9754      *
9755      * @param hasTransientState true if this view has transient state
9756      */
setHasTransientState(boolean hasTransientState)9757     public void setHasTransientState(boolean hasTransientState) {
9758         final boolean oldHasTransientState = hasTransientState();
9759         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9760                 mTransientStateCount - 1;
9761         if (mTransientStateCount < 0) {
9762             mTransientStateCount = 0;
9763             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9764                     "unmatched pair of setHasTransientState calls");
9765         } else if ((hasTransientState && mTransientStateCount == 1) ||
9766                 (!hasTransientState && mTransientStateCount == 0)) {
9767             // update flag if we've just incremented up from 0 or decremented down to 0
9768             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9769                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9770             final boolean newHasTransientState = hasTransientState();
9771             if (mParent != null && newHasTransientState != oldHasTransientState) {
9772                 try {
9773                     mParent.childHasTransientStateChanged(this, newHasTransientState);
9774                 } catch (AbstractMethodError e) {
9775                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9776                             " does not fully implement ViewParent", e);
9777                 }
9778             }
9779         }
9780     }
9781 
9782     /**
9783      * Returns true if this view is currently attached to a window.
9784      */
isAttachedToWindow()9785     public boolean isAttachedToWindow() {
9786         return mAttachInfo != null;
9787     }
9788 
9789     /**
9790      * Returns true if this view has been through at least one layout since it
9791      * was last attached to or detached from a window.
9792      */
isLaidOut()9793     public boolean isLaidOut() {
9794         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9795     }
9796 
9797     /**
9798      * If this view doesn't do any drawing on its own, set this flag to
9799      * allow further optimizations. By default, this flag is not set on
9800      * View, but could be set on some View subclasses such as ViewGroup.
9801      *
9802      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9803      * you should clear this flag.
9804      *
9805      * @param willNotDraw whether or not this View draw on its own
9806      */
setWillNotDraw(boolean willNotDraw)9807     public void setWillNotDraw(boolean willNotDraw) {
9808         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9809     }
9810 
9811     /**
9812      * Returns whether or not this View draws on its own.
9813      *
9814      * @return true if this view has nothing to draw, false otherwise
9815      */
9816     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()9817     public boolean willNotDraw() {
9818         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9819     }
9820 
9821     /**
9822      * When a View's drawing cache is enabled, drawing is redirected to an
9823      * offscreen bitmap. Some views, like an ImageView, must be able to
9824      * bypass this mechanism if they already draw a single bitmap, to avoid
9825      * unnecessary usage of the memory.
9826      *
9827      * @param willNotCacheDrawing true if this view does not cache its
9828      *        drawing, false otherwise
9829      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)9830     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9831         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9832     }
9833 
9834     /**
9835      * Returns whether or not this View can cache its drawing or not.
9836      *
9837      * @return true if this view does not cache its drawing, false otherwise
9838      */
9839     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()9840     public boolean willNotCacheDrawing() {
9841         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9842     }
9843 
9844     /**
9845      * Indicates whether this view reacts to click events or not.
9846      *
9847      * @return true if the view is clickable, false otherwise
9848      *
9849      * @see #setClickable(boolean)
9850      * @attr ref android.R.styleable#View_clickable
9851      */
9852     @ViewDebug.ExportedProperty
isClickable()9853     public boolean isClickable() {
9854         return (mViewFlags & CLICKABLE) == CLICKABLE;
9855     }
9856 
9857     /**
9858      * Enables or disables click events for this view. When a view
9859      * is clickable it will change its state to "pressed" on every click.
9860      * Subclasses should set the view clickable to visually react to
9861      * user's clicks.
9862      *
9863      * @param clickable true to make the view clickable, false otherwise
9864      *
9865      * @see #isClickable()
9866      * @attr ref android.R.styleable#View_clickable
9867      */
setClickable(boolean clickable)9868     public void setClickable(boolean clickable) {
9869         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9870     }
9871 
9872     /**
9873      * Indicates whether this view reacts to long click events or not.
9874      *
9875      * @return true if the view is long clickable, false otherwise
9876      *
9877      * @see #setLongClickable(boolean)
9878      * @attr ref android.R.styleable#View_longClickable
9879      */
isLongClickable()9880     public boolean isLongClickable() {
9881         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9882     }
9883 
9884     /**
9885      * Enables or disables long click events for this view. When a view is long
9886      * clickable it reacts to the user holding down the button for a longer
9887      * duration than a tap. This event can either launch the listener or a
9888      * context menu.
9889      *
9890      * @param longClickable true to make the view long clickable, false otherwise
9891      * @see #isLongClickable()
9892      * @attr ref android.R.styleable#View_longClickable
9893      */
setLongClickable(boolean longClickable)9894     public void setLongClickable(boolean longClickable) {
9895         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9896     }
9897 
9898     /**
9899      * Indicates whether this view reacts to context clicks or not.
9900      *
9901      * @return true if the view is context clickable, false otherwise
9902      * @see #setContextClickable(boolean)
9903      * @attr ref android.R.styleable#View_contextClickable
9904      */
isContextClickable()9905     public boolean isContextClickable() {
9906         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9907     }
9908 
9909     /**
9910      * Enables or disables context clicking for this view. This event can launch the listener.
9911      *
9912      * @param contextClickable true to make the view react to a context click, false otherwise
9913      * @see #isContextClickable()
9914      * @attr ref android.R.styleable#View_contextClickable
9915      */
setContextClickable(boolean contextClickable)9916     public void setContextClickable(boolean contextClickable) {
9917         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9918     }
9919 
9920     /**
9921      * Sets the pressed state for this view and provides a touch coordinate for
9922      * animation hinting.
9923      *
9924      * @param pressed Pass true to set the View's internal state to "pressed",
9925      *            or false to reverts the View's internal state from a
9926      *            previously set "pressed" state.
9927      * @param x The x coordinate of the touch that caused the press
9928      * @param y The y coordinate of the touch that caused the press
9929      */
setPressed(boolean pressed, float x, float y)9930     private void setPressed(boolean pressed, float x, float y) {
9931         if (pressed) {
9932             drawableHotspotChanged(x, y);
9933         }
9934 
9935         setPressed(pressed);
9936     }
9937 
9938     /**
9939      * Sets the pressed state for this view.
9940      *
9941      * @see #isClickable()
9942      * @see #setClickable(boolean)
9943      *
9944      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9945      *        the View's internal state from a previously set "pressed" state.
9946      */
setPressed(boolean pressed)9947     public void setPressed(boolean pressed) {
9948         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9949 
9950         if (pressed) {
9951             mPrivateFlags |= PFLAG_PRESSED;
9952         } else {
9953             mPrivateFlags &= ~PFLAG_PRESSED;
9954         }
9955 
9956         if (needsRefresh) {
9957             refreshDrawableState();
9958         }
9959         dispatchSetPressed(pressed);
9960     }
9961 
9962     /**
9963      * Dispatch setPressed to all of this View's children.
9964      *
9965      * @see #setPressed(boolean)
9966      *
9967      * @param pressed The new pressed state
9968      */
dispatchSetPressed(boolean pressed)9969     protected void dispatchSetPressed(boolean pressed) {
9970     }
9971 
9972     /**
9973      * Indicates whether the view is currently in pressed state. Unless
9974      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9975      * the pressed state.
9976      *
9977      * @see #setPressed(boolean)
9978      * @see #isClickable()
9979      * @see #setClickable(boolean)
9980      *
9981      * @return true if the view is currently pressed, false otherwise
9982      */
9983     @ViewDebug.ExportedProperty
isPressed()9984     public boolean isPressed() {
9985         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9986     }
9987 
9988     /**
9989      * @hide
9990      * Indicates whether this view will participate in data collection through
9991      * {@link ViewStructure}.  If true, it will not provide any data
9992      * for itself or its children.  If false, the normal data collection will be allowed.
9993      *
9994      * @return Returns false if assist data collection is not blocked, else true.
9995      *
9996      * @see #setAssistBlocked(boolean)
9997      * @attr ref android.R.styleable#View_assistBlocked
9998      */
isAssistBlocked()9999     public boolean isAssistBlocked() {
10000         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
10001     }
10002 
10003     /**
10004      * @hide
10005      * Controls whether assist data collection from this view and its children is enabled
10006      * (that is, whether {@link #onProvideStructure} and
10007      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
10008      * allowing normal assist collection.  Setting this to false will disable assist collection.
10009      *
10010      * @param enabled Set to true to <em>disable</em> assist data collection, or false
10011      * (the default) to allow it.
10012      *
10013      * @see #isAssistBlocked()
10014      * @see #onProvideStructure
10015      * @see #onProvideVirtualStructure
10016      * @attr ref android.R.styleable#View_assistBlocked
10017      */
setAssistBlocked(boolean enabled)10018     public void setAssistBlocked(boolean enabled) {
10019         if (enabled) {
10020             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
10021         } else {
10022             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
10023         }
10024     }
10025 
10026     /**
10027      * Indicates whether this view will save its state (that is,
10028      * whether its {@link #onSaveInstanceState} method will be called).
10029      *
10030      * @return Returns true if the view state saving is enabled, else false.
10031      *
10032      * @see #setSaveEnabled(boolean)
10033      * @attr ref android.R.styleable#View_saveEnabled
10034      */
isSaveEnabled()10035     public boolean isSaveEnabled() {
10036         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
10037     }
10038 
10039     /**
10040      * Controls whether the saving of this view's state is
10041      * enabled (that is, whether its {@link #onSaveInstanceState} method
10042      * will be called).  Note that even if freezing is enabled, the
10043      * view still must have an id assigned to it (via {@link #setId(int)})
10044      * for its state to be saved.  This flag can only disable the
10045      * saving of this view; any child views may still have their state saved.
10046      *
10047      * @param enabled Set to false to <em>disable</em> state saving, or true
10048      * (the default) to allow it.
10049      *
10050      * @see #isSaveEnabled()
10051      * @see #setId(int)
10052      * @see #onSaveInstanceState()
10053      * @attr ref android.R.styleable#View_saveEnabled
10054      */
setSaveEnabled(boolean enabled)10055     public void setSaveEnabled(boolean enabled) {
10056         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
10057     }
10058 
10059     /**
10060      * Gets whether the framework should discard touches when the view's
10061      * window is obscured by another visible window.
10062      * Refer to the {@link View} security documentation for more details.
10063      *
10064      * @return True if touch filtering is enabled.
10065      *
10066      * @see #setFilterTouchesWhenObscured(boolean)
10067      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10068      */
10069     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()10070     public boolean getFilterTouchesWhenObscured() {
10071         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
10072     }
10073 
10074     /**
10075      * Sets whether the framework should discard touches when the view's
10076      * window is obscured by another visible window.
10077      * Refer to the {@link View} security documentation for more details.
10078      *
10079      * @param enabled True if touch filtering should be enabled.
10080      *
10081      * @see #getFilterTouchesWhenObscured
10082      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10083      */
setFilterTouchesWhenObscured(boolean enabled)10084     public void setFilterTouchesWhenObscured(boolean enabled) {
10085         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
10086                 FILTER_TOUCHES_WHEN_OBSCURED);
10087     }
10088 
10089     /**
10090      * Indicates whether the entire hierarchy under this view will save its
10091      * state when a state saving traversal occurs from its parent.  The default
10092      * is true; if false, these views will not be saved unless
10093      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10094      *
10095      * @return Returns true if the view state saving from parent is enabled, else false.
10096      *
10097      * @see #setSaveFromParentEnabled(boolean)
10098      */
isSaveFromParentEnabled()10099     public boolean isSaveFromParentEnabled() {
10100         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
10101     }
10102 
10103     /**
10104      * Controls whether the entire hierarchy under this view will save its
10105      * state when a state saving traversal occurs from its parent.  The default
10106      * is true; if false, these views will not be saved unless
10107      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10108      *
10109      * @param enabled Set to false to <em>disable</em> state saving, or true
10110      * (the default) to allow it.
10111      *
10112      * @see #isSaveFromParentEnabled()
10113      * @see #setId(int)
10114      * @see #onSaveInstanceState()
10115      */
setSaveFromParentEnabled(boolean enabled)10116     public void setSaveFromParentEnabled(boolean enabled) {
10117         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
10118     }
10119 
10120 
10121     /**
10122      * Returns whether this View is currently able to take focus.
10123      *
10124      * @return True if this view can take focus, or false otherwise.
10125      */
10126     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()10127     public final boolean isFocusable() {
10128         return FOCUSABLE == (mViewFlags & FOCUSABLE);
10129     }
10130 
10131     /**
10132      * Returns the focusable setting for this view.
10133      *
10134      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
10135      * @attr ref android.R.styleable#View_focusable
10136      */
10137     @ViewDebug.ExportedProperty(mapping = {
10138             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
10139             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
10140             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
10141             }, category = "focus")
10142     @Focusable
getFocusable()10143     public int getFocusable() {
10144         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
10145     }
10146 
10147     /**
10148      * When a view is focusable, it may not want to take focus when in touch mode.
10149      * For example, a button would like focus when the user is navigating via a D-pad
10150      * so that the user can click on it, but once the user starts touching the screen,
10151      * the button shouldn't take focus
10152      * @return Whether the view is focusable in touch mode.
10153      * @attr ref android.R.styleable#View_focusableInTouchMode
10154      */
10155     @ViewDebug.ExportedProperty(category = "focus")
isFocusableInTouchMode()10156     public final boolean isFocusableInTouchMode() {
10157         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
10158     }
10159 
10160     /**
10161      * Find the nearest view in the specified direction that can take focus.
10162      * This does not actually give focus to that view.
10163      *
10164      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10165      *
10166      * @return The nearest focusable in the specified direction, or null if none
10167      *         can be found.
10168      */
focusSearch(@ocusRealDirection int direction)10169     public View focusSearch(@FocusRealDirection int direction) {
10170         if (mParent != null) {
10171             return mParent.focusSearch(this, direction);
10172         } else {
10173             return null;
10174         }
10175     }
10176 
10177     /**
10178      * Returns whether this View is a root of a keyboard navigation cluster.
10179      *
10180      * @return True if this view is a root of a cluster, or false otherwise.
10181      * @attr ref android.R.styleable#View_keyboardNavigationCluster
10182      */
10183     @ViewDebug.ExportedProperty(category = "focus")
isKeyboardNavigationCluster()10184     public final boolean isKeyboardNavigationCluster() {
10185         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
10186     }
10187 
10188     /**
10189      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
10190      * will be ignored.
10191      *
10192      * @return the keyboard navigation cluster that this view is in (can be this view)
10193      *         or {@code null} if not in one
10194      */
findKeyboardNavigationCluster()10195     View findKeyboardNavigationCluster() {
10196         if (mParent instanceof View) {
10197             View cluster = ((View) mParent).findKeyboardNavigationCluster();
10198             if (cluster != null) {
10199                 return cluster;
10200             } else if (isKeyboardNavigationCluster()) {
10201                 return this;
10202             }
10203         }
10204         return null;
10205     }
10206 
10207     /**
10208      * Set whether this view is a root of a keyboard navigation cluster.
10209      *
10210      * @param isCluster If true, this view is a root of a cluster.
10211      *
10212      * @attr ref android.R.styleable#View_keyboardNavigationCluster
10213      */
setKeyboardNavigationCluster(boolean isCluster)10214     public void setKeyboardNavigationCluster(boolean isCluster) {
10215         if (isCluster) {
10216             mPrivateFlags3 |= PFLAG3_CLUSTER;
10217         } else {
10218             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
10219         }
10220     }
10221 
10222     /**
10223      * Sets this View as the one which receives focus the next time cluster navigation jumps
10224      * to the cluster containing this View. This does NOT change focus even if the cluster
10225      * containing this view is current.
10226      *
10227      * @hide
10228      */
10229     @TestApi
setFocusedInCluster()10230     public final void setFocusedInCluster() {
10231         setFocusedInCluster(findKeyboardNavigationCluster());
10232     }
10233 
setFocusedInCluster(View cluster)10234     private void setFocusedInCluster(View cluster) {
10235         if (this instanceof ViewGroup) {
10236             ((ViewGroup) this).mFocusedInCluster = null;
10237         }
10238         if (cluster == this) {
10239             return;
10240         }
10241         ViewParent parent = mParent;
10242         View child = this;
10243         while (parent instanceof ViewGroup) {
10244             ((ViewGroup) parent).mFocusedInCluster = child;
10245             if (parent == cluster) {
10246                 break;
10247             }
10248             child = (View) parent;
10249             parent = parent.getParent();
10250         }
10251     }
10252 
updateFocusedInCluster(View oldFocus, @FocusDirection int direction)10253     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
10254         if (oldFocus != null) {
10255             View oldCluster = oldFocus.findKeyboardNavigationCluster();
10256             View cluster = findKeyboardNavigationCluster();
10257             if (oldCluster != cluster) {
10258                 // Going from one cluster to another, so save last-focused.
10259                 // This covers cluster jumps because they are always FOCUS_DOWN
10260                 oldFocus.setFocusedInCluster(oldCluster);
10261                 if (!(oldFocus.mParent instanceof ViewGroup)) {
10262                     return;
10263                 }
10264                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
10265                     // This is a result of ordered navigation so consider navigation through
10266                     // the previous cluster "complete" and clear its last-focused memory.
10267                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10268                 } else if (oldFocus instanceof ViewGroup
10269                         && ((ViewGroup) oldFocus).getDescendantFocusability()
10270                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
10271                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
10272                     // This means oldFocus is not focusable since it obviously has a focusable
10273                     // child (this). Don't restore focus to it in the future.
10274                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10275                 }
10276             }
10277         }
10278     }
10279 
10280     /**
10281      * Returns whether this View should receive focus when the focus is restored for the view
10282      * hierarchy containing this view.
10283      * <p>
10284      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10285      * window or serves as a target of cluster navigation.
10286      *
10287      * @see #restoreDefaultFocus()
10288      *
10289      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
10290      * @attr ref android.R.styleable#View_focusedByDefault
10291      */
10292     @ViewDebug.ExportedProperty(category = "focus")
isFocusedByDefault()10293     public final boolean isFocusedByDefault() {
10294         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
10295     }
10296 
10297     /**
10298      * Sets whether this View should receive focus when the focus is restored for the view
10299      * hierarchy containing this view.
10300      * <p>
10301      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10302      * window or serves as a target of cluster navigation.
10303      *
10304      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
10305      *                           {@code false} otherwise.
10306      *
10307      * @see #restoreDefaultFocus()
10308      *
10309      * @attr ref android.R.styleable#View_focusedByDefault
10310      */
setFocusedByDefault(boolean isFocusedByDefault)10311     public void setFocusedByDefault(boolean isFocusedByDefault) {
10312         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
10313             return;
10314         }
10315 
10316         if (isFocusedByDefault) {
10317             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
10318         } else {
10319             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
10320         }
10321 
10322         if (mParent instanceof ViewGroup) {
10323             if (isFocusedByDefault) {
10324                 ((ViewGroup) mParent).setDefaultFocus(this);
10325             } else {
10326                 ((ViewGroup) mParent).clearDefaultFocus(this);
10327             }
10328         }
10329     }
10330 
10331     /**
10332      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
10333      *
10334      * @return {@code true} if this view has default focus, {@code false} otherwise
10335      */
hasDefaultFocus()10336     boolean hasDefaultFocus() {
10337         return isFocusedByDefault();
10338     }
10339 
10340     /**
10341      * Find the nearest keyboard navigation cluster in the specified direction.
10342      * This does not actually give focus to that cluster.
10343      *
10344      * @param currentCluster The starting point of the search. Null means the current cluster is not
10345      *                       found yet
10346      * @param direction Direction to look
10347      *
10348      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
10349      *         can be found
10350      */
keyboardNavigationClusterSearch(View currentCluster, @FocusDirection int direction)10351     public View keyboardNavigationClusterSearch(View currentCluster,
10352             @FocusDirection int direction) {
10353         if (isKeyboardNavigationCluster()) {
10354             currentCluster = this;
10355         }
10356         if (isRootNamespace()) {
10357             // Root namespace means we should consider ourselves the top of the
10358             // tree for group searching; otherwise we could be group searching
10359             // into other tabs.  see LocalActivityManager and TabHost for more info.
10360             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
10361                     this, currentCluster, direction);
10362         } else if (mParent != null) {
10363             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
10364         }
10365         return null;
10366     }
10367 
10368     /**
10369      * This method is the last chance for the focused view and its ancestors to
10370      * respond to an arrow key. This is called when the focused view did not
10371      * consume the key internally, nor could the view system find a new view in
10372      * the requested direction to give focus to.
10373      *
10374      * @param focused The currently focused view.
10375      * @param direction The direction focus wants to move. One of FOCUS_UP,
10376      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
10377      * @return True if the this view consumed this unhandled move.
10378      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)10379     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
10380         return false;
10381     }
10382 
10383     /**
10384      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10385      * have {@link android.R.attr#state_focused} defined in its background.
10386      *
10387      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10388      *                                      highlight, {@code false} otherwise.
10389      *
10390      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10391      */
setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled)10392     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10393         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10394     }
10395 
10396     /**
10397 
10398     /**
10399      * Returns whether this View should use a default focus highlight when it gets focused but
10400      * doesn't have {@link android.R.attr#state_focused} defined in its background.
10401      *
10402      * @return True if this View should use a default focus highlight.
10403      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10404      */
10405     @ViewDebug.ExportedProperty(category = "focus")
getDefaultFocusHighlightEnabled()10406     public final boolean getDefaultFocusHighlightEnabled() {
10407         return mDefaultFocusHighlightEnabled;
10408     }
10409 
10410     /**
10411      * If a user manually specified the next view id for a particular direction,
10412      * use the root to look up the view.
10413      * @param root The root view of the hierarchy containing this view.
10414      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10415      * or FOCUS_BACKWARD.
10416      * @return The user specified next view, or null if there is none.
10417      */
findUserSetNextFocus(View root, @FocusDirection int direction)10418     View findUserSetNextFocus(View root, @FocusDirection int direction) {
10419         switch (direction) {
10420             case FOCUS_LEFT:
10421                 if (mNextFocusLeftId == View.NO_ID) return null;
10422                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10423             case FOCUS_RIGHT:
10424                 if (mNextFocusRightId == View.NO_ID) return null;
10425                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
10426             case FOCUS_UP:
10427                 if (mNextFocusUpId == View.NO_ID) return null;
10428                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
10429             case FOCUS_DOWN:
10430                 if (mNextFocusDownId == View.NO_ID) return null;
10431                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
10432             case FOCUS_FORWARD:
10433                 if (mNextFocusForwardId == View.NO_ID) return null;
10434                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10435             case FOCUS_BACKWARD: {
10436                 if (mID == View.NO_ID) return null;
10437                 final int id = mID;
10438                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10439                     @Override
10440                     public boolean test(View t) {
10441                         return t.mNextFocusForwardId == id;
10442                     }
10443                 });
10444             }
10445         }
10446         return null;
10447     }
10448 
10449     /**
10450      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10451      * use the root to look up the view.
10452      *
10453      * @param root the root view of the hierarchy containing this view
10454      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10455      * @return the user-specified next cluster, or {@code null} if there is none
10456      */
10457     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10458         switch (direction) {
10459             case FOCUS_FORWARD:
10460                 if (mNextClusterForwardId == View.NO_ID) return null;
10461                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10462             case FOCUS_BACKWARD: {
10463                 if (mID == View.NO_ID) return null;
10464                 final int id = mID;
10465                 return root.findViewByPredicateInsideOut(this,
10466                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
10467             }
10468         }
10469         return null;
10470     }
10471 
10472     private View findViewInsideOutShouldExist(View root, int id) {
10473         if (mMatchIdPredicate == null) {
10474             mMatchIdPredicate = new MatchIdPredicate();
10475         }
10476         mMatchIdPredicate.mId = id;
10477         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10478         if (result == null) {
10479             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10480         }
10481         return result;
10482     }
10483 
10484     /**
10485      * Find and return all focusable views that are descendants of this view,
10486      * possibly including this view if it is focusable itself.
10487      *
10488      * @param direction The direction of the focus
10489      * @return A list of focusable views
10490      */
10491     public ArrayList<View> getFocusables(@FocusDirection int direction) {
10492         ArrayList<View> result = new ArrayList<View>(24);
10493         addFocusables(result, direction);
10494         return result;
10495     }
10496 
10497     /**
10498      * Add any focusable views that are descendants of this view (possibly
10499      * including this view if it is focusable itself) to views.  If we are in touch mode,
10500      * only add views that are also focusable in touch mode.
10501      *
10502      * @param views Focusable views found so far
10503      * @param direction The direction of the focus
10504      */
10505     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10506         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10507     }
10508 
10509     /**
10510      * Adds any focusable views that are descendants of this view (possibly
10511      * including this view if it is focusable itself) to views. This method
10512      * adds all focusable views regardless if we are in touch mode or
10513      * only views focusable in touch mode if we are in touch mode or
10514      * only views that can take accessibility focus if accessibility is enabled
10515      * depending on the focusable mode parameter.
10516      *
10517      * @param views Focusable views found so far or null if all we are interested is
10518      *        the number of focusables.
10519      * @param direction The direction of the focus.
10520      * @param focusableMode The type of focusables to be added.
10521      *
10522      * @see #FOCUSABLES_ALL
10523      * @see #FOCUSABLES_TOUCH_MODE
10524      */
10525     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10526             @FocusableMode int focusableMode) {
10527         if (views == null) {
10528             return;
10529         }
10530         if (!isFocusable()) {
10531             return;
10532         }
10533         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10534                 && !isFocusableInTouchMode()) {
10535             return;
10536         }
10537         views.add(this);
10538     }
10539 
10540     /**
10541      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10542      * including this view if it is a cluster root itself) to views.
10543      *
10544      * @param views Keyboard navigation cluster roots found so far
10545      * @param direction Direction to look
10546      */
10547     public void addKeyboardNavigationClusters(
10548             @NonNull Collection<View> views,
10549             int direction) {
10550         if (!isKeyboardNavigationCluster()) {
10551             return;
10552         }
10553         if (!hasFocusable()) {
10554             return;
10555         }
10556         views.add(this);
10557     }
10558 
10559     /**
10560      * Finds the Views that contain given text. The containment is case insensitive.
10561      * The search is performed by either the text that the View renders or the content
10562      * description that describes the view for accessibility purposes and the view does
10563      * not render or both. Clients can specify how the search is to be performed via
10564      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10565      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10566      *
10567      * @param outViews The output list of matching Views.
10568      * @param searched The text to match against.
10569      *
10570      * @see #FIND_VIEWS_WITH_TEXT
10571      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10572      * @see #setContentDescription(CharSequence)
10573      */
10574     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10575             @FindViewFlags int flags) {
10576         if (getAccessibilityNodeProvider() != null) {
10577             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10578                 outViews.add(this);
10579             }
10580         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10581                 && (searched != null && searched.length() > 0)
10582                 && (mContentDescription != null && mContentDescription.length() > 0)) {
10583             String searchedLowerCase = searched.toString().toLowerCase();
10584             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10585             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10586                 outViews.add(this);
10587             }
10588         }
10589     }
10590 
10591     /**
10592      * Find and return all touchable views that are descendants of this view,
10593      * possibly including this view if it is touchable itself.
10594      *
10595      * @return A list of touchable views
10596      */
10597     public ArrayList<View> getTouchables() {
10598         ArrayList<View> result = new ArrayList<View>();
10599         addTouchables(result);
10600         return result;
10601     }
10602 
10603     /**
10604      * Add any touchable views that are descendants of this view (possibly
10605      * including this view if it is touchable itself) to views.
10606      *
10607      * @param views Touchable views found so far
10608      */
10609     public void addTouchables(ArrayList<View> views) {
10610         final int viewFlags = mViewFlags;
10611 
10612         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10613                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10614                 && (viewFlags & ENABLED_MASK) == ENABLED) {
10615             views.add(this);
10616         }
10617     }
10618 
10619     /**
10620      * Returns whether this View is accessibility focused.
10621      *
10622      * @return True if this View is accessibility focused.
10623      */
10624     public boolean isAccessibilityFocused() {
10625         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10626     }
10627 
10628     /**
10629      * Call this to try to give accessibility focus to this view.
10630      *
10631      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10632      * returns false or the view is no visible or the view already has accessibility
10633      * focus.
10634      *
10635      * See also {@link #focusSearch(int)}, which is what you call to say that you
10636      * have focus, and you want your parent to look for the next one.
10637      *
10638      * @return Whether this view actually took accessibility focus.
10639      *
10640      * @hide
10641      */
10642     public boolean requestAccessibilityFocus() {
10643         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10644         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10645             return false;
10646         }
10647         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10648             return false;
10649         }
10650         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10651             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10652             ViewRootImpl viewRootImpl = getViewRootImpl();
10653             if (viewRootImpl != null) {
10654                 viewRootImpl.setAccessibilityFocus(this, null);
10655             }
10656             invalidate();
10657             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10658             return true;
10659         }
10660         return false;
10661     }
10662 
10663     /**
10664      * Call this to try to clear accessibility focus of this view.
10665      *
10666      * See also {@link #focusSearch(int)}, which is what you call to say that you
10667      * have focus, and you want your parent to look for the next one.
10668      *
10669      * @hide
10670      */
10671     public void clearAccessibilityFocus() {
10672         clearAccessibilityFocusNoCallbacks(0);
10673 
10674         // Clear the global reference of accessibility focus if this view or
10675         // any of its descendants had accessibility focus. This will NOT send
10676         // an event or update internal state if focus is cleared from a
10677         // descendant view, which may leave views in inconsistent states.
10678         final ViewRootImpl viewRootImpl = getViewRootImpl();
10679         if (viewRootImpl != null) {
10680             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10681             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10682                 viewRootImpl.setAccessibilityFocus(null, null);
10683             }
10684         }
10685     }
10686 
10687     private void sendAccessibilityHoverEvent(int eventType) {
10688         // Since we are not delivering to a client accessibility events from not
10689         // important views (unless the clinet request that) we need to fire the
10690         // event from the deepest view exposed to the client. As a consequence if
10691         // the user crosses a not exposed view the client will see enter and exit
10692         // of the exposed predecessor followed by and enter and exit of that same
10693         // predecessor when entering and exiting the not exposed descendant. This
10694         // is fine since the client has a clear idea which view is hovered at the
10695         // price of a couple more events being sent. This is a simple and
10696         // working solution.
10697         View source = this;
10698         while (true) {
10699             if (source.includeForAccessibility()) {
10700                 source.sendAccessibilityEvent(eventType);
10701                 return;
10702             }
10703             ViewParent parent = source.getParent();
10704             if (parent instanceof View) {
10705                 source = (View) parent;
10706             } else {
10707                 return;
10708             }
10709         }
10710     }
10711 
10712     /**
10713      * Clears accessibility focus without calling any callback methods
10714      * normally invoked in {@link #clearAccessibilityFocus()}. This method
10715      * is used separately from that one for clearing accessibility focus when
10716      * giving this focus to another view.
10717      *
10718      * @param action The action, if any, that led to focus being cleared. Set to
10719      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10720      * the window.
10721      */
10722     void clearAccessibilityFocusNoCallbacks(int action) {
10723         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10724             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10725             invalidate();
10726             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10727                 AccessibilityEvent event = AccessibilityEvent.obtain(
10728                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10729                 event.setAction(action);
10730                 if (mAccessibilityDelegate != null) {
10731                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10732                 } else {
10733                     sendAccessibilityEventUnchecked(event);
10734                 }
10735             }
10736         }
10737     }
10738 
10739     /**
10740      * Call this to try to give focus to a specific view or to one of its
10741      * descendants.
10742      *
10743      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10744      * false), or if it is focusable and it is not focusable in touch mode
10745      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10746      *
10747      * See also {@link #focusSearch(int)}, which is what you call to say that you
10748      * have focus, and you want your parent to look for the next one.
10749      *
10750      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10751      * {@link #FOCUS_DOWN} and <code>null</code>.
10752      *
10753      * @return Whether this view or one of its descendants actually took focus.
10754      */
10755     public final boolean requestFocus() {
10756         return requestFocus(View.FOCUS_DOWN);
10757     }
10758 
10759     /**
10760      * This will request focus for whichever View was last focused within this
10761      * cluster before a focus-jump out of it.
10762      *
10763      * @hide
10764      */
10765     @TestApi
10766     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10767         // Prioritize focusableByDefault over algorithmic focus selection.
10768         if (restoreDefaultFocus()) {
10769             return true;
10770         }
10771         return requestFocus(direction);
10772     }
10773 
10774     /**
10775      * This will request focus for whichever View not in a cluster was last focused before a
10776      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10777      * the "first" focusable view it finds.
10778      *
10779      * @hide
10780      */
10781     @TestApi
10782     public boolean restoreFocusNotInCluster() {
10783         return requestFocus(View.FOCUS_DOWN);
10784     }
10785 
10786     /**
10787      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10788      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10789      *
10790      * @return Whether this view or one of its descendants actually took focus
10791      */
10792     public boolean restoreDefaultFocus() {
10793         return requestFocus(View.FOCUS_DOWN);
10794     }
10795 
10796     /**
10797      * Call this to try to give focus to a specific view or to one of its
10798      * descendants and give it a hint about what direction focus is heading.
10799      *
10800      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10801      * false), or if it is focusable and it is not focusable in touch mode
10802      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10803      *
10804      * See also {@link #focusSearch(int)}, which is what you call to say that you
10805      * have focus, and you want your parent to look for the next one.
10806      *
10807      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10808      * <code>null</code> set for the previously focused rectangle.
10809      *
10810      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10811      * @return Whether this view or one of its descendants actually took focus.
10812      */
10813     public final boolean requestFocus(int direction) {
10814         return requestFocus(direction, null);
10815     }
10816 
10817     /**
10818      * Call this to try to give focus to a specific view or to one of its descendants
10819      * and give it hints about the direction and a specific rectangle that the focus
10820      * is coming from.  The rectangle can help give larger views a finer grained hint
10821      * about where focus is coming from, and therefore, where to show selection, or
10822      * forward focus change internally.
10823      *
10824      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10825      * false), or if it is focusable and it is not focusable in touch mode
10826      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10827      *
10828      * A View will not take focus if it is not visible.
10829      *
10830      * A View will not take focus if one of its parents has
10831      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10832      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10833      *
10834      * See also {@link #focusSearch(int)}, which is what you call to say that you
10835      * have focus, and you want your parent to look for the next one.
10836      *
10837      * You may wish to override this method if your custom {@link View} has an internal
10838      * {@link View} that it wishes to forward the request to.
10839      *
10840      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10841      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10842      *        to give a finer grained hint about where focus is coming from.  May be null
10843      *        if there is no hint.
10844      * @return Whether this view or one of its descendants actually took focus.
10845      */
10846     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10847         return requestFocusNoSearch(direction, previouslyFocusedRect);
10848     }
10849 
10850     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10851         // need to be focusable
10852         if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10853                 || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10854             return false;
10855         }
10856 
10857         // need to be focusable in touch mode if in touch mode
10858         if (isInTouchMode() &&
10859             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10860                return false;
10861         }
10862 
10863         // need to not have any parents blocking us
10864         if (hasAncestorThatBlocksDescendantFocus()) {
10865             return false;
10866         }
10867 
10868         handleFocusGainInternal(direction, previouslyFocusedRect);
10869         return true;
10870     }
10871 
10872     /**
10873      * Call this to try to give focus to a specific view or to one of its descendants. This is a
10874      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10875      * touch mode to request focus when they are touched.
10876      *
10877      * @return Whether this view or one of its descendants actually took focus.
10878      *
10879      * @see #isInTouchMode()
10880      *
10881      */
10882     public final boolean requestFocusFromTouch() {
10883         // Leave touch mode if we need to
10884         if (isInTouchMode()) {
10885             ViewRootImpl viewRoot = getViewRootImpl();
10886             if (viewRoot != null) {
10887                 viewRoot.ensureTouchMode(false);
10888             }
10889         }
10890         return requestFocus(View.FOCUS_DOWN);
10891     }
10892 
10893     /**
10894      * @return Whether any ancestor of this view blocks descendant focus.
10895      */
10896     private boolean hasAncestorThatBlocksDescendantFocus() {
10897         final boolean focusableInTouchMode = isFocusableInTouchMode();
10898         ViewParent ancestor = mParent;
10899         while (ancestor instanceof ViewGroup) {
10900             final ViewGroup vgAncestor = (ViewGroup) ancestor;
10901             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10902                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10903                 return true;
10904             } else {
10905                 ancestor = vgAncestor.getParent();
10906             }
10907         }
10908         return false;
10909     }
10910 
10911     /**
10912      * Gets the mode for determining whether this View is important for accessibility.
10913      * A view is important for accessibility if it fires accessibility events and if it
10914      * is reported to accessibility services that query the screen.
10915      *
10916      * @return The mode for determining whether a view is important for accessibility, one
10917      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10918      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10919      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10920      *
10921      * @attr ref android.R.styleable#View_importantForAccessibility
10922      *
10923      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10924      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10925      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10926      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10927      */
10928     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10929             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10930             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10931             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10932             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10933                     to = "noHideDescendants")
10934         })
10935     public int getImportantForAccessibility() {
10936         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10937                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10938     }
10939 
10940     /**
10941      * Sets the live region mode for this view. This indicates to accessibility
10942      * services whether they should automatically notify the user about changes
10943      * to the view's content description or text, or to the content descriptions
10944      * or text of the view's children (where applicable).
10945      * <p>
10946      * For example, in a login screen with a TextView that displays an "incorrect
10947      * password" notification, that view should be marked as a live region with
10948      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10949      * <p>
10950      * To disable change notifications for this view, use
10951      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10952      * mode for most views.
10953      * <p>
10954      * To indicate that the user should be notified of changes, use
10955      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10956      * <p>
10957      * If the view's changes should interrupt ongoing speech and notify the user
10958      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10959      *
10960      * @param mode The live region mode for this view, one of:
10961      *        <ul>
10962      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10963      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10964      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10965      *        </ul>
10966      * @attr ref android.R.styleable#View_accessibilityLiveRegion
10967      */
10968     public void setAccessibilityLiveRegion(int mode) {
10969         if (mode != getAccessibilityLiveRegion()) {
10970             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10971             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10972                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10973             notifyViewAccessibilityStateChangedIfNeeded(
10974                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10975         }
10976     }
10977 
10978     /**
10979      * Gets the live region mode for this View.
10980      *
10981      * @return The live region mode for the view.
10982      *
10983      * @attr ref android.R.styleable#View_accessibilityLiveRegion
10984      *
10985      * @see #setAccessibilityLiveRegion(int)
10986      */
10987     public int getAccessibilityLiveRegion() {
10988         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10989                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10990     }
10991 
10992     /**
10993      * Sets how to determine whether this view is important for accessibility
10994      * which is if it fires accessibility events and if it is reported to
10995      * accessibility services that query the screen.
10996      *
10997      * @param mode How to determine whether this view is important for accessibility.
10998      *
10999      * @attr ref android.R.styleable#View_importantForAccessibility
11000      *
11001      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
11002      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
11003      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
11004      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
11005      */
11006     public void setImportantForAccessibility(int mode) {
11007         final int oldMode = getImportantForAccessibility();
11008         if (mode != oldMode) {
11009             final boolean hideDescendants =
11010                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
11011 
11012             // If this node or its descendants are no longer important, try to
11013             // clear accessibility focus.
11014             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
11015                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
11016                 if (focusHost != null) {
11017                     focusHost.clearAccessibilityFocus();
11018                 }
11019             }
11020 
11021             // If we're moving between AUTO and another state, we might not need
11022             // to send a subtree changed notification. We'll store the computed
11023             // importance, since we'll need to check it later to make sure.
11024             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
11025                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
11026             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
11027             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
11028             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
11029                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
11030             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
11031                 notifySubtreeAccessibilityStateChangedIfNeeded();
11032             } else {
11033                 notifyViewAccessibilityStateChangedIfNeeded(
11034                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11035             }
11036         }
11037     }
11038 
11039     /**
11040      * Returns the view within this view's hierarchy that is hosting
11041      * accessibility focus.
11042      *
11043      * @param searchDescendants whether to search for focus in descendant views
11044      * @return the view hosting accessibility focus, or {@code null}
11045      */
11046     private View findAccessibilityFocusHost(boolean searchDescendants) {
11047         if (isAccessibilityFocusedViewOrHost()) {
11048             return this;
11049         }
11050 
11051         if (searchDescendants) {
11052             final ViewRootImpl viewRoot = getViewRootImpl();
11053             if (viewRoot != null) {
11054                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
11055                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
11056                     return focusHost;
11057                 }
11058             }
11059         }
11060 
11061         return null;
11062     }
11063 
11064     /**
11065      * Computes whether this view should be exposed for accessibility. In
11066      * general, views that are interactive or provide information are exposed
11067      * while views that serve only as containers are hidden.
11068      * <p>
11069      * If an ancestor of this view has importance
11070      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
11071      * returns <code>false</code>.
11072      * <p>
11073      * Otherwise, the value is computed according to the view's
11074      * {@link #getImportantForAccessibility()} value:
11075      * <ol>
11076      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
11077      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
11078      * </code>
11079      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
11080      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
11081      * view satisfies any of the following:
11082      * <ul>
11083      * <li>Is actionable, e.g. {@link #isClickable()},
11084      * {@link #isLongClickable()}, or {@link #isFocusable()}
11085      * <li>Has an {@link AccessibilityDelegate}
11086      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
11087      * {@link OnKeyListener}, etc.
11088      * <li>Is an accessibility live region, e.g.
11089      * {@link #getAccessibilityLiveRegion()} is not
11090      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
11091      * </ul>
11092      * </ol>
11093      *
11094      * @return Whether the view is exposed for accessibility.
11095      * @see #setImportantForAccessibility(int)
11096      * @see #getImportantForAccessibility()
11097      */
11098     public boolean isImportantForAccessibility() {
11099         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
11100                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
11101         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
11102                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11103             return false;
11104         }
11105 
11106         // Check parent mode to ensure we're not hidden.
11107         ViewParent parent = mParent;
11108         while (parent instanceof View) {
11109             if (((View) parent).getImportantForAccessibility()
11110                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11111                 return false;
11112             }
11113             parent = parent.getParent();
11114         }
11115 
11116         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
11117                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
11118                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
11119     }
11120 
11121     /**
11122      * Gets the parent for accessibility purposes. Note that the parent for
11123      * accessibility is not necessary the immediate parent. It is the first
11124      * predecessor that is important for accessibility.
11125      *
11126      * @return The parent for accessibility purposes.
11127      */
11128     public ViewParent getParentForAccessibility() {
11129         if (mParent instanceof View) {
11130             View parentView = (View) mParent;
11131             if (parentView.includeForAccessibility()) {
11132                 return mParent;
11133             } else {
11134                 return mParent.getParentForAccessibility();
11135             }
11136         }
11137         return null;
11138     }
11139 
11140     /**
11141      * Adds the children of this View relevant for accessibility to the given list
11142      * as output. Since some Views are not important for accessibility the added
11143      * child views are not necessarily direct children of this view, rather they are
11144      * the first level of descendants important for accessibility.
11145      *
11146      * @param outChildren The output list that will receive children for accessibility.
11147      */
11148     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
11149 
11150     }
11151 
11152     /**
11153      * Whether to regard this view for accessibility. A view is regarded for
11154      * accessibility if it is important for accessibility or the querying
11155      * accessibility service has explicitly requested that view not
11156      * important for accessibility are regarded.
11157      *
11158      * @return Whether to regard the view for accessibility.
11159      *
11160      * @hide
11161      */
11162     public boolean includeForAccessibility() {
11163         if (mAttachInfo != null) {
11164             return (mAttachInfo.mAccessibilityFetchFlags
11165                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
11166                     || isImportantForAccessibility();
11167         }
11168         return false;
11169     }
11170 
11171     /**
11172      * Returns whether the View is considered actionable from
11173      * accessibility perspective. Such view are important for
11174      * accessibility.
11175      *
11176      * @return True if the view is actionable for accessibility.
11177      *
11178      * @hide
11179      */
11180     public boolean isActionableForAccessibility() {
11181         return (isClickable() || isLongClickable() || isFocusable());
11182     }
11183 
11184     /**
11185      * Returns whether the View has registered callbacks which makes it
11186      * important for accessibility.
11187      *
11188      * @return True if the view is actionable for accessibility.
11189      */
11190     private boolean hasListenersForAccessibility() {
11191         ListenerInfo info = getListenerInfo();
11192         return mTouchDelegate != null || info.mOnKeyListener != null
11193                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
11194                 || info.mOnHoverListener != null || info.mOnDragListener != null;
11195     }
11196 
11197     /**
11198      * Notifies that the accessibility state of this view changed. The change
11199      * is local to this view and does not represent structural changes such
11200      * as children and parent. For example, the view became focusable. The
11201      * notification is at at most once every
11202      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11203      * to avoid unnecessary load to the system. Also once a view has a pending
11204      * notification this method is a NOP until the notification has been sent.
11205      *
11206      * @hide
11207      */
11208     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
11209         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11210             return;
11211         }
11212         // If this is a live region, we should send a subtree change event
11213         // from this view immediately. Otherwise, we can let it propagate up.
11214         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
11215             final AccessibilityEvent event = AccessibilityEvent.obtain();
11216             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
11217             event.setContentChangeTypes(changeType);
11218             sendAccessibilityEventUnchecked(event);
11219         } else if (mParent != null) {
11220             try {
11221                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
11222             } catch (AbstractMethodError e) {
11223                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11224                         " does not fully implement ViewParent", e);
11225             }
11226         }
11227     }
11228 
11229     /**
11230      * Notifies that the accessibility state of this view changed. The change
11231      * is *not* local to this view and does represent structural changes such
11232      * as children and parent. For example, the view size changed. The
11233      * notification is at at most once every
11234      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11235      * to avoid unnecessary load to the system. Also once a view has a pending
11236      * notification this method is a NOP until the notification has been sent.
11237      *
11238      * @hide
11239      */
11240     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
11241         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11242             return;
11243         }
11244         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
11245             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11246             if (mParent != null) {
11247                 try {
11248                     mParent.notifySubtreeAccessibilityStateChanged(
11249                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
11250                 } catch (AbstractMethodError e) {
11251                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11252                             " does not fully implement ViewParent", e);
11253                 }
11254             }
11255         }
11256     }
11257 
11258     /**
11259      * Change the visibility of the View without triggering any other changes. This is
11260      * important for transitions, where visibility changes should not adjust focus or
11261      * trigger a new layout. This is only used when the visibility has already been changed
11262      * and we need a transient value during an animation. When the animation completes,
11263      * the original visibility value is always restored.
11264      *
11265      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11266      * @hide
11267      */
11268     public void setTransitionVisibility(@Visibility int visibility) {
11269         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
11270     }
11271 
11272     /**
11273      * Reset the flag indicating the accessibility state of the subtree rooted
11274      * at this view changed.
11275      */
11276     void resetSubtreeAccessibilityStateChanged() {
11277         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11278     }
11279 
11280     /**
11281      * Report an accessibility action to this view's parents for delegated processing.
11282      *
11283      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
11284      * call this method to delegate an accessibility action to a supporting parent. If the parent
11285      * returns true from its
11286      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
11287      * method this method will return true to signify that the action was consumed.</p>
11288      *
11289      * <p>This method is useful for implementing nested scrolling child views. If
11290      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
11291      * a custom view implementation may invoke this method to allow a parent to consume the
11292      * scroll first. If this method returns true the custom view should skip its own scrolling
11293      * behavior.</p>
11294      *
11295      * @param action Accessibility action to delegate
11296      * @param arguments Optional action arguments
11297      * @return true if the action was consumed by a parent
11298      */
11299     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
11300         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
11301             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
11302                 return true;
11303             }
11304         }
11305         return false;
11306     }
11307 
11308     /**
11309      * Performs the specified accessibility action on the view. For
11310      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
11311      * <p>
11312      * If an {@link AccessibilityDelegate} has been specified via calling
11313      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11314      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
11315      * is responsible for handling this call.
11316      * </p>
11317      *
11318      * <p>The default implementation will delegate
11319      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
11320      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
11321      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
11322      *
11323      * @param action The action to perform.
11324      * @param arguments Optional action arguments.
11325      * @return Whether the action was performed.
11326      */
11327     public boolean performAccessibilityAction(int action, Bundle arguments) {
11328       if (mAccessibilityDelegate != null) {
11329           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
11330       } else {
11331           return performAccessibilityActionInternal(action, arguments);
11332       }
11333     }
11334 
11335    /**
11336     * @see #performAccessibilityAction(int, Bundle)
11337     *
11338     * Note: Called from the default {@link AccessibilityDelegate}.
11339     *
11340     * @hide
11341     */
11342     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
11343         if (isNestedScrollingEnabled()
11344                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
11345                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
11346                 || action == R.id.accessibilityActionScrollUp
11347                 || action == R.id.accessibilityActionScrollLeft
11348                 || action == R.id.accessibilityActionScrollDown
11349                 || action == R.id.accessibilityActionScrollRight)) {
11350             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
11351                 return true;
11352             }
11353         }
11354 
11355         switch (action) {
11356             case AccessibilityNodeInfo.ACTION_CLICK: {
11357                 if (isClickable()) {
11358                     performClick();
11359                     return true;
11360                 }
11361             } break;
11362             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
11363                 if (isLongClickable()) {
11364                     performLongClick();
11365                     return true;
11366                 }
11367             } break;
11368             case AccessibilityNodeInfo.ACTION_FOCUS: {
11369                 if (!hasFocus()) {
11370                     // Get out of touch mode since accessibility
11371                     // wants to move focus around.
11372                     getViewRootImpl().ensureTouchMode(false);
11373                     return requestFocus();
11374                 }
11375             } break;
11376             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
11377                 if (hasFocus()) {
11378                     clearFocus();
11379                     return !isFocused();
11380                 }
11381             } break;
11382             case AccessibilityNodeInfo.ACTION_SELECT: {
11383                 if (!isSelected()) {
11384                     setSelected(true);
11385                     return isSelected();
11386                 }
11387             } break;
11388             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
11389                 if (isSelected()) {
11390                     setSelected(false);
11391                     return !isSelected();
11392                 }
11393             } break;
11394             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11395                 if (!isAccessibilityFocused()) {
11396                     return requestAccessibilityFocus();
11397                 }
11398             } break;
11399             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11400                 if (isAccessibilityFocused()) {
11401                     clearAccessibilityFocus();
11402                     return true;
11403                 }
11404             } break;
11405             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
11406                 if (arguments != null) {
11407                     final int granularity = arguments.getInt(
11408                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11409                     final boolean extendSelection = arguments.getBoolean(
11410                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11411                     return traverseAtGranularity(granularity, true, extendSelection);
11412                 }
11413             } break;
11414             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11415                 if (arguments != null) {
11416                     final int granularity = arguments.getInt(
11417                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11418                     final boolean extendSelection = arguments.getBoolean(
11419                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11420                     return traverseAtGranularity(granularity, false, extendSelection);
11421                 }
11422             } break;
11423             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11424                 CharSequence text = getIterableTextForAccessibility();
11425                 if (text == null) {
11426                     return false;
11427                 }
11428                 final int start = (arguments != null) ? arguments.getInt(
11429                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11430                 final int end = (arguments != null) ? arguments.getInt(
11431                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11432                 // Only cursor position can be specified (selection length == 0)
11433                 if ((getAccessibilitySelectionStart() != start
11434                         || getAccessibilitySelectionEnd() != end)
11435                         && (start == end)) {
11436                     setAccessibilitySelection(start, end);
11437                     notifyViewAccessibilityStateChangedIfNeeded(
11438                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11439                     return true;
11440                 }
11441             } break;
11442             case R.id.accessibilityActionShowOnScreen: {
11443                 if (mAttachInfo != null) {
11444                     final Rect r = mAttachInfo.mTmpInvalRect;
11445                     getDrawingRect(r);
11446                     return requestRectangleOnScreen(r, true);
11447                 }
11448             } break;
11449             case R.id.accessibilityActionContextClick: {
11450                 if (isContextClickable()) {
11451                     performContextClick();
11452                     return true;
11453                 }
11454             } break;
11455         }
11456         return false;
11457     }
11458 
11459     private boolean traverseAtGranularity(int granularity, boolean forward,
11460             boolean extendSelection) {
11461         CharSequence text = getIterableTextForAccessibility();
11462         if (text == null || text.length() == 0) {
11463             return false;
11464         }
11465         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11466         if (iterator == null) {
11467             return false;
11468         }
11469         int current = getAccessibilitySelectionEnd();
11470         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11471             current = forward ? 0 : text.length();
11472         }
11473         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11474         if (range == null) {
11475             return false;
11476         }
11477         final int segmentStart = range[0];
11478         final int segmentEnd = range[1];
11479         int selectionStart;
11480         int selectionEnd;
11481         if (extendSelection && isAccessibilitySelectionExtendable()) {
11482             selectionStart = getAccessibilitySelectionStart();
11483             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11484                 selectionStart = forward ? segmentStart : segmentEnd;
11485             }
11486             selectionEnd = forward ? segmentEnd : segmentStart;
11487         } else {
11488             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11489         }
11490         setAccessibilitySelection(selectionStart, selectionEnd);
11491         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11492                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11493         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11494         return true;
11495     }
11496 
11497     /**
11498      * Gets the text reported for accessibility purposes.
11499      *
11500      * @return The accessibility text.
11501      *
11502      * @hide
11503      */
11504     public CharSequence getIterableTextForAccessibility() {
11505         return getContentDescription();
11506     }
11507 
11508     /**
11509      * Gets whether accessibility selection can be extended.
11510      *
11511      * @return If selection is extensible.
11512      *
11513      * @hide
11514      */
11515     public boolean isAccessibilitySelectionExtendable() {
11516         return false;
11517     }
11518 
11519     /**
11520      * @hide
11521      */
11522     public int getAccessibilitySelectionStart() {
11523         return mAccessibilityCursorPosition;
11524     }
11525 
11526     /**
11527      * @hide
11528      */
11529     public int getAccessibilitySelectionEnd() {
11530         return getAccessibilitySelectionStart();
11531     }
11532 
11533     /**
11534      * @hide
11535      */
11536     public void setAccessibilitySelection(int start, int end) {
11537         if (start ==  end && end == mAccessibilityCursorPosition) {
11538             return;
11539         }
11540         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11541             mAccessibilityCursorPosition = start;
11542         } else {
11543             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11544         }
11545         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11546     }
11547 
11548     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11549             int fromIndex, int toIndex) {
11550         if (mParent == null) {
11551             return;
11552         }
11553         AccessibilityEvent event = AccessibilityEvent.obtain(
11554                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11555         onInitializeAccessibilityEvent(event);
11556         onPopulateAccessibilityEvent(event);
11557         event.setFromIndex(fromIndex);
11558         event.setToIndex(toIndex);
11559         event.setAction(action);
11560         event.setMovementGranularity(granularity);
11561         mParent.requestSendAccessibilityEvent(this, event);
11562     }
11563 
11564     /**
11565      * @hide
11566      */
11567     public TextSegmentIterator getIteratorForGranularity(int granularity) {
11568         switch (granularity) {
11569             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11570                 CharSequence text = getIterableTextForAccessibility();
11571                 if (text != null && text.length() > 0) {
11572                     CharacterTextSegmentIterator iterator =
11573                         CharacterTextSegmentIterator.getInstance(
11574                                 mContext.getResources().getConfiguration().locale);
11575                     iterator.initialize(text.toString());
11576                     return iterator;
11577                 }
11578             } break;
11579             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11580                 CharSequence text = getIterableTextForAccessibility();
11581                 if (text != null && text.length() > 0) {
11582                     WordTextSegmentIterator iterator =
11583                         WordTextSegmentIterator.getInstance(
11584                                 mContext.getResources().getConfiguration().locale);
11585                     iterator.initialize(text.toString());
11586                     return iterator;
11587                 }
11588             } break;
11589             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11590                 CharSequence text = getIterableTextForAccessibility();
11591                 if (text != null && text.length() > 0) {
11592                     ParagraphTextSegmentIterator iterator =
11593                         ParagraphTextSegmentIterator.getInstance();
11594                     iterator.initialize(text.toString());
11595                     return iterator;
11596                 }
11597             } break;
11598         }
11599         return null;
11600     }
11601 
11602     /**
11603      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11604      * and {@link #onFinishTemporaryDetach()}.
11605      *
11606      * <p>This method always returns {@code true} when called directly or indirectly from
11607      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11608      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11609      * <ul>
11610      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11611      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11612      * </ul>
11613      * </p>
11614      *
11615      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11616      * and {@link #onFinishTemporaryDetach()}.
11617      */
11618     public final boolean isTemporarilyDetached() {
11619         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11620     }
11621 
11622     /**
11623      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11624      * a container View.
11625      */
11626     @CallSuper
11627     public void dispatchStartTemporaryDetach() {
11628         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11629         notifyEnterOrExitForAutoFillIfNeeded(false);
11630         onStartTemporaryDetach();
11631     }
11632 
11633     /**
11634      * This is called when a container is going to temporarily detach a child, with
11635      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11636      * It will either be followed by {@link #onFinishTemporaryDetach()} or
11637      * {@link #onDetachedFromWindow()} when the container is done.
11638      */
11639     public void onStartTemporaryDetach() {
11640         removeUnsetPressCallback();
11641         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11642     }
11643 
11644     /**
11645      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11646      * a container View.
11647      */
11648     @CallSuper
11649     public void dispatchFinishTemporaryDetach() {
11650         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11651         onFinishTemporaryDetach();
11652         if (hasWindowFocus() && hasFocus()) {
11653             InputMethodManager.getInstance().focusIn(this);
11654         }
11655         notifyEnterOrExitForAutoFillIfNeeded(true);
11656     }
11657 
11658     /**
11659      * Called after {@link #onStartTemporaryDetach} when the container is done
11660      * changing the view.
11661      */
11662     public void onFinishTemporaryDetach() {
11663     }
11664 
11665     /**
11666      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11667      * for this view's window.  Returns null if the view is not currently attached
11668      * to the window.  Normally you will not need to use this directly, but
11669      * just use the standard high-level event callbacks like
11670      * {@link #onKeyDown(int, KeyEvent)}.
11671      */
11672     public KeyEvent.DispatcherState getKeyDispatcherState() {
11673         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11674     }
11675 
11676     /**
11677      * Dispatch a key event before it is processed by any input method
11678      * associated with the view hierarchy.  This can be used to intercept
11679      * key events in special situations before the IME consumes them; a
11680      * typical example would be handling the BACK key to update the application's
11681      * UI instead of allowing the IME to see it and close itself.
11682      *
11683      * @param event The key event to be dispatched.
11684      * @return True if the event was handled, false otherwise.
11685      */
11686     public boolean dispatchKeyEventPreIme(KeyEvent event) {
11687         return onKeyPreIme(event.getKeyCode(), event);
11688     }
11689 
11690     /**
11691      * Dispatch a key event to the next view on the focus path. This path runs
11692      * from the top of the view tree down to the currently focused view. If this
11693      * view has focus, it will dispatch to itself. Otherwise it will dispatch
11694      * the next node down the focus path. This method also fires any key
11695      * listeners.
11696      *
11697      * @param event The key event to be dispatched.
11698      * @return True if the event was handled, false otherwise.
11699      */
11700     public boolean dispatchKeyEvent(KeyEvent event) {
11701         if (mInputEventConsistencyVerifier != null) {
11702             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11703         }
11704 
11705         // Give any attached key listener a first crack at the event.
11706         //noinspection SimplifiableIfStatement
11707         ListenerInfo li = mListenerInfo;
11708         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11709                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11710             return true;
11711         }
11712 
11713         if (event.dispatch(this, mAttachInfo != null
11714                 ? mAttachInfo.mKeyDispatchState : null, this)) {
11715             return true;
11716         }
11717 
11718         if (mInputEventConsistencyVerifier != null) {
11719             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11720         }
11721         return false;
11722     }
11723 
11724     /**
11725      * Dispatches a key shortcut event.
11726      *
11727      * @param event The key event to be dispatched.
11728      * @return True if the event was handled by the view, false otherwise.
11729      */
11730     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11731         return onKeyShortcut(event.getKeyCode(), event);
11732     }
11733 
11734     /**
11735      * Pass the touch screen motion event down to the target view, or this
11736      * view if it is the target.
11737      *
11738      * @param event The motion event to be dispatched.
11739      * @return True if the event was handled by the view, false otherwise.
11740      */
11741     public boolean dispatchTouchEvent(MotionEvent event) {
11742         // If the event should be handled by accessibility focus first.
11743         if (event.isTargetAccessibilityFocus()) {
11744             // We don't have focus or no virtual descendant has it, do not handle the event.
11745             if (!isAccessibilityFocusedViewOrHost()) {
11746                 return false;
11747             }
11748             // We have focus and got the event, then use normal event dispatch.
11749             event.setTargetAccessibilityFocus(false);
11750         }
11751 
11752         boolean result = false;
11753 
11754         if (mInputEventConsistencyVerifier != null) {
11755             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11756         }
11757 
11758         final int actionMasked = event.getActionMasked();
11759         if (actionMasked == MotionEvent.ACTION_DOWN) {
11760             // Defensive cleanup for new gesture
11761             stopNestedScroll();
11762         }
11763 
11764         if (onFilterTouchEventForSecurity(event)) {
11765             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11766                 result = true;
11767             }
11768             //noinspection SimplifiableIfStatement
11769             ListenerInfo li = mListenerInfo;
11770             if (li != null && li.mOnTouchListener != null
11771                     && (mViewFlags & ENABLED_MASK) == ENABLED
11772                     && li.mOnTouchListener.onTouch(this, event)) {
11773                 result = true;
11774             }
11775 
11776             if (!result && onTouchEvent(event)) {
11777                 result = true;
11778             }
11779         }
11780 
11781         if (!result && mInputEventConsistencyVerifier != null) {
11782             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11783         }
11784 
11785         // Clean up after nested scrolls if this is the end of a gesture;
11786         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11787         // of the gesture.
11788         if (actionMasked == MotionEvent.ACTION_UP ||
11789                 actionMasked == MotionEvent.ACTION_CANCEL ||
11790                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11791             stopNestedScroll();
11792         }
11793 
11794         return result;
11795     }
11796 
11797     boolean isAccessibilityFocusedViewOrHost() {
11798         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11799                 .getAccessibilityFocusedHost() == this);
11800     }
11801 
11802     /**
11803      * Filter the touch event to apply security policies.
11804      *
11805      * @param event The motion event to be filtered.
11806      * @return True if the event should be dispatched, false if the event should be dropped.
11807      *
11808      * @see #getFilterTouchesWhenObscured
11809      */
11810     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11811         //noinspection RedundantIfStatement
11812         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11813                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11814             // Window is obscured, drop this touch.
11815             return false;
11816         }
11817         return true;
11818     }
11819 
11820     /**
11821      * Pass a trackball motion event down to the focused view.
11822      *
11823      * @param event The motion event to be dispatched.
11824      * @return True if the event was handled by the view, false otherwise.
11825      */
11826     public boolean dispatchTrackballEvent(MotionEvent event) {
11827         if (mInputEventConsistencyVerifier != null) {
11828             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11829         }
11830 
11831         return onTrackballEvent(event);
11832     }
11833 
11834     /**
11835      * Pass a captured pointer event down to the focused view.
11836      *
11837      * @param event The motion event to be dispatched.
11838      * @return True if the event was handled by the view, false otherwise.
11839      */
11840     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11841         if (!hasPointerCapture()) {
11842             return false;
11843         }
11844         //noinspection SimplifiableIfStatement
11845         ListenerInfo li = mListenerInfo;
11846         if (li != null && li.mOnCapturedPointerListener != null
11847                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11848             return true;
11849         }
11850         return onCapturedPointerEvent(event);
11851     }
11852 
11853     /**
11854      * Dispatch a generic motion event.
11855      * <p>
11856      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11857      * are delivered to the view under the pointer.  All other generic motion events are
11858      * delivered to the focused view.  Hover events are handled specially and are delivered
11859      * to {@link #onHoverEvent(MotionEvent)}.
11860      * </p>
11861      *
11862      * @param event The motion event to be dispatched.
11863      * @return True if the event was handled by the view, false otherwise.
11864      */
11865     public boolean dispatchGenericMotionEvent(MotionEvent event) {
11866         if (mInputEventConsistencyVerifier != null) {
11867             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11868         }
11869 
11870         final int source = event.getSource();
11871         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11872             final int action = event.getAction();
11873             if (action == MotionEvent.ACTION_HOVER_ENTER
11874                     || action == MotionEvent.ACTION_HOVER_MOVE
11875                     || action == MotionEvent.ACTION_HOVER_EXIT) {
11876                 if (dispatchHoverEvent(event)) {
11877                     return true;
11878                 }
11879             } else if (dispatchGenericPointerEvent(event)) {
11880                 return true;
11881             }
11882         } else if (dispatchGenericFocusedEvent(event)) {
11883             return true;
11884         }
11885 
11886         if (dispatchGenericMotionEventInternal(event)) {
11887             return true;
11888         }
11889 
11890         if (mInputEventConsistencyVerifier != null) {
11891             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11892         }
11893         return false;
11894     }
11895 
11896     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11897         //noinspection SimplifiableIfStatement
11898         ListenerInfo li = mListenerInfo;
11899         if (li != null && li.mOnGenericMotionListener != null
11900                 && (mViewFlags & ENABLED_MASK) == ENABLED
11901                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11902             return true;
11903         }
11904 
11905         if (onGenericMotionEvent(event)) {
11906             return true;
11907         }
11908 
11909         final int actionButton = event.getActionButton();
11910         switch (event.getActionMasked()) {
11911             case MotionEvent.ACTION_BUTTON_PRESS:
11912                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11913                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11914                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11915                     if (performContextClick(event.getX(), event.getY())) {
11916                         mInContextButtonPress = true;
11917                         setPressed(true, event.getX(), event.getY());
11918                         removeTapCallback();
11919                         removeLongPressCallback();
11920                         return true;
11921                     }
11922                 }
11923                 break;
11924 
11925             case MotionEvent.ACTION_BUTTON_RELEASE:
11926                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11927                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11928                     mInContextButtonPress = false;
11929                     mIgnoreNextUpEvent = true;
11930                 }
11931                 break;
11932         }
11933 
11934         if (mInputEventConsistencyVerifier != null) {
11935             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11936         }
11937         return false;
11938     }
11939 
11940     /**
11941      * Dispatch a hover event.
11942      * <p>
11943      * Do not call this method directly.
11944      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11945      * </p>
11946      *
11947      * @param event The motion event to be dispatched.
11948      * @return True if the event was handled by the view, false otherwise.
11949      */
11950     protected boolean dispatchHoverEvent(MotionEvent event) {
11951         ListenerInfo li = mListenerInfo;
11952         //noinspection SimplifiableIfStatement
11953         if (li != null && li.mOnHoverListener != null
11954                 && (mViewFlags & ENABLED_MASK) == ENABLED
11955                 && li.mOnHoverListener.onHover(this, event)) {
11956             return true;
11957         }
11958 
11959         return onHoverEvent(event);
11960     }
11961 
11962     /**
11963      * Returns true if the view has a child to which it has recently sent
11964      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11965      * it does not have a hovered child, then it must be the innermost hovered view.
11966      * @hide
11967      */
11968     protected boolean hasHoveredChild() {
11969         return false;
11970     }
11971 
11972     /**
11973      * Dispatch a generic motion event to the view under the first pointer.
11974      * <p>
11975      * Do not call this method directly.
11976      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11977      * </p>
11978      *
11979      * @param event The motion event to be dispatched.
11980      * @return True if the event was handled by the view, false otherwise.
11981      */
11982     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11983         return false;
11984     }
11985 
11986     /**
11987      * Dispatch a generic motion event to the currently focused view.
11988      * <p>
11989      * Do not call this method directly.
11990      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11991      * </p>
11992      *
11993      * @param event The motion event to be dispatched.
11994      * @return True if the event was handled by the view, false otherwise.
11995      */
11996     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11997         return false;
11998     }
11999 
12000     /**
12001      * Dispatch a pointer event.
12002      * <p>
12003      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
12004      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
12005      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
12006      * and should not be expected to handle other pointing device features.
12007      * </p>
12008      *
12009      * @param event The motion event to be dispatched.
12010      * @return True if the event was handled by the view, false otherwise.
12011      * @hide
12012      */
12013     public final boolean dispatchPointerEvent(MotionEvent event) {
12014         if (event.isTouchEvent()) {
12015             return dispatchTouchEvent(event);
12016         } else {
12017             return dispatchGenericMotionEvent(event);
12018         }
12019     }
12020 
12021     /**
12022      * Called when the window containing this view gains or loses window focus.
12023      * ViewGroups should override to route to their children.
12024      *
12025      * @param hasFocus True if the window containing this view now has focus,
12026      *        false otherwise.
12027      */
12028     public void dispatchWindowFocusChanged(boolean hasFocus) {
12029         onWindowFocusChanged(hasFocus);
12030     }
12031 
12032     /**
12033      * Called when the window containing this view gains or loses focus.  Note
12034      * that this is separate from view focus: to receive key events, both
12035      * your view and its window must have focus.  If a window is displayed
12036      * on top of yours that takes input focus, then your own window will lose
12037      * focus but the view focus will remain unchanged.
12038      *
12039      * @param hasWindowFocus True if the window containing this view now has
12040      *        focus, false otherwise.
12041      */
12042     public void onWindowFocusChanged(boolean hasWindowFocus) {
12043         InputMethodManager imm = InputMethodManager.peekInstance();
12044         if (!hasWindowFocus) {
12045             if (isPressed()) {
12046                 setPressed(false);
12047             }
12048             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12049             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12050                 imm.focusOut(this);
12051             }
12052             removeLongPressCallback();
12053             removeTapCallback();
12054             onFocusLost();
12055         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12056             imm.focusIn(this);
12057         }
12058 
12059         notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
12060 
12061         refreshDrawableState();
12062     }
12063 
12064     /**
12065      * Returns true if this view is in a window that currently has window focus.
12066      * Note that this is not the same as the view itself having focus.
12067      *
12068      * @return True if this view is in a window that currently has window focus.
12069      */
12070     public boolean hasWindowFocus() {
12071         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
12072     }
12073 
12074     /**
12075      * Dispatch a view visibility change down the view hierarchy.
12076      * ViewGroups should override to route to their children.
12077      * @param changedView The view whose visibility changed. Could be 'this' or
12078      * an ancestor view.
12079      * @param visibility The new visibility of changedView: {@link #VISIBLE},
12080      * {@link #INVISIBLE} or {@link #GONE}.
12081      */
12082     protected void dispatchVisibilityChanged(@NonNull View changedView,
12083             @Visibility int visibility) {
12084         onVisibilityChanged(changedView, visibility);
12085     }
12086 
12087     /**
12088      * Called when the visibility of the view or an ancestor of the view has
12089      * changed.
12090      *
12091      * @param changedView The view whose visibility changed. May be
12092      *                    {@code this} or an ancestor view.
12093      * @param visibility The new visibility, one of {@link #VISIBLE},
12094      *                   {@link #INVISIBLE} or {@link #GONE}.
12095      */
12096     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
12097     }
12098 
12099     /**
12100      * Dispatch a hint about whether this view is displayed. For instance, when
12101      * a View moves out of the screen, it might receives a display hint indicating
12102      * the view is not displayed. Applications should not <em>rely</em> on this hint
12103      * as there is no guarantee that they will receive one.
12104      *
12105      * @param hint A hint about whether or not this view is displayed:
12106      * {@link #VISIBLE} or {@link #INVISIBLE}.
12107      */
12108     public void dispatchDisplayHint(@Visibility int hint) {
12109         onDisplayHint(hint);
12110     }
12111 
12112     /**
12113      * Gives this view a hint about whether is displayed or not. For instance, when
12114      * a View moves out of the screen, it might receives a display hint indicating
12115      * the view is not displayed. Applications should not <em>rely</em> on this hint
12116      * as there is no guarantee that they will receive one.
12117      *
12118      * @param hint A hint about whether or not this view is displayed:
12119      * {@link #VISIBLE} or {@link #INVISIBLE}.
12120      */
12121     protected void onDisplayHint(@Visibility int hint) {
12122     }
12123 
12124     /**
12125      * Dispatch a window visibility change down the view hierarchy.
12126      * ViewGroups should override to route to their children.
12127      *
12128      * @param visibility The new visibility of the window.
12129      *
12130      * @see #onWindowVisibilityChanged(int)
12131      */
12132     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
12133         onWindowVisibilityChanged(visibility);
12134     }
12135 
12136     /**
12137      * Called when the window containing has change its visibility
12138      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
12139      * that this tells you whether or not your window is being made visible
12140      * to the window manager; this does <em>not</em> tell you whether or not
12141      * your window is obscured by other windows on the screen, even if it
12142      * is itself visible.
12143      *
12144      * @param visibility The new visibility of the window.
12145      */
12146     protected void onWindowVisibilityChanged(@Visibility int visibility) {
12147         if (visibility == VISIBLE) {
12148             initialAwakenScrollBars();
12149         }
12150     }
12151 
12152     /**
12153      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
12154      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
12155      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
12156      *
12157      * @param isVisible true if this view's visibility to the user is uninterrupted by its
12158      *                  ancestors or by window visibility
12159      * @return true if this view is visible to the user, not counting clipping or overlapping
12160      */
12161     boolean dispatchVisibilityAggregated(boolean isVisible) {
12162         final boolean thisVisible = getVisibility() == VISIBLE;
12163         // If we're not visible but something is telling us we are, ignore it.
12164         if (thisVisible || !isVisible) {
12165             onVisibilityAggregated(isVisible);
12166         }
12167         return thisVisible && isVisible;
12168     }
12169 
12170     /**
12171      * Called when the user-visibility of this View is potentially affected by a change
12172      * to this view itself, an ancestor view or the window this view is attached to.
12173      *
12174      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
12175      *                  and this view's window is also visible
12176      */
12177     @CallSuper
12178     public void onVisibilityAggregated(boolean isVisible) {
12179         if (isVisible && mAttachInfo != null) {
12180             initialAwakenScrollBars();
12181         }
12182 
12183         final Drawable dr = mBackground;
12184         if (dr != null && isVisible != dr.isVisible()) {
12185             dr.setVisible(isVisible, false);
12186         }
12187         final Drawable hl = mDefaultFocusHighlight;
12188         if (hl != null && isVisible != hl.isVisible()) {
12189             hl.setVisible(isVisible, false);
12190         }
12191         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
12192         if (fg != null && isVisible != fg.isVisible()) {
12193             fg.setVisible(isVisible, false);
12194         }
12195 
12196         if (isAutofillable()) {
12197             AutofillManager afm = getAutofillManager();
12198 
12199             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
12200                 if (mVisibilityChangeForAutofillHandler != null) {
12201                     mVisibilityChangeForAutofillHandler.removeMessages(0);
12202                 }
12203 
12204                 // If the view is in the background but still part of the hierarchy this is called
12205                 // with isVisible=false. Hence visibility==false requires further checks
12206                 if (isVisible) {
12207                     afm.notifyViewVisibilityChanged(this, true);
12208                 } else {
12209                     if (mVisibilityChangeForAutofillHandler == null) {
12210                         mVisibilityChangeForAutofillHandler =
12211                                 new VisibilityChangeForAutofillHandler(afm, this);
12212                     }
12213                     // Let current operation (e.g. removal of the view from the hierarchy)
12214                     // finish before checking state
12215                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
12216                 }
12217             }
12218         }
12219     }
12220 
12221     /**
12222      * Returns the current visibility of the window this view is attached to
12223      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
12224      *
12225      * @return Returns the current visibility of the view's window.
12226      */
12227     @Visibility
12228     public int getWindowVisibility() {
12229         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
12230     }
12231 
12232     /**
12233      * Retrieve the overall visible display size in which the window this view is
12234      * attached to has been positioned in.  This takes into account screen
12235      * decorations above the window, for both cases where the window itself
12236      * is being position inside of them or the window is being placed under
12237      * then and covered insets are used for the window to position its content
12238      * inside.  In effect, this tells you the available area where content can
12239      * be placed and remain visible to users.
12240      *
12241      * <p>This function requires an IPC back to the window manager to retrieve
12242      * the requested information, so should not be used in performance critical
12243      * code like drawing.
12244      *
12245      * @param outRect Filled in with the visible display frame.  If the view
12246      * is not attached to a window, this is simply the raw display size.
12247      */
12248     public void getWindowVisibleDisplayFrame(Rect outRect) {
12249         if (mAttachInfo != null) {
12250             try {
12251                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12252             } catch (RemoteException e) {
12253                 return;
12254             }
12255             // XXX This is really broken, and probably all needs to be done
12256             // in the window manager, and we need to know more about whether
12257             // we want the area behind or in front of the IME.
12258             final Rect insets = mAttachInfo.mVisibleInsets;
12259             outRect.left += insets.left;
12260             outRect.top += insets.top;
12261             outRect.right -= insets.right;
12262             outRect.bottom -= insets.bottom;
12263             return;
12264         }
12265         // The view is not attached to a display so we don't have a context.
12266         // Make a best guess about the display size.
12267         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12268         d.getRectSize(outRect);
12269     }
12270 
12271     /**
12272      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
12273      * is currently in without any insets.
12274      *
12275      * @hide
12276      */
12277     public void getWindowDisplayFrame(Rect outRect) {
12278         if (mAttachInfo != null) {
12279             try {
12280                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12281             } catch (RemoteException e) {
12282                 return;
12283             }
12284             return;
12285         }
12286         // The view is not attached to a display so we don't have a context.
12287         // Make a best guess about the display size.
12288         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12289         d.getRectSize(outRect);
12290     }
12291 
12292     /**
12293      * Dispatch a notification about a resource configuration change down
12294      * the view hierarchy.
12295      * ViewGroups should override to route to their children.
12296      *
12297      * @param newConfig The new resource configuration.
12298      *
12299      * @see #onConfigurationChanged(android.content.res.Configuration)
12300      */
12301     public void dispatchConfigurationChanged(Configuration newConfig) {
12302         onConfigurationChanged(newConfig);
12303     }
12304 
12305     /**
12306      * Called when the current configuration of the resources being used
12307      * by the application have changed.  You can use this to decide when
12308      * to reload resources that can changed based on orientation and other
12309      * configuration characteristics.  You only need to use this if you are
12310      * not relying on the normal {@link android.app.Activity} mechanism of
12311      * recreating the activity instance upon a configuration change.
12312      *
12313      * @param newConfig The new resource configuration.
12314      */
12315     protected void onConfigurationChanged(Configuration newConfig) {
12316     }
12317 
12318     /**
12319      * Private function to aggregate all per-view attributes in to the view
12320      * root.
12321      */
12322     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12323         performCollectViewAttributes(attachInfo, visibility);
12324     }
12325 
12326     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12327         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
12328             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
12329                 attachInfo.mKeepScreenOn = true;
12330             }
12331             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
12332             ListenerInfo li = mListenerInfo;
12333             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
12334                 attachInfo.mHasSystemUiListeners = true;
12335             }
12336         }
12337     }
12338 
12339     void needGlobalAttributesUpdate(boolean force) {
12340         final AttachInfo ai = mAttachInfo;
12341         if (ai != null && !ai.mRecomputeGlobalAttributes) {
12342             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
12343                     || ai.mHasSystemUiListeners) {
12344                 ai.mRecomputeGlobalAttributes = true;
12345             }
12346         }
12347     }
12348 
12349     /**
12350      * Returns whether the device is currently in touch mode.  Touch mode is entered
12351      * once the user begins interacting with the device by touch, and affects various
12352      * things like whether focus is always visible to the user.
12353      *
12354      * @return Whether the device is in touch mode.
12355      */
12356     @ViewDebug.ExportedProperty
12357     public boolean isInTouchMode() {
12358         if (mAttachInfo != null) {
12359             return mAttachInfo.mInTouchMode;
12360         } else {
12361             return ViewRootImpl.isInTouchMode();
12362         }
12363     }
12364 
12365     /**
12366      * Returns the context the view is running in, through which it can
12367      * access the current theme, resources, etc.
12368      *
12369      * @return The view's Context.
12370      */
12371     @ViewDebug.CapturedViewProperty
12372     public final Context getContext() {
12373         return mContext;
12374     }
12375 
12376     /**
12377      * Handle a key event before it is processed by any input method
12378      * associated with the view hierarchy.  This can be used to intercept
12379      * key events in special situations before the IME consumes them; a
12380      * typical example would be handling the BACK key to update the application's
12381      * UI instead of allowing the IME to see it and close itself.
12382      *
12383      * @param keyCode The value in event.getKeyCode().
12384      * @param event Description of the key event.
12385      * @return If you handled the event, return true. If you want to allow the
12386      *         event to be handled by the next receiver, return false.
12387      */
12388     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
12389         return false;
12390     }
12391 
12392     /**
12393      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
12394      * KeyEvent.Callback.onKeyDown()}: perform press of the view
12395      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
12396      * is released, if the view is enabled and clickable.
12397      * <p>
12398      * Key presses in software keyboards will generally NOT trigger this
12399      * listener, although some may elect to do so in some situations. Do not
12400      * rely on this to catch software key presses.
12401      *
12402      * @param keyCode a key code that represents the button pressed, from
12403      *                {@link android.view.KeyEvent}
12404      * @param event the KeyEvent object that defines the button action
12405      */
12406     public boolean onKeyDown(int keyCode, KeyEvent event) {
12407         if (KeyEvent.isConfirmKey(keyCode)) {
12408             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12409                 return true;
12410             }
12411 
12412             if (event.getRepeatCount() == 0) {
12413                 // Long clickable items don't necessarily have to be clickable.
12414                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
12415                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12416                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
12417                     // For the purposes of menu anchoring and drawable hotspots,
12418                     // key events are considered to be at the center of the view.
12419                     final float x = getWidth() / 2f;
12420                     final float y = getHeight() / 2f;
12421                     if (clickable) {
12422                         setPressed(true, x, y);
12423                     }
12424                     checkForLongClick(0, x, y);
12425                     return true;
12426                 }
12427             }
12428         }
12429 
12430         return false;
12431     }
12432 
12433     /**
12434      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12435      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12436      * the event).
12437      * <p>Key presses in software keyboards will generally NOT trigger this listener,
12438      * although some may elect to do so in some situations. Do not rely on this to
12439      * catch software key presses.
12440      */
12441     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12442         return false;
12443     }
12444 
12445     /**
12446      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12447      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12448      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12449      * or {@link KeyEvent#KEYCODE_SPACE} is released.
12450      * <p>Key presses in software keyboards will generally NOT trigger this listener,
12451      * although some may elect to do so in some situations. Do not rely on this to
12452      * catch software key presses.
12453      *
12454      * @param keyCode A key code that represents the button pressed, from
12455      *                {@link android.view.KeyEvent}.
12456      * @param event   The KeyEvent object that defines the button action.
12457      */
12458     public boolean onKeyUp(int keyCode, KeyEvent event) {
12459         if (KeyEvent.isConfirmKey(keyCode)) {
12460             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12461                 return true;
12462             }
12463             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12464                 setPressed(false);
12465 
12466                 if (!mHasPerformedLongPress) {
12467                     // This is a tap, so remove the longpress check
12468                     removeLongPressCallback();
12469                     if (!event.isCanceled()) {
12470                         return performClick();
12471                     }
12472                 }
12473             }
12474         }
12475         return false;
12476     }
12477 
12478     /**
12479      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12480      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12481      * the event).
12482      * <p>Key presses in software keyboards will generally NOT trigger this listener,
12483      * although some may elect to do so in some situations. Do not rely on this to
12484      * catch software key presses.
12485      *
12486      * @param keyCode     A key code that represents the button pressed, from
12487      *                    {@link android.view.KeyEvent}.
12488      * @param repeatCount The number of times the action was made.
12489      * @param event       The KeyEvent object that defines the button action.
12490      */
12491     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12492         return false;
12493     }
12494 
12495     /**
12496      * Called on the focused view when a key shortcut event is not handled.
12497      * Override this method to implement local key shortcuts for the View.
12498      * Key shortcuts can also be implemented by setting the
12499      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12500      *
12501      * @param keyCode The value in event.getKeyCode().
12502      * @param event Description of the key event.
12503      * @return If you handled the event, return true. If you want to allow the
12504      *         event to be handled by the next receiver, return false.
12505      */
12506     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12507         return false;
12508     }
12509 
12510     /**
12511      * Check whether the called view is a text editor, in which case it
12512      * would make sense to automatically display a soft input window for
12513      * it.  Subclasses should override this if they implement
12514      * {@link #onCreateInputConnection(EditorInfo)} to return true if
12515      * a call on that method would return a non-null InputConnection, and
12516      * they are really a first-class editor that the user would normally
12517      * start typing on when the go into a window containing your view.
12518      *
12519      * <p>The default implementation always returns false.  This does
12520      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12521      * will not be called or the user can not otherwise perform edits on your
12522      * view; it is just a hint to the system that this is not the primary
12523      * purpose of this view.
12524      *
12525      * @return Returns true if this view is a text editor, else false.
12526      */
12527     public boolean onCheckIsTextEditor() {
12528         return false;
12529     }
12530 
12531     /**
12532      * Create a new InputConnection for an InputMethod to interact
12533      * with the view.  The default implementation returns null, since it doesn't
12534      * support input methods.  You can override this to implement such support.
12535      * This is only needed for views that take focus and text input.
12536      *
12537      * <p>When implementing this, you probably also want to implement
12538      * {@link #onCheckIsTextEditor()} to indicate you will return a
12539      * non-null InputConnection.</p>
12540      *
12541      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12542      * object correctly and in its entirety, so that the connected IME can rely
12543      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12544      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12545      * must be filled in with the correct cursor position for IMEs to work correctly
12546      * with your application.</p>
12547      *
12548      * @param outAttrs Fill in with attribute information about the connection.
12549      */
12550     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12551         return null;
12552     }
12553 
12554     /**
12555      * Called by the {@link android.view.inputmethod.InputMethodManager}
12556      * when a view who is not the current
12557      * input connection target is trying to make a call on the manager.  The
12558      * default implementation returns false; you can override this to return
12559      * true for certain views if you are performing InputConnection proxying
12560      * to them.
12561      * @param view The View that is making the InputMethodManager call.
12562      * @return Return true to allow the call, false to reject.
12563      */
12564     public boolean checkInputConnectionProxy(View view) {
12565         return false;
12566     }
12567 
12568     /**
12569      * Show the context menu for this view. It is not safe to hold on to the
12570      * menu after returning from this method.
12571      *
12572      * You should normally not overload this method. Overload
12573      * {@link #onCreateContextMenu(ContextMenu)} or define an
12574      * {@link OnCreateContextMenuListener} to add items to the context menu.
12575      *
12576      * @param menu The context menu to populate
12577      */
12578     public void createContextMenu(ContextMenu menu) {
12579         ContextMenuInfo menuInfo = getContextMenuInfo();
12580 
12581         // Sets the current menu info so all items added to menu will have
12582         // my extra info set.
12583         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12584 
12585         onCreateContextMenu(menu);
12586         ListenerInfo li = mListenerInfo;
12587         if (li != null && li.mOnCreateContextMenuListener != null) {
12588             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12589         }
12590 
12591         // Clear the extra information so subsequent items that aren't mine don't
12592         // have my extra info.
12593         ((MenuBuilder)menu).setCurrentMenuInfo(null);
12594 
12595         if (mParent != null) {
12596             mParent.createContextMenu(menu);
12597         }
12598     }
12599 
12600     /**
12601      * Views should implement this if they have extra information to associate
12602      * with the context menu. The return result is supplied as a parameter to
12603      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12604      * callback.
12605      *
12606      * @return Extra information about the item for which the context menu
12607      *         should be shown. This information will vary across different
12608      *         subclasses of View.
12609      */
12610     protected ContextMenuInfo getContextMenuInfo() {
12611         return null;
12612     }
12613 
12614     /**
12615      * Views should implement this if the view itself is going to add items to
12616      * the context menu.
12617      *
12618      * @param menu the context menu to populate
12619      */
12620     protected void onCreateContextMenu(ContextMenu menu) {
12621     }
12622 
12623     /**
12624      * Implement this method to handle trackball motion events.  The
12625      * <em>relative</em> movement of the trackball since the last event
12626      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12627      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12628      * that a movement of 1 corresponds to the user pressing one DPAD key (so
12629      * they will often be fractional values, representing the more fine-grained
12630      * movement information available from a trackball).
12631      *
12632      * @param event The motion event.
12633      * @return True if the event was handled, false otherwise.
12634      */
12635     public boolean onTrackballEvent(MotionEvent event) {
12636         return false;
12637     }
12638 
12639     /**
12640      * Implement this method to handle generic motion events.
12641      * <p>
12642      * Generic motion events describe joystick movements, mouse hovers, track pad
12643      * touches, scroll wheel movements and other input events.  The
12644      * {@link MotionEvent#getSource() source} of the motion event specifies
12645      * the class of input that was received.  Implementations of this method
12646      * must examine the bits in the source before processing the event.
12647      * The following code example shows how this is done.
12648      * </p><p>
12649      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12650      * are delivered to the view under the pointer.  All other generic motion events are
12651      * delivered to the focused view.
12652      * </p>
12653      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12654      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12655      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12656      *             // process the joystick movement...
12657      *             return true;
12658      *         }
12659      *     }
12660      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12661      *         switch (event.getAction()) {
12662      *             case MotionEvent.ACTION_HOVER_MOVE:
12663      *                 // process the mouse hover movement...
12664      *                 return true;
12665      *             case MotionEvent.ACTION_SCROLL:
12666      *                 // process the scroll wheel movement...
12667      *                 return true;
12668      *         }
12669      *     }
12670      *     return super.onGenericMotionEvent(event);
12671      * }</pre>
12672      *
12673      * @param event The generic motion event being processed.
12674      * @return True if the event was handled, false otherwise.
12675      */
12676     public boolean onGenericMotionEvent(MotionEvent event) {
12677         return false;
12678     }
12679 
12680     /**
12681      * Implement this method to handle hover events.
12682      * <p>
12683      * This method is called whenever a pointer is hovering into, over, or out of the
12684      * bounds of a view and the view is not currently being touched.
12685      * Hover events are represented as pointer events with action
12686      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12687      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12688      * </p>
12689      * <ul>
12690      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12691      * when the pointer enters the bounds of the view.</li>
12692      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12693      * when the pointer has already entered the bounds of the view and has moved.</li>
12694      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12695      * when the pointer has exited the bounds of the view or when the pointer is
12696      * about to go down due to a button click, tap, or similar user action that
12697      * causes the view to be touched.</li>
12698      * </ul>
12699      * <p>
12700      * The view should implement this method to return true to indicate that it is
12701      * handling the hover event, such as by changing its drawable state.
12702      * </p><p>
12703      * The default implementation calls {@link #setHovered} to update the hovered state
12704      * of the view when a hover enter or hover exit event is received, if the view
12705      * is enabled and is clickable.  The default implementation also sends hover
12706      * accessibility events.
12707      * </p>
12708      *
12709      * @param event The motion event that describes the hover.
12710      * @return True if the view handled the hover event.
12711      *
12712      * @see #isHovered
12713      * @see #setHovered
12714      * @see #onHoverChanged
12715      */
12716     public boolean onHoverEvent(MotionEvent event) {
12717         // The root view may receive hover (or touch) events that are outside the bounds of
12718         // the window.  This code ensures that we only send accessibility events for
12719         // hovers that are actually within the bounds of the root view.
12720         final int action = event.getActionMasked();
12721         if (!mSendingHoverAccessibilityEvents) {
12722             if ((action == MotionEvent.ACTION_HOVER_ENTER
12723                     || action == MotionEvent.ACTION_HOVER_MOVE)
12724                     && !hasHoveredChild()
12725                     && pointInView(event.getX(), event.getY())) {
12726                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12727                 mSendingHoverAccessibilityEvents = true;
12728             }
12729         } else {
12730             if (action == MotionEvent.ACTION_HOVER_EXIT
12731                     || (action == MotionEvent.ACTION_MOVE
12732                             && !pointInView(event.getX(), event.getY()))) {
12733                 mSendingHoverAccessibilityEvents = false;
12734                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12735             }
12736         }
12737 
12738         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12739                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
12740                 && isOnScrollbar(event.getX(), event.getY())) {
12741             awakenScrollBars();
12742         }
12743 
12744         // If we consider ourself hoverable, or if we we're already hovered,
12745         // handle changing state in response to ENTER and EXIT events.
12746         if (isHoverable() || isHovered()) {
12747             switch (action) {
12748                 case MotionEvent.ACTION_HOVER_ENTER:
12749                     setHovered(true);
12750                     break;
12751                 case MotionEvent.ACTION_HOVER_EXIT:
12752                     setHovered(false);
12753                     break;
12754             }
12755 
12756             // Dispatch the event to onGenericMotionEvent before returning true.
12757             // This is to provide compatibility with existing applications that
12758             // handled HOVER_MOVE events in onGenericMotionEvent and that would
12759             // break because of the new default handling for hoverable views
12760             // in onHoverEvent.
12761             // Note that onGenericMotionEvent will be called by default when
12762             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12763             dispatchGenericMotionEventInternal(event);
12764             // The event was already handled by calling setHovered(), so always
12765             // return true.
12766             return true;
12767         }
12768 
12769         return false;
12770     }
12771 
12772     /**
12773      * Returns true if the view should handle {@link #onHoverEvent}
12774      * by calling {@link #setHovered} to change its hovered state.
12775      *
12776      * @return True if the view is hoverable.
12777      */
12778     private boolean isHoverable() {
12779         final int viewFlags = mViewFlags;
12780         if ((viewFlags & ENABLED_MASK) == DISABLED) {
12781             return false;
12782         }
12783 
12784         return (viewFlags & CLICKABLE) == CLICKABLE
12785                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12786                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12787     }
12788 
12789     /**
12790      * Returns true if the view is currently hovered.
12791      *
12792      * @return True if the view is currently hovered.
12793      *
12794      * @see #setHovered
12795      * @see #onHoverChanged
12796      */
12797     @ViewDebug.ExportedProperty
12798     public boolean isHovered() {
12799         return (mPrivateFlags & PFLAG_HOVERED) != 0;
12800     }
12801 
12802     /**
12803      * Sets whether the view is currently hovered.
12804      * <p>
12805      * Calling this method also changes the drawable state of the view.  This
12806      * enables the view to react to hover by using different drawable resources
12807      * to change its appearance.
12808      * </p><p>
12809      * The {@link #onHoverChanged} method is called when the hovered state changes.
12810      * </p>
12811      *
12812      * @param hovered True if the view is hovered.
12813      *
12814      * @see #isHovered
12815      * @see #onHoverChanged
12816      */
12817     public void setHovered(boolean hovered) {
12818         if (hovered) {
12819             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12820                 mPrivateFlags |= PFLAG_HOVERED;
12821                 refreshDrawableState();
12822                 onHoverChanged(true);
12823             }
12824         } else {
12825             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12826                 mPrivateFlags &= ~PFLAG_HOVERED;
12827                 refreshDrawableState();
12828                 onHoverChanged(false);
12829             }
12830         }
12831     }
12832 
12833     /**
12834      * Implement this method to handle hover state changes.
12835      * <p>
12836      * This method is called whenever the hover state changes as a result of a
12837      * call to {@link #setHovered}.
12838      * </p>
12839      *
12840      * @param hovered The current hover state, as returned by {@link #isHovered}.
12841      *
12842      * @see #isHovered
12843      * @see #setHovered
12844      */
12845     public void onHoverChanged(boolean hovered) {
12846     }
12847 
12848     /**
12849      * Handles scroll bar dragging by mouse input.
12850      *
12851      * @hide
12852      * @param event The motion event.
12853      *
12854      * @return true if the event was handled as a scroll bar dragging, false otherwise.
12855      */
12856     protected boolean handleScrollBarDragging(MotionEvent event) {
12857         if (mScrollCache == null) {
12858             return false;
12859         }
12860         final float x = event.getX();
12861         final float y = event.getY();
12862         final int action = event.getAction();
12863         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12864                 && action != MotionEvent.ACTION_DOWN)
12865                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12866                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12867             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12868             return false;
12869         }
12870 
12871         switch (action) {
12872             case MotionEvent.ACTION_MOVE:
12873                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12874                     return false;
12875                 }
12876                 if (mScrollCache.mScrollBarDraggingState
12877                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12878                     final Rect bounds = mScrollCache.mScrollBarBounds;
12879                     getVerticalScrollBarBounds(bounds, null);
12880                     final int range = computeVerticalScrollRange();
12881                     final int offset = computeVerticalScrollOffset();
12882                     final int extent = computeVerticalScrollExtent();
12883 
12884                     final int thumbLength = ScrollBarUtils.getThumbLength(
12885                             bounds.height(), bounds.width(), extent, range);
12886                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
12887                             bounds.height(), thumbLength, extent, range, offset);
12888 
12889                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
12890                     final float maxThumbOffset = bounds.height() - thumbLength;
12891                     final float newThumbOffset =
12892                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12893                     final int height = getHeight();
12894                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12895                             && height > 0 && extent > 0) {
12896                         final int newY = Math.round((range - extent)
12897                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12898                         if (newY != getScrollY()) {
12899                             mScrollCache.mScrollBarDraggingPos = y;
12900                             setScrollY(newY);
12901                         }
12902                     }
12903                     return true;
12904                 }
12905                 if (mScrollCache.mScrollBarDraggingState
12906                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12907                     final Rect bounds = mScrollCache.mScrollBarBounds;
12908                     getHorizontalScrollBarBounds(bounds, null);
12909                     final int range = computeHorizontalScrollRange();
12910                     final int offset = computeHorizontalScrollOffset();
12911                     final int extent = computeHorizontalScrollExtent();
12912 
12913                     final int thumbLength = ScrollBarUtils.getThumbLength(
12914                             bounds.width(), bounds.height(), extent, range);
12915                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
12916                             bounds.width(), thumbLength, extent, range, offset);
12917 
12918                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
12919                     final float maxThumbOffset = bounds.width() - thumbLength;
12920                     final float newThumbOffset =
12921                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12922                     final int width = getWidth();
12923                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12924                             && width > 0 && extent > 0) {
12925                         final int newX = Math.round((range - extent)
12926                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12927                         if (newX != getScrollX()) {
12928                             mScrollCache.mScrollBarDraggingPos = x;
12929                             setScrollX(newX);
12930                         }
12931                     }
12932                     return true;
12933                 }
12934             case MotionEvent.ACTION_DOWN:
12935                 if (mScrollCache.state == ScrollabilityCache.OFF) {
12936                     return false;
12937                 }
12938                 if (isOnVerticalScrollbarThumb(x, y)) {
12939                     mScrollCache.mScrollBarDraggingState =
12940                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12941                     mScrollCache.mScrollBarDraggingPos = y;
12942                     return true;
12943                 }
12944                 if (isOnHorizontalScrollbarThumb(x, y)) {
12945                     mScrollCache.mScrollBarDraggingState =
12946                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12947                     mScrollCache.mScrollBarDraggingPos = x;
12948                     return true;
12949                 }
12950         }
12951         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12952         return false;
12953     }
12954 
12955     /**
12956      * Implement this method to handle touch screen motion events.
12957      * <p>
12958      * If this method is used to detect click actions, it is recommended that
12959      * the actions be performed by implementing and calling
12960      * {@link #performClick()}. This will ensure consistent system behavior,
12961      * including:
12962      * <ul>
12963      * <li>obeying click sound preferences
12964      * <li>dispatching OnClickListener calls
12965      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12966      * accessibility features are enabled
12967      * </ul>
12968      *
12969      * @param event The motion event.
12970      * @return True if the event was handled, false otherwise.
12971      */
12972     public boolean onTouchEvent(MotionEvent event) {
12973         final float x = event.getX();
12974         final float y = event.getY();
12975         final int viewFlags = mViewFlags;
12976         final int action = event.getAction();
12977 
12978         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12979                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12980                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12981 
12982         if ((viewFlags & ENABLED_MASK) == DISABLED) {
12983             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12984                 setPressed(false);
12985             }
12986             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12987             // A disabled view that is clickable still consumes the touch
12988             // events, it just doesn't respond to them.
12989             return clickable;
12990         }
12991         if (mTouchDelegate != null) {
12992             if (mTouchDelegate.onTouchEvent(event)) {
12993                 return true;
12994             }
12995         }
12996 
12997         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12998             switch (action) {
12999                 case MotionEvent.ACTION_UP:
13000                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13001                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
13002                         handleTooltipUp();
13003                     }
13004                     if (!clickable) {
13005                         removeTapCallback();
13006                         removeLongPressCallback();
13007                         mInContextButtonPress = false;
13008                         mHasPerformedLongPress = false;
13009                         mIgnoreNextUpEvent = false;
13010                         break;
13011                     }
13012                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
13013                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
13014                         // take focus if we don't have it already and we should in
13015                         // touch mode.
13016                         boolean focusTaken = false;
13017                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
13018                             focusTaken = requestFocus();
13019                         }
13020 
13021                         if (prepressed) {
13022                             // The button is being released before we actually
13023                             // showed it as pressed.  Make it show the pressed
13024                             // state now (before scheduling the click) to ensure
13025                             // the user sees it.
13026                             setPressed(true, x, y);
13027                         }
13028 
13029                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
13030                             // This is a tap, so remove the longpress check
13031                             removeLongPressCallback();
13032 
13033                             // Only perform take click actions if we were in the pressed state
13034                             if (!focusTaken) {
13035                                 // Use a Runnable and post this rather than calling
13036                                 // performClick directly. This lets other visual state
13037                                 // of the view update before click actions start.
13038                                 if (mPerformClick == null) {
13039                                     mPerformClick = new PerformClick();
13040                                 }
13041                                 if (!post(mPerformClick)) {
13042                                     performClick();
13043                                 }
13044                             }
13045                         }
13046 
13047                         if (mUnsetPressedState == null) {
13048                             mUnsetPressedState = new UnsetPressedState();
13049                         }
13050 
13051                         if (prepressed) {
13052                             postDelayed(mUnsetPressedState,
13053                                     ViewConfiguration.getPressedStateDuration());
13054                         } else if (!post(mUnsetPressedState)) {
13055                             // If the post failed, unpress right now
13056                             mUnsetPressedState.run();
13057                         }
13058 
13059                         removeTapCallback();
13060                     }
13061                     mIgnoreNextUpEvent = false;
13062                     break;
13063 
13064                 case MotionEvent.ACTION_DOWN:
13065                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
13066                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
13067                     }
13068                     mHasPerformedLongPress = false;
13069 
13070                     if (!clickable) {
13071                         checkForLongClick(0, x, y);
13072                         break;
13073                     }
13074 
13075                     if (performButtonActionOnTouchDown(event)) {
13076                         break;
13077                     }
13078 
13079                     // Walk up the hierarchy to determine if we're inside a scrolling container.
13080                     boolean isInScrollingContainer = isInScrollingContainer();
13081 
13082                     // For views inside a scrolling container, delay the pressed feedback for
13083                     // a short period in case this is a scroll.
13084                     if (isInScrollingContainer) {
13085                         mPrivateFlags |= PFLAG_PREPRESSED;
13086                         if (mPendingCheckForTap == null) {
13087                             mPendingCheckForTap = new CheckForTap();
13088                         }
13089                         mPendingCheckForTap.x = event.getX();
13090                         mPendingCheckForTap.y = event.getY();
13091                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
13092                     } else {
13093                         // Not inside a scrolling container, so show the feedback right away
13094                         setPressed(true, x, y);
13095                         checkForLongClick(0, x, y);
13096                     }
13097                     break;
13098 
13099                 case MotionEvent.ACTION_CANCEL:
13100                     if (clickable) {
13101                         setPressed(false);
13102                     }
13103                     removeTapCallback();
13104                     removeLongPressCallback();
13105                     mInContextButtonPress = false;
13106                     mHasPerformedLongPress = false;
13107                     mIgnoreNextUpEvent = false;
13108                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13109                     break;
13110 
13111                 case MotionEvent.ACTION_MOVE:
13112                     if (clickable) {
13113                         drawableHotspotChanged(x, y);
13114                     }
13115 
13116                     // Be lenient about moving outside of buttons
13117                     if (!pointInView(x, y, mTouchSlop)) {
13118                         // Outside button
13119                         // Remove any future long press/tap checks
13120                         removeTapCallback();
13121                         removeLongPressCallback();
13122                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
13123                             setPressed(false);
13124                         }
13125                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13126                     }
13127                     break;
13128             }
13129 
13130             return true;
13131         }
13132 
13133         return false;
13134     }
13135 
13136     /**
13137      * @hide
13138      */
13139     public boolean isInScrollingContainer() {
13140         ViewParent p = getParent();
13141         while (p != null && p instanceof ViewGroup) {
13142             if (((ViewGroup) p).shouldDelayChildPressedState()) {
13143                 return true;
13144             }
13145             p = p.getParent();
13146         }
13147         return false;
13148     }
13149 
13150     /**
13151      * Remove the longpress detection timer.
13152      */
13153     private void removeLongPressCallback() {
13154         if (mPendingCheckForLongPress != null) {
13155             removeCallbacks(mPendingCheckForLongPress);
13156         }
13157     }
13158 
13159     /**
13160      * Remove the pending click action
13161      */
13162     private void removePerformClickCallback() {
13163         if (mPerformClick != null) {
13164             removeCallbacks(mPerformClick);
13165         }
13166     }
13167 
13168     /**
13169      * Remove the prepress detection timer.
13170      */
13171     private void removeUnsetPressCallback() {
13172         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
13173             setPressed(false);
13174             removeCallbacks(mUnsetPressedState);
13175         }
13176     }
13177 
13178     /**
13179      * Remove the tap detection timer.
13180      */
13181     private void removeTapCallback() {
13182         if (mPendingCheckForTap != null) {
13183             mPrivateFlags &= ~PFLAG_PREPRESSED;
13184             removeCallbacks(mPendingCheckForTap);
13185         }
13186     }
13187 
13188     /**
13189      * Cancels a pending long press.  Your subclass can use this if you
13190      * want the context menu to come up if the user presses and holds
13191      * at the same place, but you don't want it to come up if they press
13192      * and then move around enough to cause scrolling.
13193      */
13194     public void cancelLongPress() {
13195         removeLongPressCallback();
13196 
13197         /*
13198          * The prepressed state handled by the tap callback is a display
13199          * construct, but the tap callback will post a long press callback
13200          * less its own timeout. Remove it here.
13201          */
13202         removeTapCallback();
13203     }
13204 
13205     /**
13206      * Remove the pending callback for sending a
13207      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
13208      */
13209     private void removeSendViewScrolledAccessibilityEventCallback() {
13210         if (mSendViewScrolledAccessibilityEvent != null) {
13211             removeCallbacks(mSendViewScrolledAccessibilityEvent);
13212             mSendViewScrolledAccessibilityEvent.mIsPending = false;
13213         }
13214     }
13215 
13216     /**
13217      * Sets the TouchDelegate for this View.
13218      */
13219     public void setTouchDelegate(TouchDelegate delegate) {
13220         mTouchDelegate = delegate;
13221     }
13222 
13223     /**
13224      * Gets the TouchDelegate for this View.
13225      */
13226     public TouchDelegate getTouchDelegate() {
13227         return mTouchDelegate;
13228     }
13229 
13230     /**
13231      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
13232      *
13233      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
13234      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
13235      * available. This method should only be called for touch events.
13236      *
13237      * <p class="note">This api is not intended for most applications. Buffered dispatch
13238      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
13239      * streams will not improve your input latency. Side effects include: increased latency,
13240      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
13241      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
13242      * you.</p>
13243      */
13244     public final void requestUnbufferedDispatch(MotionEvent event) {
13245         final int action = event.getAction();
13246         if (mAttachInfo == null
13247                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
13248                 || !event.isTouchEvent()) {
13249             return;
13250         }
13251         mAttachInfo.mUnbufferedDispatchRequested = true;
13252     }
13253 
13254     /**
13255      * Set flags controlling behavior of this view.
13256      *
13257      * @param flags Constant indicating the value which should be set
13258      * @param mask Constant indicating the bit range that should be changed
13259      */
13260     void setFlags(int flags, int mask) {
13261         final boolean accessibilityEnabled =
13262                 AccessibilityManager.getInstance(mContext).isEnabled();
13263         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
13264 
13265         int old = mViewFlags;
13266         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
13267 
13268         int changed = mViewFlags ^ old;
13269         if (changed == 0) {
13270             return;
13271         }
13272         int privateFlags = mPrivateFlags;
13273 
13274         // If focusable is auto, update the FOCUSABLE bit.
13275         int focusableChangedByAuto = 0;
13276         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
13277                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
13278             // Heuristic only takes into account whether view is clickable.
13279             final int newFocus;
13280             if ((mViewFlags & CLICKABLE) != 0) {
13281                 newFocus = FOCUSABLE;
13282             } else {
13283                 newFocus = NOT_FOCUSABLE;
13284             }
13285             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
13286             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
13287             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
13288         }
13289 
13290         /* Check if the FOCUSABLE bit has changed */
13291         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
13292             if (((old & FOCUSABLE) == FOCUSABLE)
13293                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
13294                 /* Give up focus if we are no longer focusable */
13295                 clearFocus();
13296                 if (mParent instanceof ViewGroup) {
13297                     ((ViewGroup) mParent).clearFocusedInCluster();
13298                 }
13299             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
13300                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
13301                 /*
13302                  * Tell the view system that we are now available to take focus
13303                  * if no one else already has it.
13304                  */
13305                 if (mParent != null) {
13306                     ViewRootImpl viewRootImpl = getViewRootImpl();
13307                     if (!sAutoFocusableOffUIThreadWontNotifyParents
13308                             || focusableChangedByAuto == 0
13309                             || viewRootImpl == null
13310                             || viewRootImpl.mThread == Thread.currentThread()) {
13311                         mParent.focusableViewAvailable(this);
13312                     }
13313                 }
13314             }
13315         }
13316 
13317         final int newVisibility = flags & VISIBILITY_MASK;
13318         if (newVisibility == VISIBLE) {
13319             if ((changed & VISIBILITY_MASK) != 0) {
13320                 /*
13321                  * If this view is becoming visible, invalidate it in case it changed while
13322                  * it was not visible. Marking it drawn ensures that the invalidation will
13323                  * go through.
13324                  */
13325                 mPrivateFlags |= PFLAG_DRAWN;
13326                 invalidate(true);
13327 
13328                 needGlobalAttributesUpdate(true);
13329 
13330                 // a view becoming visible is worth notifying the parent
13331                 // about in case nothing has focus.  even if this specific view
13332                 // isn't focusable, it may contain something that is, so let
13333                 // the root view try to give this focus if nothing else does.
13334                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
13335                     mParent.focusableViewAvailable(this);
13336                 }
13337             }
13338         }
13339 
13340         /* Check if the GONE bit has changed */
13341         if ((changed & GONE) != 0) {
13342             needGlobalAttributesUpdate(false);
13343             requestLayout();
13344 
13345             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
13346                 if (hasFocus()) {
13347                     clearFocus();
13348                     if (mParent instanceof ViewGroup) {
13349                         ((ViewGroup) mParent).clearFocusedInCluster();
13350                     }
13351                 }
13352                 clearAccessibilityFocus();
13353                 destroyDrawingCache();
13354                 if (mParent instanceof View) {
13355                     // GONE views noop invalidation, so invalidate the parent
13356                     ((View) mParent).invalidate(true);
13357                 }
13358                 // Mark the view drawn to ensure that it gets invalidated properly the next
13359                 // time it is visible and gets invalidated
13360                 mPrivateFlags |= PFLAG_DRAWN;
13361             }
13362             if (mAttachInfo != null) {
13363                 mAttachInfo.mViewVisibilityChanged = true;
13364             }
13365         }
13366 
13367         /* Check if the VISIBLE bit has changed */
13368         if ((changed & INVISIBLE) != 0) {
13369             needGlobalAttributesUpdate(false);
13370             /*
13371              * If this view is becoming invisible, set the DRAWN flag so that
13372              * the next invalidate() will not be skipped.
13373              */
13374             mPrivateFlags |= PFLAG_DRAWN;
13375 
13376             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
13377                 // root view becoming invisible shouldn't clear focus and accessibility focus
13378                 if (getRootView() != this) {
13379                     if (hasFocus()) {
13380                         clearFocus();
13381                         if (mParent instanceof ViewGroup) {
13382                             ((ViewGroup) mParent).clearFocusedInCluster();
13383                         }
13384                     }
13385                     clearAccessibilityFocus();
13386                 }
13387             }
13388             if (mAttachInfo != null) {
13389                 mAttachInfo.mViewVisibilityChanged = true;
13390             }
13391         }
13392 
13393         if ((changed & VISIBILITY_MASK) != 0) {
13394             // If the view is invisible, cleanup its display list to free up resources
13395             if (newVisibility != VISIBLE && mAttachInfo != null) {
13396                 cleanupDraw();
13397             }
13398 
13399             if (mParent instanceof ViewGroup) {
13400                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
13401                         (changed & VISIBILITY_MASK), newVisibility);
13402                 ((View) mParent).invalidate(true);
13403             } else if (mParent != null) {
13404                 mParent.invalidateChild(this, null);
13405             }
13406 
13407             if (mAttachInfo != null) {
13408                 dispatchVisibilityChanged(this, newVisibility);
13409 
13410                 // Aggregated visibility changes are dispatched to attached views
13411                 // in visible windows where the parent is currently shown/drawn
13412                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
13413                 // discounting clipping or overlapping. This makes it a good place
13414                 // to change animation states.
13415                 if (mParent != null && getWindowVisibility() == VISIBLE &&
13416                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
13417                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
13418                 }
13419                 notifySubtreeAccessibilityStateChangedIfNeeded();
13420             }
13421         }
13422 
13423         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
13424             destroyDrawingCache();
13425         }
13426 
13427         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
13428             destroyDrawingCache();
13429             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13430             invalidateParentCaches();
13431         }
13432 
13433         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
13434             destroyDrawingCache();
13435             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13436         }
13437 
13438         if ((changed & DRAW_MASK) != 0) {
13439             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13440                 if (mBackground != null
13441                         || mDefaultFocusHighlight != null
13442                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13443                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13444                 } else {
13445                     mPrivateFlags |= PFLAG_SKIP_DRAW;
13446                 }
13447             } else {
13448                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13449             }
13450             requestLayout();
13451             invalidate(true);
13452         }
13453 
13454         if ((changed & KEEP_SCREEN_ON) != 0) {
13455             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13456                 mParent.recomputeViewAttributes(this);
13457             }
13458         }
13459 
13460         if (accessibilityEnabled) {
13461             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13462                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13463                     || (changed & CONTEXT_CLICKABLE) != 0) {
13464                 if (oldIncludeForAccessibility != includeForAccessibility()) {
13465                     notifySubtreeAccessibilityStateChangedIfNeeded();
13466                 } else {
13467                     notifyViewAccessibilityStateChangedIfNeeded(
13468                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13469                 }
13470             } else if ((changed & ENABLED_MASK) != 0) {
13471                 notifyViewAccessibilityStateChangedIfNeeded(
13472                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13473             }
13474         }
13475     }
13476 
13477     /**
13478      * Change the view's z order in the tree, so it's on top of other sibling
13479      * views. This ordering change may affect layout, if the parent container
13480      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13481      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13482      * method should be followed by calls to {@link #requestLayout()} and
13483      * {@link View#invalidate()} on the view's parent to force the parent to redraw
13484      * with the new child ordering.
13485      *
13486      * @see ViewGroup#bringChildToFront(View)
13487      */
13488     public void bringToFront() {
13489         if (mParent != null) {
13490             mParent.bringChildToFront(this);
13491         }
13492     }
13493 
13494     /**
13495      * This is called in response to an internal scroll in this view (i.e., the
13496      * view scrolled its own contents). This is typically as a result of
13497      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13498      * called.
13499      *
13500      * @param l Current horizontal scroll origin.
13501      * @param t Current vertical scroll origin.
13502      * @param oldl Previous horizontal scroll origin.
13503      * @param oldt Previous vertical scroll origin.
13504      */
13505     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13506         notifySubtreeAccessibilityStateChangedIfNeeded();
13507 
13508         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13509             postSendViewScrolledAccessibilityEventCallback();
13510         }
13511 
13512         mBackgroundSizeChanged = true;
13513         mDefaultFocusHighlightSizeChanged = true;
13514         if (mForegroundInfo != null) {
13515             mForegroundInfo.mBoundsChanged = true;
13516         }
13517 
13518         final AttachInfo ai = mAttachInfo;
13519         if (ai != null) {
13520             ai.mViewScrollChanged = true;
13521         }
13522 
13523         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13524             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13525         }
13526     }
13527 
13528     /**
13529      * Interface definition for a callback to be invoked when the scroll
13530      * X or Y positions of a view change.
13531      * <p>
13532      * <b>Note:</b> Some views handle scrolling independently from View and may
13533      * have their own separate listeners for scroll-type events. For example,
13534      * {@link android.widget.ListView ListView} allows clients to register an
13535      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13536      * to listen for changes in list scroll position.
13537      *
13538      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13539      */
13540     public interface OnScrollChangeListener {
13541         /**
13542          * Called when the scroll position of a view changes.
13543          *
13544          * @param v The view whose scroll position has changed.
13545          * @param scrollX Current horizontal scroll origin.
13546          * @param scrollY Current vertical scroll origin.
13547          * @param oldScrollX Previous horizontal scroll origin.
13548          * @param oldScrollY Previous vertical scroll origin.
13549          */
13550         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13551     }
13552 
13553     /**
13554      * Interface definition for a callback to be invoked when the layout bounds of a view
13555      * changes due to layout processing.
13556      */
13557     public interface OnLayoutChangeListener {
13558         /**
13559          * Called when the layout bounds of a view changes due to layout processing.
13560          *
13561          * @param v The view whose bounds have changed.
13562          * @param left The new value of the view's left property.
13563          * @param top The new value of the view's top property.
13564          * @param right The new value of the view's right property.
13565          * @param bottom The new value of the view's bottom property.
13566          * @param oldLeft The previous value of the view's left property.
13567          * @param oldTop The previous value of the view's top property.
13568          * @param oldRight The previous value of the view's right property.
13569          * @param oldBottom The previous value of the view's bottom property.
13570          */
13571         void onLayoutChange(View v, int left, int top, int right, int bottom,
13572             int oldLeft, int oldTop, int oldRight, int oldBottom);
13573     }
13574 
13575     /**
13576      * This is called during layout when the size of this view has changed. If
13577      * you were just added to the view hierarchy, you're called with the old
13578      * values of 0.
13579      *
13580      * @param w Current width of this view.
13581      * @param h Current height of this view.
13582      * @param oldw Old width of this view.
13583      * @param oldh Old height of this view.
13584      */
13585     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13586     }
13587 
13588     /**
13589      * Called by draw to draw the child views. This may be overridden
13590      * by derived classes to gain control just before its children are drawn
13591      * (but after its own view has been drawn).
13592      * @param canvas the canvas on which to draw the view
13593      */
13594     protected void dispatchDraw(Canvas canvas) {
13595 
13596     }
13597 
13598     /**
13599      * Gets the parent of this view. Note that the parent is a
13600      * ViewParent and not necessarily a View.
13601      *
13602      * @return Parent of this view.
13603      */
13604     public final ViewParent getParent() {
13605         return mParent;
13606     }
13607 
13608     /**
13609      * Set the horizontal scrolled position of your view. This will cause a call to
13610      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13611      * invalidated.
13612      * @param value the x position to scroll to
13613      */
13614     public void setScrollX(int value) {
13615         scrollTo(value, mScrollY);
13616     }
13617 
13618     /**
13619      * Set the vertical scrolled position of your view. This will cause a call to
13620      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13621      * invalidated.
13622      * @param value the y position to scroll to
13623      */
13624     public void setScrollY(int value) {
13625         scrollTo(mScrollX, value);
13626     }
13627 
13628     /**
13629      * Return the scrolled left position of this view. This is the left edge of
13630      * the displayed part of your view. You do not need to draw any pixels
13631      * farther left, since those are outside of the frame of your view on
13632      * screen.
13633      *
13634      * @return The left edge of the displayed part of your view, in pixels.
13635      */
13636     public final int getScrollX() {
13637         return mScrollX;
13638     }
13639 
13640     /**
13641      * Return the scrolled top position of this view. This is the top edge of
13642      * the displayed part of your view. You do not need to draw any pixels above
13643      * it, since those are outside of the frame of your view on screen.
13644      *
13645      * @return The top edge of the displayed part of your view, in pixels.
13646      */
13647     public final int getScrollY() {
13648         return mScrollY;
13649     }
13650 
13651     /**
13652      * Return the width of the your view.
13653      *
13654      * @return The width of your view, in pixels.
13655      */
13656     @ViewDebug.ExportedProperty(category = "layout")
13657     public final int getWidth() {
13658         return mRight - mLeft;
13659     }
13660 
13661     /**
13662      * Return the height of your view.
13663      *
13664      * @return The height of your view, in pixels.
13665      */
13666     @ViewDebug.ExportedProperty(category = "layout")
13667     public final int getHeight() {
13668         return mBottom - mTop;
13669     }
13670 
13671     /**
13672      * Return the visible drawing bounds of your view. Fills in the output
13673      * rectangle with the values from getScrollX(), getScrollY(),
13674      * getWidth(), and getHeight(). These bounds do not account for any
13675      * transformation properties currently set on the view, such as
13676      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13677      *
13678      * @param outRect The (scrolled) drawing bounds of the view.
13679      */
13680     public void getDrawingRect(Rect outRect) {
13681         outRect.left = mScrollX;
13682         outRect.top = mScrollY;
13683         outRect.right = mScrollX + (mRight - mLeft);
13684         outRect.bottom = mScrollY + (mBottom - mTop);
13685     }
13686 
13687     /**
13688      * Like {@link #getMeasuredWidthAndState()}, but only returns the
13689      * raw width component (that is the result is masked by
13690      * {@link #MEASURED_SIZE_MASK}).
13691      *
13692      * @return The raw measured width of this view.
13693      */
13694     public final int getMeasuredWidth() {
13695         return mMeasuredWidth & MEASURED_SIZE_MASK;
13696     }
13697 
13698     /**
13699      * Return the full width measurement information for this view as computed
13700      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13701      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13702      * This should be used during measurement and layout calculations only. Use
13703      * {@link #getWidth()} to see how wide a view is after layout.
13704      *
13705      * @return The measured width of this view as a bit mask.
13706      */
13707     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13708             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13709                     name = "MEASURED_STATE_TOO_SMALL"),
13710     })
13711     public final int getMeasuredWidthAndState() {
13712         return mMeasuredWidth;
13713     }
13714 
13715     /**
13716      * Like {@link #getMeasuredHeightAndState()}, but only returns the
13717      * raw height component (that is the result is masked by
13718      * {@link #MEASURED_SIZE_MASK}).
13719      *
13720      * @return The raw measured height of this view.
13721      */
13722     public final int getMeasuredHeight() {
13723         return mMeasuredHeight & MEASURED_SIZE_MASK;
13724     }
13725 
13726     /**
13727      * Return the full height measurement information for this view as computed
13728      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13729      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13730      * This should be used during measurement and layout calculations only. Use
13731      * {@link #getHeight()} to see how wide a view is after layout.
13732      *
13733      * @return The measured height of this view as a bit mask.
13734      */
13735     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13736             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13737                     name = "MEASURED_STATE_TOO_SMALL"),
13738     })
13739     public final int getMeasuredHeightAndState() {
13740         return mMeasuredHeight;
13741     }
13742 
13743     /**
13744      * Return only the state bits of {@link #getMeasuredWidthAndState()}
13745      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13746      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13747      * and the height component is at the shifted bits
13748      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13749      */
13750     public final int getMeasuredState() {
13751         return (mMeasuredWidth&MEASURED_STATE_MASK)
13752                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13753                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13754     }
13755 
13756     /**
13757      * The transform matrix of this view, which is calculated based on the current
13758      * rotation, scale, and pivot properties.
13759      *
13760      * @see #getRotation()
13761      * @see #getScaleX()
13762      * @see #getScaleY()
13763      * @see #getPivotX()
13764      * @see #getPivotY()
13765      * @return The current transform matrix for the view
13766      */
13767     public Matrix getMatrix() {
13768         ensureTransformationInfo();
13769         final Matrix matrix = mTransformationInfo.mMatrix;
13770         mRenderNode.getMatrix(matrix);
13771         return matrix;
13772     }
13773 
13774     /**
13775      * Returns true if the transform matrix is the identity matrix.
13776      * Recomputes the matrix if necessary.
13777      *
13778      * @return True if the transform matrix is the identity matrix, false otherwise.
13779      */
13780     final boolean hasIdentityMatrix() {
13781         return mRenderNode.hasIdentityMatrix();
13782     }
13783 
13784     void ensureTransformationInfo() {
13785         if (mTransformationInfo == null) {
13786             mTransformationInfo = new TransformationInfo();
13787         }
13788     }
13789 
13790     /**
13791      * Utility method to retrieve the inverse of the current mMatrix property.
13792      * We cache the matrix to avoid recalculating it when transform properties
13793      * have not changed.
13794      *
13795      * @return The inverse of the current matrix of this view.
13796      * @hide
13797      */
13798     public final Matrix getInverseMatrix() {
13799         ensureTransformationInfo();
13800         if (mTransformationInfo.mInverseMatrix == null) {
13801             mTransformationInfo.mInverseMatrix = new Matrix();
13802         }
13803         final Matrix matrix = mTransformationInfo.mInverseMatrix;
13804         mRenderNode.getInverseMatrix(matrix);
13805         return matrix;
13806     }
13807 
13808     /**
13809      * Gets the distance along the Z axis from the camera to this view.
13810      *
13811      * @see #setCameraDistance(float)
13812      *
13813      * @return The distance along the Z axis.
13814      */
13815     public float getCameraDistance() {
13816         final float dpi = mResources.getDisplayMetrics().densityDpi;
13817         return -(mRenderNode.getCameraDistance() * dpi);
13818     }
13819 
13820     /**
13821      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13822      * views are drawn) from the camera to this view. The camera's distance
13823      * affects 3D transformations, for instance rotations around the X and Y
13824      * axis. If the rotationX or rotationY properties are changed and this view is
13825      * large (more than half the size of the screen), it is recommended to always
13826      * use a camera distance that's greater than the height (X axis rotation) or
13827      * the width (Y axis rotation) of this view.</p>
13828      *
13829      * <p>The distance of the camera from the view plane can have an affect on the
13830      * perspective distortion of the view when it is rotated around the x or y axis.
13831      * For example, a large distance will result in a large viewing angle, and there
13832      * will not be much perspective distortion of the view as it rotates. A short
13833      * distance may cause much more perspective distortion upon rotation, and can
13834      * also result in some drawing artifacts if the rotated view ends up partially
13835      * behind the camera (which is why the recommendation is to use a distance at
13836      * least as far as the size of the view, if the view is to be rotated.)</p>
13837      *
13838      * <p>The distance is expressed in "depth pixels." The default distance depends
13839      * on the screen density. For instance, on a medium density display, the
13840      * default distance is 1280. On a high density display, the default distance
13841      * is 1920.</p>
13842      *
13843      * <p>If you want to specify a distance that leads to visually consistent
13844      * results across various densities, use the following formula:</p>
13845      * <pre>
13846      * float scale = context.getResources().getDisplayMetrics().density;
13847      * view.setCameraDistance(distance * scale);
13848      * </pre>
13849      *
13850      * <p>The density scale factor of a high density display is 1.5,
13851      * and 1920 = 1280 * 1.5.</p>
13852      *
13853      * @param distance The distance in "depth pixels", if negative the opposite
13854      *        value is used
13855      *
13856      * @see #setRotationX(float)
13857      * @see #setRotationY(float)
13858      */
13859     public void setCameraDistance(float distance) {
13860         final float dpi = mResources.getDisplayMetrics().densityDpi;
13861 
13862         invalidateViewProperty(true, false);
13863         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13864         invalidateViewProperty(false, false);
13865 
13866         invalidateParentIfNeededAndWasQuickRejected();
13867     }
13868 
13869     /**
13870      * The degrees that the view is rotated around the pivot point.
13871      *
13872      * @see #setRotation(float)
13873      * @see #getPivotX()
13874      * @see #getPivotY()
13875      *
13876      * @return The degrees of rotation.
13877      */
13878     @ViewDebug.ExportedProperty(category = "drawing")
13879     public float getRotation() {
13880         return mRenderNode.getRotation();
13881     }
13882 
13883     /**
13884      * Sets the degrees that the view is rotated around the pivot point. Increasing values
13885      * result in clockwise rotation.
13886      *
13887      * @param rotation The degrees of rotation.
13888      *
13889      * @see #getRotation()
13890      * @see #getPivotX()
13891      * @see #getPivotY()
13892      * @see #setRotationX(float)
13893      * @see #setRotationY(float)
13894      *
13895      * @attr ref android.R.styleable#View_rotation
13896      */
13897     public void setRotation(float rotation) {
13898         if (rotation != getRotation()) {
13899             // Double-invalidation is necessary to capture view's old and new areas
13900             invalidateViewProperty(true, false);
13901             mRenderNode.setRotation(rotation);
13902             invalidateViewProperty(false, true);
13903 
13904             invalidateParentIfNeededAndWasQuickRejected();
13905             notifySubtreeAccessibilityStateChangedIfNeeded();
13906         }
13907     }
13908 
13909     /**
13910      * The degrees that the view is rotated around the vertical axis through the pivot point.
13911      *
13912      * @see #getPivotX()
13913      * @see #getPivotY()
13914      * @see #setRotationY(float)
13915      *
13916      * @return The degrees of Y rotation.
13917      */
13918     @ViewDebug.ExportedProperty(category = "drawing")
13919     public float getRotationY() {
13920         return mRenderNode.getRotationY();
13921     }
13922 
13923     /**
13924      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13925      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13926      * down the y axis.
13927      *
13928      * When rotating large views, it is recommended to adjust the camera distance
13929      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13930      *
13931      * @param rotationY The degrees of Y rotation.
13932      *
13933      * @see #getRotationY()
13934      * @see #getPivotX()
13935      * @see #getPivotY()
13936      * @see #setRotation(float)
13937      * @see #setRotationX(float)
13938      * @see #setCameraDistance(float)
13939      *
13940      * @attr ref android.R.styleable#View_rotationY
13941      */
13942     public void setRotationY(float rotationY) {
13943         if (rotationY != getRotationY()) {
13944             invalidateViewProperty(true, false);
13945             mRenderNode.setRotationY(rotationY);
13946             invalidateViewProperty(false, true);
13947 
13948             invalidateParentIfNeededAndWasQuickRejected();
13949             notifySubtreeAccessibilityStateChangedIfNeeded();
13950         }
13951     }
13952 
13953     /**
13954      * The degrees that the view is rotated around the horizontal axis through the pivot point.
13955      *
13956      * @see #getPivotX()
13957      * @see #getPivotY()
13958      * @see #setRotationX(float)
13959      *
13960      * @return The degrees of X rotation.
13961      */
13962     @ViewDebug.ExportedProperty(category = "drawing")
13963     public float getRotationX() {
13964         return mRenderNode.getRotationX();
13965     }
13966 
13967     /**
13968      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13969      * Increasing values result in clockwise rotation from the viewpoint of looking down the
13970      * x axis.
13971      *
13972      * When rotating large views, it is recommended to adjust the camera distance
13973      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13974      *
13975      * @param rotationX The degrees of X rotation.
13976      *
13977      * @see #getRotationX()
13978      * @see #getPivotX()
13979      * @see #getPivotY()
13980      * @see #setRotation(float)
13981      * @see #setRotationY(float)
13982      * @see #setCameraDistance(float)
13983      *
13984      * @attr ref android.R.styleable#View_rotationX
13985      */
13986     public void setRotationX(float rotationX) {
13987         if (rotationX != getRotationX()) {
13988             invalidateViewProperty(true, false);
13989             mRenderNode.setRotationX(rotationX);
13990             invalidateViewProperty(false, true);
13991 
13992             invalidateParentIfNeededAndWasQuickRejected();
13993             notifySubtreeAccessibilityStateChangedIfNeeded();
13994         }
13995     }
13996 
13997     /**
13998      * The amount that the view is scaled in x around the pivot point, as a proportion of
13999      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
14000      *
14001      * <p>By default, this is 1.0f.
14002      *
14003      * @see #getPivotX()
14004      * @see #getPivotY()
14005      * @return The scaling factor.
14006      */
14007     @ViewDebug.ExportedProperty(category = "drawing")
14008     public float getScaleX() {
14009         return mRenderNode.getScaleX();
14010     }
14011 
14012     /**
14013      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
14014      * the view's unscaled width. A value of 1 means that no scaling is applied.
14015      *
14016      * @param scaleX The scaling factor.
14017      * @see #getPivotX()
14018      * @see #getPivotY()
14019      *
14020      * @attr ref android.R.styleable#View_scaleX
14021      */
14022     public void setScaleX(float scaleX) {
14023         if (scaleX != getScaleX()) {
14024             invalidateViewProperty(true, false);
14025             mRenderNode.setScaleX(scaleX);
14026             invalidateViewProperty(false, true);
14027 
14028             invalidateParentIfNeededAndWasQuickRejected();
14029             notifySubtreeAccessibilityStateChangedIfNeeded();
14030         }
14031     }
14032 
14033     /**
14034      * The amount that the view is scaled in y around the pivot point, as a proportion of
14035      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
14036      *
14037      * <p>By default, this is 1.0f.
14038      *
14039      * @see #getPivotX()
14040      * @see #getPivotY()
14041      * @return The scaling factor.
14042      */
14043     @ViewDebug.ExportedProperty(category = "drawing")
14044     public float getScaleY() {
14045         return mRenderNode.getScaleY();
14046     }
14047 
14048     /**
14049      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
14050      * the view's unscaled width. A value of 1 means that no scaling is applied.
14051      *
14052      * @param scaleY The scaling factor.
14053      * @see #getPivotX()
14054      * @see #getPivotY()
14055      *
14056      * @attr ref android.R.styleable#View_scaleY
14057      */
14058     public void setScaleY(float scaleY) {
14059         if (scaleY != getScaleY()) {
14060             invalidateViewProperty(true, false);
14061             mRenderNode.setScaleY(scaleY);
14062             invalidateViewProperty(false, true);
14063 
14064             invalidateParentIfNeededAndWasQuickRejected();
14065             notifySubtreeAccessibilityStateChangedIfNeeded();
14066         }
14067     }
14068 
14069     /**
14070      * The x location of the point around which the view is {@link #setRotation(float) rotated}
14071      * and {@link #setScaleX(float) scaled}.
14072      *
14073      * @see #getRotation()
14074      * @see #getScaleX()
14075      * @see #getScaleY()
14076      * @see #getPivotY()
14077      * @return The x location of the pivot point.
14078      *
14079      * @attr ref android.R.styleable#View_transformPivotX
14080      */
14081     @ViewDebug.ExportedProperty(category = "drawing")
14082     public float getPivotX() {
14083         return mRenderNode.getPivotX();
14084     }
14085 
14086     /**
14087      * Sets the x location of the point around which the view is
14088      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
14089      * By default, the pivot point is centered on the object.
14090      * Setting this property disables this behavior and causes the view to use only the
14091      * explicitly set pivotX and pivotY values.
14092      *
14093      * @param pivotX The x location of the pivot point.
14094      * @see #getRotation()
14095      * @see #getScaleX()
14096      * @see #getScaleY()
14097      * @see #getPivotY()
14098      *
14099      * @attr ref android.R.styleable#View_transformPivotX
14100      */
14101     public void setPivotX(float pivotX) {
14102         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
14103             invalidateViewProperty(true, false);
14104             mRenderNode.setPivotX(pivotX);
14105             invalidateViewProperty(false, true);
14106 
14107             invalidateParentIfNeededAndWasQuickRejected();
14108         }
14109     }
14110 
14111     /**
14112      * The y location of the point around which the view is {@link #setRotation(float) rotated}
14113      * and {@link #setScaleY(float) scaled}.
14114      *
14115      * @see #getRotation()
14116      * @see #getScaleX()
14117      * @see #getScaleY()
14118      * @see #getPivotY()
14119      * @return The y location of the pivot point.
14120      *
14121      * @attr ref android.R.styleable#View_transformPivotY
14122      */
14123     @ViewDebug.ExportedProperty(category = "drawing")
14124     public float getPivotY() {
14125         return mRenderNode.getPivotY();
14126     }
14127 
14128     /**
14129      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
14130      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
14131      * Setting this property disables this behavior and causes the view to use only the
14132      * explicitly set pivotX and pivotY values.
14133      *
14134      * @param pivotY The y location of the pivot point.
14135      * @see #getRotation()
14136      * @see #getScaleX()
14137      * @see #getScaleY()
14138      * @see #getPivotY()
14139      *
14140      * @attr ref android.R.styleable#View_transformPivotY
14141      */
14142     public void setPivotY(float pivotY) {
14143         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
14144             invalidateViewProperty(true, false);
14145             mRenderNode.setPivotY(pivotY);
14146             invalidateViewProperty(false, true);
14147 
14148             invalidateParentIfNeededAndWasQuickRejected();
14149         }
14150     }
14151 
14152     /**
14153      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
14154      * completely transparent and 1 means the view is completely opaque.
14155      *
14156      * <p>By default this is 1.0f.
14157      * @return The opacity of the view.
14158      */
14159     @ViewDebug.ExportedProperty(category = "drawing")
14160     public float getAlpha() {
14161         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
14162     }
14163 
14164     /**
14165      * Sets the behavior for overlapping rendering for this view (see {@link
14166      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
14167      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
14168      * providing the value which is then used internally. That is, when {@link
14169      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
14170      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
14171      * instead.
14172      *
14173      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
14174      * instead of that returned by {@link #hasOverlappingRendering()}.
14175      *
14176      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
14177      */
14178     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
14179         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
14180         if (hasOverlappingRendering) {
14181             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14182         } else {
14183             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14184         }
14185     }
14186 
14187     /**
14188      * Returns the value for overlapping rendering that is used internally. This is either
14189      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
14190      * the return value of {@link #hasOverlappingRendering()}, otherwise.
14191      *
14192      * @return The value for overlapping rendering being used internally.
14193      */
14194     public final boolean getHasOverlappingRendering() {
14195         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
14196                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
14197                 hasOverlappingRendering();
14198     }
14199 
14200     /**
14201      * Returns whether this View has content which overlaps.
14202      *
14203      * <p>This function, intended to be overridden by specific View types, is an optimization when
14204      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
14205      * an offscreen buffer and then composited into place, which can be expensive. If the view has
14206      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
14207      * directly. An example of overlapping rendering is a TextView with a background image, such as
14208      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
14209      * ImageView with only the foreground image. The default implementation returns true; subclasses
14210      * should override if they have cases which can be optimized.</p>
14211      *
14212      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
14213      * necessitates that a View return true if it uses the methods internally without passing the
14214      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
14215      *
14216      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
14217      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
14218      *
14219      * @return true if the content in this view might overlap, false otherwise.
14220      */
14221     @ViewDebug.ExportedProperty(category = "drawing")
14222     public boolean hasOverlappingRendering() {
14223         return true;
14224     }
14225 
14226     /**
14227      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
14228      * completely transparent and 1 means the view is completely opaque.
14229      *
14230      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
14231      * can have significant performance implications, especially for large views. It is best to use
14232      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
14233      *
14234      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
14235      * strongly recommended for performance reasons to either override
14236      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
14237      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
14238      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
14239      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
14240      * of rendering cost, even for simple or small views. Starting with
14241      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
14242      * applied to the view at the rendering level.</p>
14243      *
14244      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
14245      * responsible for applying the opacity itself.</p>
14246      *
14247      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
14248      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
14249      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
14250      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
14251      *
14252      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
14253      * value will clip a View to its bounds, unless the View returns <code>false</code> from
14254      * {@link #hasOverlappingRendering}.</p>
14255      *
14256      * @param alpha The opacity of the view.
14257      *
14258      * @see #hasOverlappingRendering()
14259      * @see #setLayerType(int, android.graphics.Paint)
14260      *
14261      * @attr ref android.R.styleable#View_alpha
14262      */
14263     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
14264         ensureTransformationInfo();
14265         if (mTransformationInfo.mAlpha != alpha) {
14266             // Report visibility changes, which can affect children, to accessibility
14267             if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
14268                 notifySubtreeAccessibilityStateChangedIfNeeded();
14269             }
14270             mTransformationInfo.mAlpha = alpha;
14271             if (onSetAlpha((int) (alpha * 255))) {
14272                 mPrivateFlags |= PFLAG_ALPHA_SET;
14273                 // subclass is handling alpha - don't optimize rendering cache invalidation
14274                 invalidateParentCaches();
14275                 invalidate(true);
14276             } else {
14277                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
14278                 invalidateViewProperty(true, false);
14279                 mRenderNode.setAlpha(getFinalAlpha());
14280             }
14281         }
14282     }
14283 
14284     /**
14285      * Faster version of setAlpha() which performs the same steps except there are
14286      * no calls to invalidate(). The caller of this function should perform proper invalidation
14287      * on the parent and this object. The return value indicates whether the subclass handles
14288      * alpha (the return value for onSetAlpha()).
14289      *
14290      * @param alpha The new value for the alpha property
14291      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
14292      *         the new value for the alpha property is different from the old value
14293      */
14294     boolean setAlphaNoInvalidation(float alpha) {
14295         ensureTransformationInfo();
14296         if (mTransformationInfo.mAlpha != alpha) {
14297             mTransformationInfo.mAlpha = alpha;
14298             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
14299             if (subclassHandlesAlpha) {
14300                 mPrivateFlags |= PFLAG_ALPHA_SET;
14301                 return true;
14302             } else {
14303                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
14304                 mRenderNode.setAlpha(getFinalAlpha());
14305             }
14306         }
14307         return false;
14308     }
14309 
14310     /**
14311      * This property is hidden and intended only for use by the Fade transition, which
14312      * animates it to produce a visual translucency that does not side-effect (or get
14313      * affected by) the real alpha property. This value is composited with the other
14314      * alpha value (and the AlphaAnimation value, when that is present) to produce
14315      * a final visual translucency result, which is what is passed into the DisplayList.
14316      *
14317      * @hide
14318      */
14319     public void setTransitionAlpha(float alpha) {
14320         ensureTransformationInfo();
14321         if (mTransformationInfo.mTransitionAlpha != alpha) {
14322             mTransformationInfo.mTransitionAlpha = alpha;
14323             mPrivateFlags &= ~PFLAG_ALPHA_SET;
14324             invalidateViewProperty(true, false);
14325             mRenderNode.setAlpha(getFinalAlpha());
14326         }
14327     }
14328 
14329     /**
14330      * Calculates the visual alpha of this view, which is a combination of the actual
14331      * alpha value and the transitionAlpha value (if set).
14332      */
14333     private float getFinalAlpha() {
14334         if (mTransformationInfo != null) {
14335             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
14336         }
14337         return 1;
14338     }
14339 
14340     /**
14341      * This property is hidden and intended only for use by the Fade transition, which
14342      * animates it to produce a visual translucency that does not side-effect (or get
14343      * affected by) the real alpha property. This value is composited with the other
14344      * alpha value (and the AlphaAnimation value, when that is present) to produce
14345      * a final visual translucency result, which is what is passed into the DisplayList.
14346      *
14347      * @hide
14348      */
14349     @ViewDebug.ExportedProperty(category = "drawing")
14350     public float getTransitionAlpha() {
14351         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
14352     }
14353 
14354     /**
14355      * Top position of this view relative to its parent.
14356      *
14357      * @return The top of this view, in pixels.
14358      */
14359     @ViewDebug.CapturedViewProperty
14360     public final int getTop() {
14361         return mTop;
14362     }
14363 
14364     /**
14365      * Sets the top position of this view relative to its parent. This method is meant to be called
14366      * by the layout system and should not generally be called otherwise, because the property
14367      * may be changed at any time by the layout.
14368      *
14369      * @param top The top of this view, in pixels.
14370      */
14371     public final void setTop(int top) {
14372         if (top != mTop) {
14373             final boolean matrixIsIdentity = hasIdentityMatrix();
14374             if (matrixIsIdentity) {
14375                 if (mAttachInfo != null) {
14376                     int minTop;
14377                     int yLoc;
14378                     if (top < mTop) {
14379                         minTop = top;
14380                         yLoc = top - mTop;
14381                     } else {
14382                         minTop = mTop;
14383                         yLoc = 0;
14384                     }
14385                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
14386                 }
14387             } else {
14388                 // Double-invalidation is necessary to capture view's old and new areas
14389                 invalidate(true);
14390             }
14391 
14392             int width = mRight - mLeft;
14393             int oldHeight = mBottom - mTop;
14394 
14395             mTop = top;
14396             mRenderNode.setTop(mTop);
14397 
14398             sizeChange(width, mBottom - mTop, width, oldHeight);
14399 
14400             if (!matrixIsIdentity) {
14401                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14402                 invalidate(true);
14403             }
14404             mBackgroundSizeChanged = true;
14405             mDefaultFocusHighlightSizeChanged = true;
14406             if (mForegroundInfo != null) {
14407                 mForegroundInfo.mBoundsChanged = true;
14408             }
14409             invalidateParentIfNeeded();
14410             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14411                 // View was rejected last time it was drawn by its parent; this may have changed
14412                 invalidateParentIfNeeded();
14413             }
14414         }
14415     }
14416 
14417     /**
14418      * Bottom position of this view relative to its parent.
14419      *
14420      * @return The bottom of this view, in pixels.
14421      */
14422     @ViewDebug.CapturedViewProperty
14423     public final int getBottom() {
14424         return mBottom;
14425     }
14426 
14427     /**
14428      * True if this view has changed since the last time being drawn.
14429      *
14430      * @return The dirty state of this view.
14431      */
14432     public boolean isDirty() {
14433         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
14434     }
14435 
14436     /**
14437      * Sets the bottom position of this view relative to its parent. This method is meant to be
14438      * called by the layout system and should not generally be called otherwise, because the
14439      * property may be changed at any time by the layout.
14440      *
14441      * @param bottom The bottom of this view, in pixels.
14442      */
14443     public final void setBottom(int bottom) {
14444         if (bottom != mBottom) {
14445             final boolean matrixIsIdentity = hasIdentityMatrix();
14446             if (matrixIsIdentity) {
14447                 if (mAttachInfo != null) {
14448                     int maxBottom;
14449                     if (bottom < mBottom) {
14450                         maxBottom = mBottom;
14451                     } else {
14452                         maxBottom = bottom;
14453                     }
14454                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14455                 }
14456             } else {
14457                 // Double-invalidation is necessary to capture view's old and new areas
14458                 invalidate(true);
14459             }
14460 
14461             int width = mRight - mLeft;
14462             int oldHeight = mBottom - mTop;
14463 
14464             mBottom = bottom;
14465             mRenderNode.setBottom(mBottom);
14466 
14467             sizeChange(width, mBottom - mTop, width, oldHeight);
14468 
14469             if (!matrixIsIdentity) {
14470                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14471                 invalidate(true);
14472             }
14473             mBackgroundSizeChanged = true;
14474             mDefaultFocusHighlightSizeChanged = true;
14475             if (mForegroundInfo != null) {
14476                 mForegroundInfo.mBoundsChanged = true;
14477             }
14478             invalidateParentIfNeeded();
14479             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14480                 // View was rejected last time it was drawn by its parent; this may have changed
14481                 invalidateParentIfNeeded();
14482             }
14483         }
14484     }
14485 
14486     /**
14487      * Left position of this view relative to its parent.
14488      *
14489      * @return The left edge of this view, in pixels.
14490      */
14491     @ViewDebug.CapturedViewProperty
14492     public final int getLeft() {
14493         return mLeft;
14494     }
14495 
14496     /**
14497      * Sets the left position of this view relative to its parent. This method is meant to be called
14498      * by the layout system and should not generally be called otherwise, because the property
14499      * may be changed at any time by the layout.
14500      *
14501      * @param left The left of this view, in pixels.
14502      */
14503     public final void setLeft(int left) {
14504         if (left != mLeft) {
14505             final boolean matrixIsIdentity = hasIdentityMatrix();
14506             if (matrixIsIdentity) {
14507                 if (mAttachInfo != null) {
14508                     int minLeft;
14509                     int xLoc;
14510                     if (left < mLeft) {
14511                         minLeft = left;
14512                         xLoc = left - mLeft;
14513                     } else {
14514                         minLeft = mLeft;
14515                         xLoc = 0;
14516                     }
14517                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14518                 }
14519             } else {
14520                 // Double-invalidation is necessary to capture view's old and new areas
14521                 invalidate(true);
14522             }
14523 
14524             int oldWidth = mRight - mLeft;
14525             int height = mBottom - mTop;
14526 
14527             mLeft = left;
14528             mRenderNode.setLeft(left);
14529 
14530             sizeChange(mRight - mLeft, height, oldWidth, height);
14531 
14532             if (!matrixIsIdentity) {
14533                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14534                 invalidate(true);
14535             }
14536             mBackgroundSizeChanged = true;
14537             mDefaultFocusHighlightSizeChanged = true;
14538             if (mForegroundInfo != null) {
14539                 mForegroundInfo.mBoundsChanged = true;
14540             }
14541             invalidateParentIfNeeded();
14542             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14543                 // View was rejected last time it was drawn by its parent; this may have changed
14544                 invalidateParentIfNeeded();
14545             }
14546         }
14547     }
14548 
14549     /**
14550      * Right position of this view relative to its parent.
14551      *
14552      * @return The right edge of this view, in pixels.
14553      */
14554     @ViewDebug.CapturedViewProperty
14555     public final int getRight() {
14556         return mRight;
14557     }
14558 
14559     /**
14560      * Sets the right position of this view relative to its parent. This method is meant to be called
14561      * by the layout system and should not generally be called otherwise, because the property
14562      * may be changed at any time by the layout.
14563      *
14564      * @param right The right of this view, in pixels.
14565      */
14566     public final void setRight(int right) {
14567         if (right != mRight) {
14568             final boolean matrixIsIdentity = hasIdentityMatrix();
14569             if (matrixIsIdentity) {
14570                 if (mAttachInfo != null) {
14571                     int maxRight;
14572                     if (right < mRight) {
14573                         maxRight = mRight;
14574                     } else {
14575                         maxRight = right;
14576                     }
14577                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14578                 }
14579             } else {
14580                 // Double-invalidation is necessary to capture view's old and new areas
14581                 invalidate(true);
14582             }
14583 
14584             int oldWidth = mRight - mLeft;
14585             int height = mBottom - mTop;
14586 
14587             mRight = right;
14588             mRenderNode.setRight(mRight);
14589 
14590             sizeChange(mRight - mLeft, height, oldWidth, height);
14591 
14592             if (!matrixIsIdentity) {
14593                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14594                 invalidate(true);
14595             }
14596             mBackgroundSizeChanged = true;
14597             mDefaultFocusHighlightSizeChanged = true;
14598             if (mForegroundInfo != null) {
14599                 mForegroundInfo.mBoundsChanged = true;
14600             }
14601             invalidateParentIfNeeded();
14602             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14603                 // View was rejected last time it was drawn by its parent; this may have changed
14604                 invalidateParentIfNeeded();
14605             }
14606         }
14607     }
14608 
14609     /**
14610      * The visual x position of this view, in pixels. This is equivalent to the
14611      * {@link #setTranslationX(float) translationX} property plus the current
14612      * {@link #getLeft() left} property.
14613      *
14614      * @return The visual x position of this view, in pixels.
14615      */
14616     @ViewDebug.ExportedProperty(category = "drawing")
14617     public float getX() {
14618         return mLeft + getTranslationX();
14619     }
14620 
14621     /**
14622      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14623      * {@link #setTranslationX(float) translationX} property to be the difference between
14624      * the x value passed in and the current {@link #getLeft() left} property.
14625      *
14626      * @param x The visual x position of this view, in pixels.
14627      */
14628     public void setX(float x) {
14629         setTranslationX(x - mLeft);
14630     }
14631 
14632     /**
14633      * The visual y position of this view, in pixels. This is equivalent to the
14634      * {@link #setTranslationY(float) translationY} property plus the current
14635      * {@link #getTop() top} property.
14636      *
14637      * @return The visual y position of this view, in pixels.
14638      */
14639     @ViewDebug.ExportedProperty(category = "drawing")
14640     public float getY() {
14641         return mTop + getTranslationY();
14642     }
14643 
14644     /**
14645      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14646      * {@link #setTranslationY(float) translationY} property to be the difference between
14647      * the y value passed in and the current {@link #getTop() top} property.
14648      *
14649      * @param y The visual y position of this view, in pixels.
14650      */
14651     public void setY(float y) {
14652         setTranslationY(y - mTop);
14653     }
14654 
14655     /**
14656      * The visual z position of this view, in pixels. This is equivalent to the
14657      * {@link #setTranslationZ(float) translationZ} property plus the current
14658      * {@link #getElevation() elevation} property.
14659      *
14660      * @return The visual z position of this view, in pixels.
14661      */
14662     @ViewDebug.ExportedProperty(category = "drawing")
14663     public float getZ() {
14664         return getElevation() + getTranslationZ();
14665     }
14666 
14667     /**
14668      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14669      * {@link #setTranslationZ(float) translationZ} property to be the difference between
14670      * the x value passed in and the current {@link #getElevation() elevation} property.
14671      *
14672      * @param z The visual z position of this view, in pixels.
14673      */
14674     public void setZ(float z) {
14675         setTranslationZ(z - getElevation());
14676     }
14677 
14678     /**
14679      * The base elevation of this view relative to its parent, in pixels.
14680      *
14681      * @return The base depth position of the view, in pixels.
14682      */
14683     @ViewDebug.ExportedProperty(category = "drawing")
14684     public float getElevation() {
14685         return mRenderNode.getElevation();
14686     }
14687 
14688     /**
14689      * Sets the base elevation of this view, in pixels.
14690      *
14691      * @attr ref android.R.styleable#View_elevation
14692      */
14693     public void setElevation(float elevation) {
14694         if (elevation != getElevation()) {
14695             invalidateViewProperty(true, false);
14696             mRenderNode.setElevation(elevation);
14697             invalidateViewProperty(false, true);
14698 
14699             invalidateParentIfNeededAndWasQuickRejected();
14700         }
14701     }
14702 
14703     /**
14704      * The horizontal location of this view relative to its {@link #getLeft() left} position.
14705      * This position is post-layout, in addition to wherever the object's
14706      * layout placed it.
14707      *
14708      * @return The horizontal position of this view relative to its left position, in pixels.
14709      */
14710     @ViewDebug.ExportedProperty(category = "drawing")
14711     public float getTranslationX() {
14712         return mRenderNode.getTranslationX();
14713     }
14714 
14715     /**
14716      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14717      * This effectively positions the object post-layout, in addition to wherever the object's
14718      * layout placed it.
14719      *
14720      * @param translationX The horizontal position of this view relative to its left position,
14721      * in pixels.
14722      *
14723      * @attr ref android.R.styleable#View_translationX
14724      */
14725     public void setTranslationX(float translationX) {
14726         if (translationX != getTranslationX()) {
14727             invalidateViewProperty(true, false);
14728             mRenderNode.setTranslationX(translationX);
14729             invalidateViewProperty(false, true);
14730 
14731             invalidateParentIfNeededAndWasQuickRejected();
14732             notifySubtreeAccessibilityStateChangedIfNeeded();
14733         }
14734     }
14735 
14736     /**
14737      * The vertical location of this view relative to its {@link #getTop() top} position.
14738      * This position is post-layout, in addition to wherever the object's
14739      * layout placed it.
14740      *
14741      * @return The vertical position of this view relative to its top position,
14742      * in pixels.
14743      */
14744     @ViewDebug.ExportedProperty(category = "drawing")
14745     public float getTranslationY() {
14746         return mRenderNode.getTranslationY();
14747     }
14748 
14749     /**
14750      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14751      * This effectively positions the object post-layout, in addition to wherever the object's
14752      * layout placed it.
14753      *
14754      * @param translationY The vertical position of this view relative to its top position,
14755      * in pixels.
14756      *
14757      * @attr ref android.R.styleable#View_translationY
14758      */
14759     public void setTranslationY(float translationY) {
14760         if (translationY != getTranslationY()) {
14761             invalidateViewProperty(true, false);
14762             mRenderNode.setTranslationY(translationY);
14763             invalidateViewProperty(false, true);
14764 
14765             invalidateParentIfNeededAndWasQuickRejected();
14766             notifySubtreeAccessibilityStateChangedIfNeeded();
14767         }
14768     }
14769 
14770     /**
14771      * The depth location of this view relative to its {@link #getElevation() elevation}.
14772      *
14773      * @return The depth of this view relative to its elevation.
14774      */
14775     @ViewDebug.ExportedProperty(category = "drawing")
14776     public float getTranslationZ() {
14777         return mRenderNode.getTranslationZ();
14778     }
14779 
14780     /**
14781      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14782      *
14783      * @attr ref android.R.styleable#View_translationZ
14784      */
14785     public void setTranslationZ(float translationZ) {
14786         if (translationZ != getTranslationZ()) {
14787             invalidateViewProperty(true, false);
14788             mRenderNode.setTranslationZ(translationZ);
14789             invalidateViewProperty(false, true);
14790 
14791             invalidateParentIfNeededAndWasQuickRejected();
14792         }
14793     }
14794 
14795     /** @hide */
14796     public void setAnimationMatrix(Matrix matrix) {
14797         invalidateViewProperty(true, false);
14798         mRenderNode.setAnimationMatrix(matrix);
14799         invalidateViewProperty(false, true);
14800 
14801         invalidateParentIfNeededAndWasQuickRejected();
14802     }
14803 
14804     /**
14805      * Returns the current StateListAnimator if exists.
14806      *
14807      * @return StateListAnimator or null if it does not exists
14808      * @see    #setStateListAnimator(android.animation.StateListAnimator)
14809      */
14810     public StateListAnimator getStateListAnimator() {
14811         return mStateListAnimator;
14812     }
14813 
14814     /**
14815      * Attaches the provided StateListAnimator to this View.
14816      * <p>
14817      * Any previously attached StateListAnimator will be detached.
14818      *
14819      * @param stateListAnimator The StateListAnimator to update the view
14820      * @see android.animation.StateListAnimator
14821      */
14822     public void setStateListAnimator(StateListAnimator stateListAnimator) {
14823         if (mStateListAnimator == stateListAnimator) {
14824             return;
14825         }
14826         if (mStateListAnimator != null) {
14827             mStateListAnimator.setTarget(null);
14828         }
14829         mStateListAnimator = stateListAnimator;
14830         if (stateListAnimator != null) {
14831             stateListAnimator.setTarget(this);
14832             if (isAttachedToWindow()) {
14833                 stateListAnimator.setState(getDrawableState());
14834             }
14835         }
14836     }
14837 
14838     /**
14839      * Returns whether the Outline should be used to clip the contents of the View.
14840      * <p>
14841      * Note that this flag will only be respected if the View's Outline returns true from
14842      * {@link Outline#canClip()}.
14843      *
14844      * @see #setOutlineProvider(ViewOutlineProvider)
14845      * @see #setClipToOutline(boolean)
14846      */
14847     public final boolean getClipToOutline() {
14848         return mRenderNode.getClipToOutline();
14849     }
14850 
14851     /**
14852      * Sets whether the View's Outline should be used to clip the contents of the View.
14853      * <p>
14854      * Only a single non-rectangular clip can be applied on a View at any time.
14855      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14856      * circular reveal} animation take priority over Outline clipping, and
14857      * child Outline clipping takes priority over Outline clipping done by a
14858      * parent.
14859      * <p>
14860      * Note that this flag will only be respected if the View's Outline returns true from
14861      * {@link Outline#canClip()}.
14862      *
14863      * @see #setOutlineProvider(ViewOutlineProvider)
14864      * @see #getClipToOutline()
14865      */
14866     public void setClipToOutline(boolean clipToOutline) {
14867         damageInParent();
14868         if (getClipToOutline() != clipToOutline) {
14869             mRenderNode.setClipToOutline(clipToOutline);
14870         }
14871     }
14872 
14873     // correspond to the enum values of View_outlineProvider
14874     private static final int PROVIDER_BACKGROUND = 0;
14875     private static final int PROVIDER_NONE = 1;
14876     private static final int PROVIDER_BOUNDS = 2;
14877     private static final int PROVIDER_PADDED_BOUNDS = 3;
14878     private void setOutlineProviderFromAttribute(int providerInt) {
14879         switch (providerInt) {
14880             case PROVIDER_BACKGROUND:
14881                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14882                 break;
14883             case PROVIDER_NONE:
14884                 setOutlineProvider(null);
14885                 break;
14886             case PROVIDER_BOUNDS:
14887                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
14888                 break;
14889             case PROVIDER_PADDED_BOUNDS:
14890                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14891                 break;
14892         }
14893     }
14894 
14895     /**
14896      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14897      * the shape of the shadow it casts, and enables outline clipping.
14898      * <p>
14899      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14900      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14901      * outline provider with this method allows this behavior to be overridden.
14902      * <p>
14903      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14904      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14905      * <p>
14906      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14907      *
14908      * @see #setClipToOutline(boolean)
14909      * @see #getClipToOutline()
14910      * @see #getOutlineProvider()
14911      */
14912     public void setOutlineProvider(ViewOutlineProvider provider) {
14913         mOutlineProvider = provider;
14914         invalidateOutline();
14915     }
14916 
14917     /**
14918      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14919      * that defines the shape of the shadow it casts, and enables outline clipping.
14920      *
14921      * @see #setOutlineProvider(ViewOutlineProvider)
14922      */
14923     public ViewOutlineProvider getOutlineProvider() {
14924         return mOutlineProvider;
14925     }
14926 
14927     /**
14928      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14929      *
14930      * @see #setOutlineProvider(ViewOutlineProvider)
14931      */
14932     public void invalidateOutline() {
14933         rebuildOutline();
14934 
14935         notifySubtreeAccessibilityStateChangedIfNeeded();
14936         invalidateViewProperty(false, false);
14937     }
14938 
14939     /**
14940      * Internal version of {@link #invalidateOutline()} which invalidates the
14941      * outline without invalidating the view itself. This is intended to be called from
14942      * within methods in the View class itself which are the result of the view being
14943      * invalidated already. For example, when we are drawing the background of a View,
14944      * we invalidate the outline in case it changed in the meantime, but we do not
14945      * need to invalidate the view because we're already drawing the background as part
14946      * of drawing the view in response to an earlier invalidation of the view.
14947      */
14948     private void rebuildOutline() {
14949         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14950         if (mAttachInfo == null) return;
14951 
14952         if (mOutlineProvider == null) {
14953             // no provider, remove outline
14954             mRenderNode.setOutline(null);
14955         } else {
14956             final Outline outline = mAttachInfo.mTmpOutline;
14957             outline.setEmpty();
14958             outline.setAlpha(1.0f);
14959 
14960             mOutlineProvider.getOutline(this, outline);
14961             mRenderNode.setOutline(outline);
14962         }
14963     }
14964 
14965     /**
14966      * HierarchyViewer only
14967      *
14968      * @hide
14969      */
14970     @ViewDebug.ExportedProperty(category = "drawing")
14971     public boolean hasShadow() {
14972         return mRenderNode.hasShadow();
14973     }
14974 
14975 
14976     /** @hide */
14977     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14978         mRenderNode.setRevealClip(shouldClip, x, y, radius);
14979         invalidateViewProperty(false, false);
14980     }
14981 
14982     /**
14983      * Hit rectangle in parent's coordinates
14984      *
14985      * @param outRect The hit rectangle of the view.
14986      */
14987     public void getHitRect(Rect outRect) {
14988         if (hasIdentityMatrix() || mAttachInfo == null) {
14989             outRect.set(mLeft, mTop, mRight, mBottom);
14990         } else {
14991             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14992             tmpRect.set(0, 0, getWidth(), getHeight());
14993             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14994             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14995                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14996         }
14997     }
14998 
14999     /**
15000      * Determines whether the given point, in local coordinates is inside the view.
15001      */
15002     /*package*/ final boolean pointInView(float localX, float localY) {
15003         return pointInView(localX, localY, 0);
15004     }
15005 
15006     /**
15007      * Utility method to determine whether the given point, in local coordinates,
15008      * is inside the view, where the area of the view is expanded by the slop factor.
15009      * This method is called while processing touch-move events to determine if the event
15010      * is still within the view.
15011      *
15012      * @hide
15013      */
15014     public boolean pointInView(float localX, float localY, float slop) {
15015         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
15016                 localY < ((mBottom - mTop) + slop);
15017     }
15018 
15019     /**
15020      * When a view has focus and the user navigates away from it, the next view is searched for
15021      * starting from the rectangle filled in by this method.
15022      *
15023      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
15024      * of the view.  However, if your view maintains some idea of internal selection,
15025      * such as a cursor, or a selected row or column, you should override this method and
15026      * fill in a more specific rectangle.
15027      *
15028      * @param r The rectangle to fill in, in this view's coordinates.
15029      */
15030     public void getFocusedRect(Rect r) {
15031         getDrawingRect(r);
15032     }
15033 
15034     /**
15035      * If some part of this view is not clipped by any of its parents, then
15036      * return that area in r in global (root) coordinates. To convert r to local
15037      * coordinates (without taking possible View rotations into account), offset
15038      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
15039      * If the view is completely clipped or translated out, return false.
15040      *
15041      * @param r If true is returned, r holds the global coordinates of the
15042      *        visible portion of this view.
15043      * @param globalOffset If true is returned, globalOffset holds the dx,dy
15044      *        between this view and its root. globalOffet may be null.
15045      * @return true if r is non-empty (i.e. part of the view is visible at the
15046      *         root level.
15047      */
15048     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
15049         int width = mRight - mLeft;
15050         int height = mBottom - mTop;
15051         if (width > 0 && height > 0) {
15052             r.set(0, 0, width, height);
15053             if (globalOffset != null) {
15054                 globalOffset.set(-mScrollX, -mScrollY);
15055             }
15056             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
15057         }
15058         return false;
15059     }
15060 
15061     public final boolean getGlobalVisibleRect(Rect r) {
15062         return getGlobalVisibleRect(r, null);
15063     }
15064 
15065     public final boolean getLocalVisibleRect(Rect r) {
15066         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
15067         if (getGlobalVisibleRect(r, offset)) {
15068             r.offset(-offset.x, -offset.y); // make r local
15069             return true;
15070         }
15071         return false;
15072     }
15073 
15074     /**
15075      * Offset this view's vertical location by the specified number of pixels.
15076      *
15077      * @param offset the number of pixels to offset the view by
15078      */
15079     public void offsetTopAndBottom(int offset) {
15080         if (offset != 0) {
15081             final boolean matrixIsIdentity = hasIdentityMatrix();
15082             if (matrixIsIdentity) {
15083                 if (isHardwareAccelerated()) {
15084                     invalidateViewProperty(false, false);
15085                 } else {
15086                     final ViewParent p = mParent;
15087                     if (p != null && mAttachInfo != null) {
15088                         final Rect r = mAttachInfo.mTmpInvalRect;
15089                         int minTop;
15090                         int maxBottom;
15091                         int yLoc;
15092                         if (offset < 0) {
15093                             minTop = mTop + offset;
15094                             maxBottom = mBottom;
15095                             yLoc = offset;
15096                         } else {
15097                             minTop = mTop;
15098                             maxBottom = mBottom + offset;
15099                             yLoc = 0;
15100                         }
15101                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
15102                         p.invalidateChild(this, r);
15103                     }
15104                 }
15105             } else {
15106                 invalidateViewProperty(false, false);
15107             }
15108 
15109             mTop += offset;
15110             mBottom += offset;
15111             mRenderNode.offsetTopAndBottom(offset);
15112             if (isHardwareAccelerated()) {
15113                 invalidateViewProperty(false, false);
15114                 invalidateParentIfNeededAndWasQuickRejected();
15115             } else {
15116                 if (!matrixIsIdentity) {
15117                     invalidateViewProperty(false, true);
15118                 }
15119                 invalidateParentIfNeeded();
15120             }
15121             notifySubtreeAccessibilityStateChangedIfNeeded();
15122         }
15123     }
15124 
15125     /**
15126      * Offset this view's horizontal location by the specified amount of pixels.
15127      *
15128      * @param offset the number of pixels to offset the view by
15129      */
15130     public void offsetLeftAndRight(int offset) {
15131         if (offset != 0) {
15132             final boolean matrixIsIdentity = hasIdentityMatrix();
15133             if (matrixIsIdentity) {
15134                 if (isHardwareAccelerated()) {
15135                     invalidateViewProperty(false, false);
15136                 } else {
15137                     final ViewParent p = mParent;
15138                     if (p != null && mAttachInfo != null) {
15139                         final Rect r = mAttachInfo.mTmpInvalRect;
15140                         int minLeft;
15141                         int maxRight;
15142                         if (offset < 0) {
15143                             minLeft = mLeft + offset;
15144                             maxRight = mRight;
15145                         } else {
15146                             minLeft = mLeft;
15147                             maxRight = mRight + offset;
15148                         }
15149                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
15150                         p.invalidateChild(this, r);
15151                     }
15152                 }
15153             } else {
15154                 invalidateViewProperty(false, false);
15155             }
15156 
15157             mLeft += offset;
15158             mRight += offset;
15159             mRenderNode.offsetLeftAndRight(offset);
15160             if (isHardwareAccelerated()) {
15161                 invalidateViewProperty(false, false);
15162                 invalidateParentIfNeededAndWasQuickRejected();
15163             } else {
15164                 if (!matrixIsIdentity) {
15165                     invalidateViewProperty(false, true);
15166                 }
15167                 invalidateParentIfNeeded();
15168             }
15169             notifySubtreeAccessibilityStateChangedIfNeeded();
15170         }
15171     }
15172 
15173     /**
15174      * Get the LayoutParams associated with this view. All views should have
15175      * layout parameters. These supply parameters to the <i>parent</i> of this
15176      * view specifying how it should be arranged. There are many subclasses of
15177      * ViewGroup.LayoutParams, and these correspond to the different subclasses
15178      * of ViewGroup that are responsible for arranging their children.
15179      *
15180      * This method may return null if this View is not attached to a parent
15181      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
15182      * was not invoked successfully. When a View is attached to a parent
15183      * ViewGroup, this method must not return null.
15184      *
15185      * @return The LayoutParams associated with this view, or null if no
15186      *         parameters have been set yet
15187      */
15188     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
15189     public ViewGroup.LayoutParams getLayoutParams() {
15190         return mLayoutParams;
15191     }
15192 
15193     /**
15194      * Set the layout parameters associated with this view. These supply
15195      * parameters to the <i>parent</i> of this view specifying how it should be
15196      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
15197      * correspond to the different subclasses of ViewGroup that are responsible
15198      * for arranging their children.
15199      *
15200      * @param params The layout parameters for this view, cannot be null
15201      */
15202     public void setLayoutParams(ViewGroup.LayoutParams params) {
15203         if (params == null) {
15204             throw new NullPointerException("Layout parameters cannot be null");
15205         }
15206         mLayoutParams = params;
15207         resolveLayoutParams();
15208         if (mParent instanceof ViewGroup) {
15209             ((ViewGroup) mParent).onSetLayoutParams(this, params);
15210         }
15211         requestLayout();
15212     }
15213 
15214     /**
15215      * Resolve the layout parameters depending on the resolved layout direction
15216      *
15217      * @hide
15218      */
15219     public void resolveLayoutParams() {
15220         if (mLayoutParams != null) {
15221             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
15222         }
15223     }
15224 
15225     /**
15226      * Set the scrolled position of your view. This will cause a call to
15227      * {@link #onScrollChanged(int, int, int, int)} and the view will be
15228      * invalidated.
15229      * @param x the x position to scroll to
15230      * @param y the y position to scroll to
15231      */
15232     public void scrollTo(int x, int y) {
15233         if (mScrollX != x || mScrollY != y) {
15234             int oldX = mScrollX;
15235             int oldY = mScrollY;
15236             mScrollX = x;
15237             mScrollY = y;
15238             invalidateParentCaches();
15239             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
15240             if (!awakenScrollBars()) {
15241                 postInvalidateOnAnimation();
15242             }
15243         }
15244     }
15245 
15246     /**
15247      * Move the scrolled position of your view. This will cause a call to
15248      * {@link #onScrollChanged(int, int, int, int)} and the view will be
15249      * invalidated.
15250      * @param x the amount of pixels to scroll by horizontally
15251      * @param y the amount of pixels to scroll by vertically
15252      */
15253     public void scrollBy(int x, int y) {
15254         scrollTo(mScrollX + x, mScrollY + y);
15255     }
15256 
15257     /**
15258      * <p>Trigger the scrollbars to draw. When invoked this method starts an
15259      * animation to fade the scrollbars out after a default delay. If a subclass
15260      * provides animated scrolling, the start delay should equal the duration
15261      * of the scrolling animation.</p>
15262      *
15263      * <p>The animation starts only if at least one of the scrollbars is
15264      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
15265      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15266      * this method returns true, and false otherwise. If the animation is
15267      * started, this method calls {@link #invalidate()}; in that case the
15268      * caller should not call {@link #invalidate()}.</p>
15269      *
15270      * <p>This method should be invoked every time a subclass directly updates
15271      * the scroll parameters.</p>
15272      *
15273      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
15274      * and {@link #scrollTo(int, int)}.</p>
15275      *
15276      * @return true if the animation is played, false otherwise
15277      *
15278      * @see #awakenScrollBars(int)
15279      * @see #scrollBy(int, int)
15280      * @see #scrollTo(int, int)
15281      * @see #isHorizontalScrollBarEnabled()
15282      * @see #isVerticalScrollBarEnabled()
15283      * @see #setHorizontalScrollBarEnabled(boolean)
15284      * @see #setVerticalScrollBarEnabled(boolean)
15285      */
15286     protected boolean awakenScrollBars() {
15287         return mScrollCache != null &&
15288                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
15289     }
15290 
15291     /**
15292      * Trigger the scrollbars to draw.
15293      * This method differs from awakenScrollBars() only in its default duration.
15294      * initialAwakenScrollBars() will show the scroll bars for longer than
15295      * usual to give the user more of a chance to notice them.
15296      *
15297      * @return true if the animation is played, false otherwise.
15298      */
15299     private boolean initialAwakenScrollBars() {
15300         return mScrollCache != null &&
15301                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
15302     }
15303 
15304     /**
15305      * <p>
15306      * Trigger the scrollbars to draw. When invoked this method starts an
15307      * animation to fade the scrollbars out after a fixed delay. If a subclass
15308      * provides animated scrolling, the start delay should equal the duration of
15309      * the scrolling animation.
15310      * </p>
15311      *
15312      * <p>
15313      * The animation starts only if at least one of the scrollbars is enabled,
15314      * as specified by {@link #isHorizontalScrollBarEnabled()} and
15315      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15316      * this method returns true, and false otherwise. If the animation is
15317      * started, this method calls {@link #invalidate()}; in that case the caller
15318      * should not call {@link #invalidate()}.
15319      * </p>
15320      *
15321      * <p>
15322      * This method should be invoked every time a subclass directly updates the
15323      * scroll parameters.
15324      * </p>
15325      *
15326      * @param startDelay the delay, in milliseconds, after which the animation
15327      *        should start; when the delay is 0, the animation starts
15328      *        immediately
15329      * @return true if the animation is played, false otherwise
15330      *
15331      * @see #scrollBy(int, int)
15332      * @see #scrollTo(int, int)
15333      * @see #isHorizontalScrollBarEnabled()
15334      * @see #isVerticalScrollBarEnabled()
15335      * @see #setHorizontalScrollBarEnabled(boolean)
15336      * @see #setVerticalScrollBarEnabled(boolean)
15337      */
15338     protected boolean awakenScrollBars(int startDelay) {
15339         return awakenScrollBars(startDelay, true);
15340     }
15341 
15342     /**
15343      * <p>
15344      * Trigger the scrollbars to draw. When invoked this method starts an
15345      * animation to fade the scrollbars out after a fixed delay. If a subclass
15346      * provides animated scrolling, the start delay should equal the duration of
15347      * the scrolling animation.
15348      * </p>
15349      *
15350      * <p>
15351      * The animation starts only if at least one of the scrollbars is enabled,
15352      * as specified by {@link #isHorizontalScrollBarEnabled()} and
15353      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15354      * this method returns true, and false otherwise. If the animation is
15355      * started, this method calls {@link #invalidate()} if the invalidate parameter
15356      * is set to true; in that case the caller
15357      * should not call {@link #invalidate()}.
15358      * </p>
15359      *
15360      * <p>
15361      * This method should be invoked every time a subclass directly updates the
15362      * scroll parameters.
15363      * </p>
15364      *
15365      * @param startDelay the delay, in milliseconds, after which the animation
15366      *        should start; when the delay is 0, the animation starts
15367      *        immediately
15368      *
15369      * @param invalidate Whether this method should call invalidate
15370      *
15371      * @return true if the animation is played, false otherwise
15372      *
15373      * @see #scrollBy(int, int)
15374      * @see #scrollTo(int, int)
15375      * @see #isHorizontalScrollBarEnabled()
15376      * @see #isVerticalScrollBarEnabled()
15377      * @see #setHorizontalScrollBarEnabled(boolean)
15378      * @see #setVerticalScrollBarEnabled(boolean)
15379      */
15380     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
15381         final ScrollabilityCache scrollCache = mScrollCache;
15382 
15383         if (scrollCache == null || !scrollCache.fadeScrollBars) {
15384             return false;
15385         }
15386 
15387         if (scrollCache.scrollBar == null) {
15388             scrollCache.scrollBar = new ScrollBarDrawable();
15389             scrollCache.scrollBar.setState(getDrawableState());
15390             scrollCache.scrollBar.setCallback(this);
15391         }
15392 
15393         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
15394 
15395             if (invalidate) {
15396                 // Invalidate to show the scrollbars
15397                 postInvalidateOnAnimation();
15398             }
15399 
15400             if (scrollCache.state == ScrollabilityCache.OFF) {
15401                 // FIXME: this is copied from WindowManagerService.
15402                 // We should get this value from the system when it
15403                 // is possible to do so.
15404                 final int KEY_REPEAT_FIRST_DELAY = 750;
15405                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
15406             }
15407 
15408             // Tell mScrollCache when we should start fading. This may
15409             // extend the fade start time if one was already scheduled
15410             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
15411             scrollCache.fadeStartTime = fadeStartTime;
15412             scrollCache.state = ScrollabilityCache.ON;
15413 
15414             // Schedule our fader to run, unscheduling any old ones first
15415             if (mAttachInfo != null) {
15416                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
15417                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
15418             }
15419 
15420             return true;
15421         }
15422 
15423         return false;
15424     }
15425 
15426     /**
15427      * Do not invalidate views which are not visible and which are not running an animation. They
15428      * will not get drawn and they should not set dirty flags as if they will be drawn
15429      */
15430     private boolean skipInvalidate() {
15431         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
15432                 (!(mParent instanceof ViewGroup) ||
15433                         !((ViewGroup) mParent).isViewTransitioning(this));
15434     }
15435 
15436     /**
15437      * Mark the area defined by dirty as needing to be drawn. If the view is
15438      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15439      * point in the future.
15440      * <p>
15441      * This must be called from a UI thread. To call from a non-UI thread, call
15442      * {@link #postInvalidate()}.
15443      * <p>
15444      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15445      * {@code dirty}.
15446      *
15447      * @param dirty the rectangle representing the bounds of the dirty region
15448      */
15449     public void invalidate(Rect dirty) {
15450         final int scrollX = mScrollX;
15451         final int scrollY = mScrollY;
15452         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15453                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15454     }
15455 
15456     /**
15457      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15458      * coordinates of the dirty rect are relative to the view. If the view is
15459      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15460      * point in the future.
15461      * <p>
15462      * This must be called from a UI thread. To call from a non-UI thread, call
15463      * {@link #postInvalidate()}.
15464      *
15465      * @param l the left position of the dirty region
15466      * @param t the top position of the dirty region
15467      * @param r the right position of the dirty region
15468      * @param b the bottom position of the dirty region
15469      */
15470     public void invalidate(int l, int t, int r, int b) {
15471         final int scrollX = mScrollX;
15472         final int scrollY = mScrollY;
15473         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15474     }
15475 
15476     /**
15477      * Invalidate the whole view. If the view is visible,
15478      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15479      * the future.
15480      * <p>
15481      * This must be called from a UI thread. To call from a non-UI thread, call
15482      * {@link #postInvalidate()}.
15483      */
15484     public void invalidate() {
15485         invalidate(true);
15486     }
15487 
15488     /**
15489      * This is where the invalidate() work actually happens. A full invalidate()
15490      * causes the drawing cache to be invalidated, but this function can be
15491      * called with invalidateCache set to false to skip that invalidation step
15492      * for cases that do not need it (for example, a component that remains at
15493      * the same dimensions with the same content).
15494      *
15495      * @param invalidateCache Whether the drawing cache for this view should be
15496      *            invalidated as well. This is usually true for a full
15497      *            invalidate, but may be set to false if the View's contents or
15498      *            dimensions have not changed.
15499      * @hide
15500      */
15501     public void invalidate(boolean invalidateCache) {
15502         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15503     }
15504 
15505     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15506             boolean fullInvalidate) {
15507         if (mGhostView != null) {
15508             mGhostView.invalidate(true);
15509             return;
15510         }
15511 
15512         if (skipInvalidate()) {
15513             return;
15514         }
15515 
15516         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15517                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15518                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15519                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15520             if (fullInvalidate) {
15521                 mLastIsOpaque = isOpaque();
15522                 mPrivateFlags &= ~PFLAG_DRAWN;
15523             }
15524 
15525             mPrivateFlags |= PFLAG_DIRTY;
15526 
15527             if (invalidateCache) {
15528                 mPrivateFlags |= PFLAG_INVALIDATED;
15529                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15530             }
15531 
15532             // Propagate the damage rectangle to the parent view.
15533             final AttachInfo ai = mAttachInfo;
15534             final ViewParent p = mParent;
15535             if (p != null && ai != null && l < r && t < b) {
15536                 final Rect damage = ai.mTmpInvalRect;
15537                 damage.set(l, t, r, b);
15538                 p.invalidateChild(this, damage);
15539             }
15540 
15541             // Damage the entire projection receiver, if necessary.
15542             if (mBackground != null && mBackground.isProjected()) {
15543                 final View receiver = getProjectionReceiver();
15544                 if (receiver != null) {
15545                     receiver.damageInParent();
15546                 }
15547             }
15548         }
15549     }
15550 
15551     /**
15552      * @return this view's projection receiver, or {@code null} if none exists
15553      */
15554     private View getProjectionReceiver() {
15555         ViewParent p = getParent();
15556         while (p != null && p instanceof View) {
15557             final View v = (View) p;
15558             if (v.isProjectionReceiver()) {
15559                 return v;
15560             }
15561             p = p.getParent();
15562         }
15563 
15564         return null;
15565     }
15566 
15567     /**
15568      * @return whether the view is a projection receiver
15569      */
15570     private boolean isProjectionReceiver() {
15571         return mBackground != null;
15572     }
15573 
15574     /**
15575      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15576      * set any flags or handle all of the cases handled by the default invalidation methods.
15577      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15578      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15579      * walk up the hierarchy, transforming the dirty rect as necessary.
15580      *
15581      * The method also handles normal invalidation logic if display list properties are not
15582      * being used in this view. The invalidateParent and forceRedraw flags are used by that
15583      * backup approach, to handle these cases used in the various property-setting methods.
15584      *
15585      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15586      * are not being used in this view
15587      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15588      * list properties are not being used in this view
15589      */
15590     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15591         if (!isHardwareAccelerated()
15592                 || !mRenderNode.isValid()
15593                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15594             if (invalidateParent) {
15595                 invalidateParentCaches();
15596             }
15597             if (forceRedraw) {
15598                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15599             }
15600             invalidate(false);
15601         } else {
15602             damageInParent();
15603         }
15604     }
15605 
15606     /**
15607      * Tells the parent view to damage this view's bounds.
15608      *
15609      * @hide
15610      */
15611     protected void damageInParent() {
15612         if (mParent != null && mAttachInfo != null) {
15613             mParent.onDescendantInvalidated(this, this);
15614         }
15615     }
15616 
15617     /**
15618      * Utility method to transform a given Rect by the current matrix of this view.
15619      */
15620     void transformRect(final Rect rect) {
15621         if (!getMatrix().isIdentity()) {
15622             RectF boundingRect = mAttachInfo.mTmpTransformRect;
15623             boundingRect.set(rect);
15624             getMatrix().mapRect(boundingRect);
15625             rect.set((int) Math.floor(boundingRect.left),
15626                     (int) Math.floor(boundingRect.top),
15627                     (int) Math.ceil(boundingRect.right),
15628                     (int) Math.ceil(boundingRect.bottom));
15629         }
15630     }
15631 
15632     /**
15633      * Used to indicate that the parent of this view should clear its caches. This functionality
15634      * is used to force the parent to rebuild its display list (when hardware-accelerated),
15635      * which is necessary when various parent-managed properties of the view change, such as
15636      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15637      * clears the parent caches and does not causes an invalidate event.
15638      *
15639      * @hide
15640      */
15641     protected void invalidateParentCaches() {
15642         if (mParent instanceof View) {
15643             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15644         }
15645     }
15646 
15647     /**
15648      * Used to indicate that the parent of this view should be invalidated. This functionality
15649      * is used to force the parent to rebuild its display list (when hardware-accelerated),
15650      * which is necessary when various parent-managed properties of the view change, such as
15651      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15652      * an invalidation event to the parent.
15653      *
15654      * @hide
15655      */
15656     protected void invalidateParentIfNeeded() {
15657         if (isHardwareAccelerated() && mParent instanceof View) {
15658             ((View) mParent).invalidate(true);
15659         }
15660     }
15661 
15662     /**
15663      * @hide
15664      */
15665     protected void invalidateParentIfNeededAndWasQuickRejected() {
15666         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15667             // View was rejected last time it was drawn by its parent; this may have changed
15668             invalidateParentIfNeeded();
15669         }
15670     }
15671 
15672     /**
15673      * Indicates whether this View is opaque. An opaque View guarantees that it will
15674      * draw all the pixels overlapping its bounds using a fully opaque color.
15675      *
15676      * Subclasses of View should override this method whenever possible to indicate
15677      * whether an instance is opaque. Opaque Views are treated in a special way by
15678      * the View hierarchy, possibly allowing it to perform optimizations during
15679      * invalidate/draw passes.
15680      *
15681      * @return True if this View is guaranteed to be fully opaque, false otherwise.
15682      */
15683     @ViewDebug.ExportedProperty(category = "drawing")
15684     public boolean isOpaque() {
15685         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15686                 getFinalAlpha() >= 1.0f;
15687     }
15688 
15689     /**
15690      * @hide
15691      */
15692     protected void computeOpaqueFlags() {
15693         // Opaque if:
15694         //   - Has a background
15695         //   - Background is opaque
15696         //   - Doesn't have scrollbars or scrollbars overlay
15697 
15698         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15699             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15700         } else {
15701             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15702         }
15703 
15704         final int flags = mViewFlags;
15705         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15706                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15707                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15708             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15709         } else {
15710             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15711         }
15712     }
15713 
15714     /**
15715      * @hide
15716      */
15717     protected boolean hasOpaqueScrollbars() {
15718         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15719     }
15720 
15721     /**
15722      * @return A handler associated with the thread running the View. This
15723      * handler can be used to pump events in the UI events queue.
15724      */
15725     public Handler getHandler() {
15726         final AttachInfo attachInfo = mAttachInfo;
15727         if (attachInfo != null) {
15728             return attachInfo.mHandler;
15729         }
15730         return null;
15731     }
15732 
15733     /**
15734      * Returns the queue of runnable for this view.
15735      *
15736      * @return the queue of runnables for this view
15737      */
15738     private HandlerActionQueue getRunQueue() {
15739         if (mRunQueue == null) {
15740             mRunQueue = new HandlerActionQueue();
15741         }
15742         return mRunQueue;
15743     }
15744 
15745     /**
15746      * Gets the view root associated with the View.
15747      * @return The view root, or null if none.
15748      * @hide
15749      */
15750     public ViewRootImpl getViewRootImpl() {
15751         if (mAttachInfo != null) {
15752             return mAttachInfo.mViewRootImpl;
15753         }
15754         return null;
15755     }
15756 
15757     /**
15758      * @hide
15759      */
15760     public ThreadedRenderer getThreadedRenderer() {
15761         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15762     }
15763 
15764     /**
15765      * <p>Causes the Runnable to be added to the message queue.
15766      * The runnable will be run on the user interface thread.</p>
15767      *
15768      * @param action The Runnable that will be executed.
15769      *
15770      * @return Returns true if the Runnable was successfully placed in to the
15771      *         message queue.  Returns false on failure, usually because the
15772      *         looper processing the message queue is exiting.
15773      *
15774      * @see #postDelayed
15775      * @see #removeCallbacks
15776      */
15777     public boolean post(Runnable action) {
15778         final AttachInfo attachInfo = mAttachInfo;
15779         if (attachInfo != null) {
15780             return attachInfo.mHandler.post(action);
15781         }
15782 
15783         // Postpone the runnable until we know on which thread it needs to run.
15784         // Assume that the runnable will be successfully placed after attach.
15785         getRunQueue().post(action);
15786         return true;
15787     }
15788 
15789     /**
15790      * <p>Causes the Runnable to be added to the message queue, to be run
15791      * after the specified amount of time elapses.
15792      * The runnable will be run on the user interface thread.</p>
15793      *
15794      * @param action The Runnable that will be executed.
15795      * @param delayMillis The delay (in milliseconds) until the Runnable
15796      *        will be executed.
15797      *
15798      * @return true if the Runnable was successfully placed in to the
15799      *         message queue.  Returns false on failure, usually because the
15800      *         looper processing the message queue is exiting.  Note that a
15801      *         result of true does not mean the Runnable will be processed --
15802      *         if the looper is quit before the delivery time of the message
15803      *         occurs then the message will be dropped.
15804      *
15805      * @see #post
15806      * @see #removeCallbacks
15807      */
15808     public boolean postDelayed(Runnable action, long delayMillis) {
15809         final AttachInfo attachInfo = mAttachInfo;
15810         if (attachInfo != null) {
15811             return attachInfo.mHandler.postDelayed(action, delayMillis);
15812         }
15813 
15814         // Postpone the runnable until we know on which thread it needs to run.
15815         // Assume that the runnable will be successfully placed after attach.
15816         getRunQueue().postDelayed(action, delayMillis);
15817         return true;
15818     }
15819 
15820     /**
15821      * <p>Causes the Runnable to execute on the next animation time step.
15822      * The runnable will be run on the user interface thread.</p>
15823      *
15824      * @param action The Runnable that will be executed.
15825      *
15826      * @see #postOnAnimationDelayed
15827      * @see #removeCallbacks
15828      */
15829     public void postOnAnimation(Runnable action) {
15830         final AttachInfo attachInfo = mAttachInfo;
15831         if (attachInfo != null) {
15832             attachInfo.mViewRootImpl.mChoreographer.postCallback(
15833                     Choreographer.CALLBACK_ANIMATION, action, null);
15834         } else {
15835             // Postpone the runnable until we know
15836             // on which thread it needs to run.
15837             getRunQueue().post(action);
15838         }
15839     }
15840 
15841     /**
15842      * <p>Causes the Runnable to execute on the next animation time step,
15843      * after the specified amount of time elapses.
15844      * The runnable will be run on the user interface thread.</p>
15845      *
15846      * @param action The Runnable that will be executed.
15847      * @param delayMillis The delay (in milliseconds) until the Runnable
15848      *        will be executed.
15849      *
15850      * @see #postOnAnimation
15851      * @see #removeCallbacks
15852      */
15853     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15854         final AttachInfo attachInfo = mAttachInfo;
15855         if (attachInfo != null) {
15856             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15857                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15858         } else {
15859             // Postpone the runnable until we know
15860             // on which thread it needs to run.
15861             getRunQueue().postDelayed(action, delayMillis);
15862         }
15863     }
15864 
15865     /**
15866      * <p>Removes the specified Runnable from the message queue.</p>
15867      *
15868      * @param action The Runnable to remove from the message handling queue
15869      *
15870      * @return true if this view could ask the Handler to remove the Runnable,
15871      *         false otherwise. When the returned value is true, the Runnable
15872      *         may or may not have been actually removed from the message queue
15873      *         (for instance, if the Runnable was not in the queue already.)
15874      *
15875      * @see #post
15876      * @see #postDelayed
15877      * @see #postOnAnimation
15878      * @see #postOnAnimationDelayed
15879      */
15880     public boolean removeCallbacks(Runnable action) {
15881         if (action != null) {
15882             final AttachInfo attachInfo = mAttachInfo;
15883             if (attachInfo != null) {
15884                 attachInfo.mHandler.removeCallbacks(action);
15885                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15886                         Choreographer.CALLBACK_ANIMATION, action, null);
15887             }
15888             getRunQueue().removeCallbacks(action);
15889         }
15890         return true;
15891     }
15892 
15893     /**
15894      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15895      * Use this to invalidate the View from a non-UI thread.</p>
15896      *
15897      * <p>This method can be invoked from outside of the UI thread
15898      * only when this View is attached to a window.</p>
15899      *
15900      * @see #invalidate()
15901      * @see #postInvalidateDelayed(long)
15902      */
15903     public void postInvalidate() {
15904         postInvalidateDelayed(0);
15905     }
15906 
15907     /**
15908      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15909      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15910      *
15911      * <p>This method can be invoked from outside of the UI thread
15912      * only when this View is attached to a window.</p>
15913      *
15914      * @param left The left coordinate of the rectangle to invalidate.
15915      * @param top The top coordinate of the rectangle to invalidate.
15916      * @param right The right coordinate of the rectangle to invalidate.
15917      * @param bottom The bottom coordinate of the rectangle to invalidate.
15918      *
15919      * @see #invalidate(int, int, int, int)
15920      * @see #invalidate(Rect)
15921      * @see #postInvalidateDelayed(long, int, int, int, int)
15922      */
15923     public void postInvalidate(int left, int top, int right, int bottom) {
15924         postInvalidateDelayed(0, left, top, right, bottom);
15925     }
15926 
15927     /**
15928      * <p>Cause an invalidate to happen on a subsequent cycle through the event
15929      * loop. Waits for the specified amount of time.</p>
15930      *
15931      * <p>This method can be invoked from outside of the UI thread
15932      * only when this View is attached to a window.</p>
15933      *
15934      * @param delayMilliseconds the duration in milliseconds to delay the
15935      *         invalidation by
15936      *
15937      * @see #invalidate()
15938      * @see #postInvalidate()
15939      */
15940     public void postInvalidateDelayed(long delayMilliseconds) {
15941         // We try only with the AttachInfo because there's no point in invalidating
15942         // if we are not attached to our window
15943         final AttachInfo attachInfo = mAttachInfo;
15944         if (attachInfo != null) {
15945             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15946         }
15947     }
15948 
15949     /**
15950      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15951      * through the event loop. Waits for the specified amount of time.</p>
15952      *
15953      * <p>This method can be invoked from outside of the UI thread
15954      * only when this View is attached to a window.</p>
15955      *
15956      * @param delayMilliseconds the duration in milliseconds to delay the
15957      *         invalidation by
15958      * @param left The left coordinate of the rectangle to invalidate.
15959      * @param top The top coordinate of the rectangle to invalidate.
15960      * @param right The right coordinate of the rectangle to invalidate.
15961      * @param bottom The bottom coordinate of the rectangle to invalidate.
15962      *
15963      * @see #invalidate(int, int, int, int)
15964      * @see #invalidate(Rect)
15965      * @see #postInvalidate(int, int, int, int)
15966      */
15967     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15968             int right, int bottom) {
15969 
15970         // We try only with the AttachInfo because there's no point in invalidating
15971         // if we are not attached to our window
15972         final AttachInfo attachInfo = mAttachInfo;
15973         if (attachInfo != null) {
15974             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15975             info.target = this;
15976             info.left = left;
15977             info.top = top;
15978             info.right = right;
15979             info.bottom = bottom;
15980 
15981             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15982         }
15983     }
15984 
15985     /**
15986      * <p>Cause an invalidate to happen on the next animation time step, typically the
15987      * next display frame.</p>
15988      *
15989      * <p>This method can be invoked from outside of the UI thread
15990      * only when this View is attached to a window.</p>
15991      *
15992      * @see #invalidate()
15993      */
15994     public void postInvalidateOnAnimation() {
15995         // We try only with the AttachInfo because there's no point in invalidating
15996         // if we are not attached to our window
15997         final AttachInfo attachInfo = mAttachInfo;
15998         if (attachInfo != null) {
15999             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
16000         }
16001     }
16002 
16003     /**
16004      * <p>Cause an invalidate of the specified area to happen on the next animation
16005      * time step, typically the next display frame.</p>
16006      *
16007      * <p>This method can be invoked from outside of the UI thread
16008      * only when this View is attached to a window.</p>
16009      *
16010      * @param left The left coordinate of the rectangle to invalidate.
16011      * @param top The top coordinate of the rectangle to invalidate.
16012      * @param right The right coordinate of the rectangle to invalidate.
16013      * @param bottom The bottom coordinate of the rectangle to invalidate.
16014      *
16015      * @see #invalidate(int, int, int, int)
16016      * @see #invalidate(Rect)
16017      */
16018     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
16019         // We try only with the AttachInfo because there's no point in invalidating
16020         // if we are not attached to our window
16021         final AttachInfo attachInfo = mAttachInfo;
16022         if (attachInfo != null) {
16023             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
16024             info.target = this;
16025             info.left = left;
16026             info.top = top;
16027             info.right = right;
16028             info.bottom = bottom;
16029 
16030             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
16031         }
16032     }
16033 
16034     /**
16035      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
16036      * This event is sent at most once every
16037      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
16038      */
16039     private void postSendViewScrolledAccessibilityEventCallback() {
16040         if (mSendViewScrolledAccessibilityEvent == null) {
16041             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
16042         }
16043         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
16044             mSendViewScrolledAccessibilityEvent.mIsPending = true;
16045             postDelayed(mSendViewScrolledAccessibilityEvent,
16046                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
16047         }
16048     }
16049 
16050     /**
16051      * Called by a parent to request that a child update its values for mScrollX
16052      * and mScrollY if necessary. This will typically be done if the child is
16053      * animating a scroll using a {@link android.widget.Scroller Scroller}
16054      * object.
16055      */
16056     public void computeScroll() {
16057     }
16058 
16059     /**
16060      * <p>Indicate whether the horizontal edges are faded when the view is
16061      * scrolled horizontally.</p>
16062      *
16063      * @return true if the horizontal edges should are faded on scroll, false
16064      *         otherwise
16065      *
16066      * @see #setHorizontalFadingEdgeEnabled(boolean)
16067      *
16068      * @attr ref android.R.styleable#View_requiresFadingEdge
16069      */
16070     public boolean isHorizontalFadingEdgeEnabled() {
16071         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
16072     }
16073 
16074     /**
16075      * <p>Define whether the horizontal edges should be faded when this view
16076      * is scrolled horizontally.</p>
16077      *
16078      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
16079      *                                    be faded when the view is scrolled
16080      *                                    horizontally
16081      *
16082      * @see #isHorizontalFadingEdgeEnabled()
16083      *
16084      * @attr ref android.R.styleable#View_requiresFadingEdge
16085      */
16086     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
16087         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
16088             if (horizontalFadingEdgeEnabled) {
16089                 initScrollCache();
16090             }
16091 
16092             mViewFlags ^= FADING_EDGE_HORIZONTAL;
16093         }
16094     }
16095 
16096     /**
16097      * <p>Indicate whether the vertical edges are faded when the view is
16098      * scrolled horizontally.</p>
16099      *
16100      * @return true if the vertical edges should are faded on scroll, false
16101      *         otherwise
16102      *
16103      * @see #setVerticalFadingEdgeEnabled(boolean)
16104      *
16105      * @attr ref android.R.styleable#View_requiresFadingEdge
16106      */
16107     public boolean isVerticalFadingEdgeEnabled() {
16108         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
16109     }
16110 
16111     /**
16112      * <p>Define whether the vertical edges should be faded when this view
16113      * is scrolled vertically.</p>
16114      *
16115      * @param verticalFadingEdgeEnabled true if the vertical edges should
16116      *                                  be faded when the view is scrolled
16117      *                                  vertically
16118      *
16119      * @see #isVerticalFadingEdgeEnabled()
16120      *
16121      * @attr ref android.R.styleable#View_requiresFadingEdge
16122      */
16123     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
16124         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
16125             if (verticalFadingEdgeEnabled) {
16126                 initScrollCache();
16127             }
16128 
16129             mViewFlags ^= FADING_EDGE_VERTICAL;
16130         }
16131     }
16132 
16133     /**
16134      * Returns the strength, or intensity, of the top faded edge. The strength is
16135      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16136      * returns 0.0 or 1.0 but no value in between.
16137      *
16138      * Subclasses should override this method to provide a smoother fade transition
16139      * when scrolling occurs.
16140      *
16141      * @return the intensity of the top fade as a float between 0.0f and 1.0f
16142      */
16143     protected float getTopFadingEdgeStrength() {
16144         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
16145     }
16146 
16147     /**
16148      * Returns the strength, or intensity, of the bottom faded edge. The strength is
16149      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16150      * returns 0.0 or 1.0 but no value in between.
16151      *
16152      * Subclasses should override this method to provide a smoother fade transition
16153      * when scrolling occurs.
16154      *
16155      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
16156      */
16157     protected float getBottomFadingEdgeStrength() {
16158         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
16159                 computeVerticalScrollRange() ? 1.0f : 0.0f;
16160     }
16161 
16162     /**
16163      * Returns the strength, or intensity, of the left faded edge. The strength is
16164      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16165      * returns 0.0 or 1.0 but no value in between.
16166      *
16167      * Subclasses should override this method to provide a smoother fade transition
16168      * when scrolling occurs.
16169      *
16170      * @return the intensity of the left fade as a float between 0.0f and 1.0f
16171      */
16172     protected float getLeftFadingEdgeStrength() {
16173         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
16174     }
16175 
16176     /**
16177      * Returns the strength, or intensity, of the right faded edge. The strength is
16178      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16179      * returns 0.0 or 1.0 but no value in between.
16180      *
16181      * Subclasses should override this method to provide a smoother fade transition
16182      * when scrolling occurs.
16183      *
16184      * @return the intensity of the right fade as a float between 0.0f and 1.0f
16185      */
16186     protected float getRightFadingEdgeStrength() {
16187         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
16188                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
16189     }
16190 
16191     /**
16192      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
16193      * scrollbar is not drawn by default.</p>
16194      *
16195      * @return true if the horizontal scrollbar should be painted, false
16196      *         otherwise
16197      *
16198      * @see #setHorizontalScrollBarEnabled(boolean)
16199      */
16200     public boolean isHorizontalScrollBarEnabled() {
16201         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
16202     }
16203 
16204     /**
16205      * <p>Define whether the horizontal scrollbar should be drawn or not. The
16206      * scrollbar is not drawn by default.</p>
16207      *
16208      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
16209      *                                   be painted
16210      *
16211      * @see #isHorizontalScrollBarEnabled()
16212      */
16213     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
16214         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
16215             mViewFlags ^= SCROLLBARS_HORIZONTAL;
16216             computeOpaqueFlags();
16217             resolvePadding();
16218         }
16219     }
16220 
16221     /**
16222      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
16223      * scrollbar is not drawn by default.</p>
16224      *
16225      * @return true if the vertical scrollbar should be painted, false
16226      *         otherwise
16227      *
16228      * @see #setVerticalScrollBarEnabled(boolean)
16229      */
16230     public boolean isVerticalScrollBarEnabled() {
16231         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
16232     }
16233 
16234     /**
16235      * <p>Define whether the vertical scrollbar should be drawn or not. The
16236      * scrollbar is not drawn by default.</p>
16237      *
16238      * @param verticalScrollBarEnabled true if the vertical scrollbar should
16239      *                                 be painted
16240      *
16241      * @see #isVerticalScrollBarEnabled()
16242      */
16243     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
16244         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
16245             mViewFlags ^= SCROLLBARS_VERTICAL;
16246             computeOpaqueFlags();
16247             resolvePadding();
16248         }
16249     }
16250 
16251     /**
16252      * @hide
16253      */
16254     protected void recomputePadding() {
16255         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16256     }
16257 
16258     /**
16259      * Define whether scrollbars will fade when the view is not scrolling.
16260      *
16261      * @param fadeScrollbars whether to enable fading
16262      *
16263      * @attr ref android.R.styleable#View_fadeScrollbars
16264      */
16265     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
16266         initScrollCache();
16267         final ScrollabilityCache scrollabilityCache = mScrollCache;
16268         scrollabilityCache.fadeScrollBars = fadeScrollbars;
16269         if (fadeScrollbars) {
16270             scrollabilityCache.state = ScrollabilityCache.OFF;
16271         } else {
16272             scrollabilityCache.state = ScrollabilityCache.ON;
16273         }
16274     }
16275 
16276     /**
16277      *
16278      * Returns true if scrollbars will fade when this view is not scrolling
16279      *
16280      * @return true if scrollbar fading is enabled
16281      *
16282      * @attr ref android.R.styleable#View_fadeScrollbars
16283      */
16284     public boolean isScrollbarFadingEnabled() {
16285         return mScrollCache != null && mScrollCache.fadeScrollBars;
16286     }
16287 
16288     /**
16289      *
16290      * Returns the delay before scrollbars fade.
16291      *
16292      * @return the delay before scrollbars fade
16293      *
16294      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16295      */
16296     public int getScrollBarDefaultDelayBeforeFade() {
16297         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
16298                 mScrollCache.scrollBarDefaultDelayBeforeFade;
16299     }
16300 
16301     /**
16302      * Define the delay before scrollbars fade.
16303      *
16304      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
16305      *
16306      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16307      */
16308     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
16309         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
16310     }
16311 
16312     /**
16313      *
16314      * Returns the scrollbar fade duration.
16315      *
16316      * @return the scrollbar fade duration, in milliseconds
16317      *
16318      * @attr ref android.R.styleable#View_scrollbarFadeDuration
16319      */
16320     public int getScrollBarFadeDuration() {
16321         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
16322                 mScrollCache.scrollBarFadeDuration;
16323     }
16324 
16325     /**
16326      * Define the scrollbar fade duration.
16327      *
16328      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
16329      *
16330      * @attr ref android.R.styleable#View_scrollbarFadeDuration
16331      */
16332     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
16333         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
16334     }
16335 
16336     /**
16337      *
16338      * Returns the scrollbar size.
16339      *
16340      * @return the scrollbar size
16341      *
16342      * @attr ref android.R.styleable#View_scrollbarSize
16343      */
16344     public int getScrollBarSize() {
16345         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
16346                 mScrollCache.scrollBarSize;
16347     }
16348 
16349     /**
16350      * Define the scrollbar size.
16351      *
16352      * @param scrollBarSize - the scrollbar size
16353      *
16354      * @attr ref android.R.styleable#View_scrollbarSize
16355      */
16356     public void setScrollBarSize(int scrollBarSize) {
16357         getScrollCache().scrollBarSize = scrollBarSize;
16358     }
16359 
16360     /**
16361      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
16362      * inset. When inset, they add to the padding of the view. And the scrollbars
16363      * can be drawn inside the padding area or on the edge of the view. For example,
16364      * if a view has a background drawable and you want to draw the scrollbars
16365      * inside the padding specified by the drawable, you can use
16366      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
16367      * appear at the edge of the view, ignoring the padding, then you can use
16368      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
16369      * @param style the style of the scrollbars. Should be one of
16370      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
16371      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
16372      * @see #SCROLLBARS_INSIDE_OVERLAY
16373      * @see #SCROLLBARS_INSIDE_INSET
16374      * @see #SCROLLBARS_OUTSIDE_OVERLAY
16375      * @see #SCROLLBARS_OUTSIDE_INSET
16376      *
16377      * @attr ref android.R.styleable#View_scrollbarStyle
16378      */
16379     public void setScrollBarStyle(@ScrollBarStyle int style) {
16380         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
16381             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
16382             computeOpaqueFlags();
16383             resolvePadding();
16384         }
16385     }
16386 
16387     /**
16388      * <p>Returns the current scrollbar style.</p>
16389      * @return the current scrollbar style
16390      * @see #SCROLLBARS_INSIDE_OVERLAY
16391      * @see #SCROLLBARS_INSIDE_INSET
16392      * @see #SCROLLBARS_OUTSIDE_OVERLAY
16393      * @see #SCROLLBARS_OUTSIDE_INSET
16394      *
16395      * @attr ref android.R.styleable#View_scrollbarStyle
16396      */
16397     @ViewDebug.ExportedProperty(mapping = {
16398             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
16399             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
16400             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
16401             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
16402     })
16403     @ScrollBarStyle
16404     public int getScrollBarStyle() {
16405         return mViewFlags & SCROLLBARS_STYLE_MASK;
16406     }
16407 
16408     /**
16409      * <p>Compute the horizontal range that the horizontal scrollbar
16410      * represents.</p>
16411      *
16412      * <p>The range is expressed in arbitrary units that must be the same as the
16413      * units used by {@link #computeHorizontalScrollExtent()} and
16414      * {@link #computeHorizontalScrollOffset()}.</p>
16415      *
16416      * <p>The default range is the drawing width of this view.</p>
16417      *
16418      * @return the total horizontal range represented by the horizontal
16419      *         scrollbar
16420      *
16421      * @see #computeHorizontalScrollExtent()
16422      * @see #computeHorizontalScrollOffset()
16423      * @see android.widget.ScrollBarDrawable
16424      */
16425     protected int computeHorizontalScrollRange() {
16426         return getWidth();
16427     }
16428 
16429     /**
16430      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
16431      * within the horizontal range. This value is used to compute the position
16432      * of the thumb within the scrollbar's track.</p>
16433      *
16434      * <p>The range is expressed in arbitrary units that must be the same as the
16435      * units used by {@link #computeHorizontalScrollRange()} and
16436      * {@link #computeHorizontalScrollExtent()}.</p>
16437      *
16438      * <p>The default offset is the scroll offset of this view.</p>
16439      *
16440      * @return the horizontal offset of the scrollbar's thumb
16441      *
16442      * @see #computeHorizontalScrollRange()
16443      * @see #computeHorizontalScrollExtent()
16444      * @see android.widget.ScrollBarDrawable
16445      */
16446     protected int computeHorizontalScrollOffset() {
16447         return mScrollX;
16448     }
16449 
16450     /**
16451      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16452      * within the horizontal range. This value is used to compute the length
16453      * of the thumb within the scrollbar's track.</p>
16454      *
16455      * <p>The range is expressed in arbitrary units that must be the same as the
16456      * units used by {@link #computeHorizontalScrollRange()} and
16457      * {@link #computeHorizontalScrollOffset()}.</p>
16458      *
16459      * <p>The default extent is the drawing width of this view.</p>
16460      *
16461      * @return the horizontal extent of the scrollbar's thumb
16462      *
16463      * @see #computeHorizontalScrollRange()
16464      * @see #computeHorizontalScrollOffset()
16465      * @see android.widget.ScrollBarDrawable
16466      */
16467     protected int computeHorizontalScrollExtent() {
16468         return getWidth();
16469     }
16470 
16471     /**
16472      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16473      *
16474      * <p>The range is expressed in arbitrary units that must be the same as the
16475      * units used by {@link #computeVerticalScrollExtent()} and
16476      * {@link #computeVerticalScrollOffset()}.</p>
16477      *
16478      * @return the total vertical range represented by the vertical scrollbar
16479      *
16480      * <p>The default range is the drawing height of this view.</p>
16481      *
16482      * @see #computeVerticalScrollExtent()
16483      * @see #computeVerticalScrollOffset()
16484      * @see android.widget.ScrollBarDrawable
16485      */
16486     protected int computeVerticalScrollRange() {
16487         return getHeight();
16488     }
16489 
16490     /**
16491      * <p>Compute the vertical offset of the vertical scrollbar's thumb
16492      * within the horizontal range. This value is used to compute the position
16493      * of the thumb within the scrollbar's track.</p>
16494      *
16495      * <p>The range is expressed in arbitrary units that must be the same as the
16496      * units used by {@link #computeVerticalScrollRange()} and
16497      * {@link #computeVerticalScrollExtent()}.</p>
16498      *
16499      * <p>The default offset is the scroll offset of this view.</p>
16500      *
16501      * @return the vertical offset of the scrollbar's thumb
16502      *
16503      * @see #computeVerticalScrollRange()
16504      * @see #computeVerticalScrollExtent()
16505      * @see android.widget.ScrollBarDrawable
16506      */
16507     protected int computeVerticalScrollOffset() {
16508         return mScrollY;
16509     }
16510 
16511     /**
16512      * <p>Compute the vertical extent of the vertical scrollbar's thumb
16513      * within the vertical range. This value is used to compute the length
16514      * of the thumb within the scrollbar's track.</p>
16515      *
16516      * <p>The range is expressed in arbitrary units that must be the same as the
16517      * units used by {@link #computeVerticalScrollRange()} and
16518      * {@link #computeVerticalScrollOffset()}.</p>
16519      *
16520      * <p>The default extent is the drawing height of this view.</p>
16521      *
16522      * @return the vertical extent of the scrollbar's thumb
16523      *
16524      * @see #computeVerticalScrollRange()
16525      * @see #computeVerticalScrollOffset()
16526      * @see android.widget.ScrollBarDrawable
16527      */
16528     protected int computeVerticalScrollExtent() {
16529         return getHeight();
16530     }
16531 
16532     /**
16533      * Check if this view can be scrolled horizontally in a certain direction.
16534      *
16535      * @param direction Negative to check scrolling left, positive to check scrolling right.
16536      * @return true if this view can be scrolled in the specified direction, false otherwise.
16537      */
16538     public boolean canScrollHorizontally(int direction) {
16539         final int offset = computeHorizontalScrollOffset();
16540         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16541         if (range == 0) return false;
16542         if (direction < 0) {
16543             return offset > 0;
16544         } else {
16545             return offset < range - 1;
16546         }
16547     }
16548 
16549     /**
16550      * Check if this view can be scrolled vertically in a certain direction.
16551      *
16552      * @param direction Negative to check scrolling up, positive to check scrolling down.
16553      * @return true if this view can be scrolled in the specified direction, false otherwise.
16554      */
16555     public boolean canScrollVertically(int direction) {
16556         final int offset = computeVerticalScrollOffset();
16557         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16558         if (range == 0) return false;
16559         if (direction < 0) {
16560             return offset > 0;
16561         } else {
16562             return offset < range - 1;
16563         }
16564     }
16565 
16566     void getScrollIndicatorBounds(@NonNull Rect out) {
16567         out.left = mScrollX;
16568         out.right = mScrollX + mRight - mLeft;
16569         out.top = mScrollY;
16570         out.bottom = mScrollY + mBottom - mTop;
16571     }
16572 
16573     private void onDrawScrollIndicators(Canvas c) {
16574         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16575             // No scroll indicators enabled.
16576             return;
16577         }
16578 
16579         final Drawable dr = mScrollIndicatorDrawable;
16580         if (dr == null) {
16581             // Scroll indicators aren't supported here.
16582             return;
16583         }
16584 
16585         final int h = dr.getIntrinsicHeight();
16586         final int w = dr.getIntrinsicWidth();
16587         final Rect rect = mAttachInfo.mTmpInvalRect;
16588         getScrollIndicatorBounds(rect);
16589 
16590         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16591             final boolean canScrollUp = canScrollVertically(-1);
16592             if (canScrollUp) {
16593                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16594                 dr.draw(c);
16595             }
16596         }
16597 
16598         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16599             final boolean canScrollDown = canScrollVertically(1);
16600             if (canScrollDown) {
16601                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16602                 dr.draw(c);
16603             }
16604         }
16605 
16606         final int leftRtl;
16607         final int rightRtl;
16608         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16609             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16610             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16611         } else {
16612             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16613             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16614         }
16615 
16616         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16617         if ((mPrivateFlags3 & leftMask) != 0) {
16618             final boolean canScrollLeft = canScrollHorizontally(-1);
16619             if (canScrollLeft) {
16620                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16621                 dr.draw(c);
16622             }
16623         }
16624 
16625         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16626         if ((mPrivateFlags3 & rightMask) != 0) {
16627             final boolean canScrollRight = canScrollHorizontally(1);
16628             if (canScrollRight) {
16629                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16630                 dr.draw(c);
16631             }
16632         }
16633     }
16634 
16635     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16636             @Nullable Rect touchBounds) {
16637         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16638         if (bounds == null) {
16639             return;
16640         }
16641         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16642         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16643                 && !isVerticalScrollBarHidden();
16644         final int size = getHorizontalScrollbarHeight();
16645         final int verticalScrollBarGap = drawVerticalScrollBar ?
16646                 getVerticalScrollbarWidth() : 0;
16647         final int width = mRight - mLeft;
16648         final int height = mBottom - mTop;
16649         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16650         bounds.left = mScrollX + (mPaddingLeft & inside);
16651         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16652         bounds.bottom = bounds.top + size;
16653 
16654         if (touchBounds == null) {
16655             return;
16656         }
16657         if (touchBounds != bounds) {
16658             touchBounds.set(bounds);
16659         }
16660         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16661         if (touchBounds.height() < minTouchTarget) {
16662             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16663             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16664             touchBounds.top = touchBounds.bottom - minTouchTarget;
16665         }
16666         if (touchBounds.width() < minTouchTarget) {
16667             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16668             touchBounds.left -= adjust;
16669             touchBounds.right = touchBounds.left + minTouchTarget;
16670         }
16671     }
16672 
16673     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16674         if (mRoundScrollbarRenderer == null) {
16675             getStraightVerticalScrollBarBounds(bounds, touchBounds);
16676         } else {
16677             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16678         }
16679     }
16680 
16681     private void getRoundVerticalScrollBarBounds(Rect bounds) {
16682         final int width = mRight - mLeft;
16683         final int height = mBottom - mTop;
16684         // Do not take padding into account as we always want the scrollbars
16685         // to hug the screen for round wearable devices.
16686         bounds.left = mScrollX;
16687         bounds.top = mScrollY;
16688         bounds.right = bounds.left + width;
16689         bounds.bottom = mScrollY + height;
16690     }
16691 
16692     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16693             @Nullable Rect touchBounds) {
16694         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16695         if (bounds == null) {
16696             return;
16697         }
16698         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16699         final int size = getVerticalScrollbarWidth();
16700         int verticalScrollbarPosition = mVerticalScrollbarPosition;
16701         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16702             verticalScrollbarPosition = isLayoutRtl() ?
16703                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16704         }
16705         final int width = mRight - mLeft;
16706         final int height = mBottom - mTop;
16707         switch (verticalScrollbarPosition) {
16708             default:
16709             case SCROLLBAR_POSITION_RIGHT:
16710                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16711                 break;
16712             case SCROLLBAR_POSITION_LEFT:
16713                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
16714                 break;
16715         }
16716         bounds.top = mScrollY + (mPaddingTop & inside);
16717         bounds.right = bounds.left + size;
16718         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16719 
16720         if (touchBounds == null) {
16721             return;
16722         }
16723         if (touchBounds != bounds) {
16724             touchBounds.set(bounds);
16725         }
16726         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16727         if (touchBounds.width() < minTouchTarget) {
16728             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16729             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16730                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16731                 touchBounds.left = touchBounds.right - minTouchTarget;
16732             } else {
16733                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16734                 touchBounds.right = touchBounds.left + minTouchTarget;
16735             }
16736         }
16737         if (touchBounds.height() < minTouchTarget) {
16738             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16739             touchBounds.top -= adjust;
16740             touchBounds.bottom = touchBounds.top + minTouchTarget;
16741         }
16742     }
16743 
16744     /**
16745      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16746      * scrollbars are painted only if they have been awakened first.</p>
16747      *
16748      * @param canvas the canvas on which to draw the scrollbars
16749      *
16750      * @see #awakenScrollBars(int)
16751      */
16752     protected final void onDrawScrollBars(Canvas canvas) {
16753         // scrollbars are drawn only when the animation is running
16754         final ScrollabilityCache cache = mScrollCache;
16755 
16756         if (cache != null) {
16757 
16758             int state = cache.state;
16759 
16760             if (state == ScrollabilityCache.OFF) {
16761                 return;
16762             }
16763 
16764             boolean invalidate = false;
16765 
16766             if (state == ScrollabilityCache.FADING) {
16767                 // We're fading -- get our fade interpolation
16768                 if (cache.interpolatorValues == null) {
16769                     cache.interpolatorValues = new float[1];
16770                 }
16771 
16772                 float[] values = cache.interpolatorValues;
16773 
16774                 // Stops the animation if we're done
16775                 if (cache.scrollBarInterpolator.timeToValues(values) ==
16776                         Interpolator.Result.FREEZE_END) {
16777                     cache.state = ScrollabilityCache.OFF;
16778                 } else {
16779                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16780                 }
16781 
16782                 // This will make the scroll bars inval themselves after
16783                 // drawing. We only want this when we're fading so that
16784                 // we prevent excessive redraws
16785                 invalidate = true;
16786             } else {
16787                 // We're just on -- but we may have been fading before so
16788                 // reset alpha
16789                 cache.scrollBar.mutate().setAlpha(255);
16790             }
16791 
16792             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16793             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16794                     && !isVerticalScrollBarHidden();
16795 
16796             // Fork out the scroll bar drawing for round wearable devices.
16797             if (mRoundScrollbarRenderer != null) {
16798                 if (drawVerticalScrollBar) {
16799                     final Rect bounds = cache.mScrollBarBounds;
16800                     getVerticalScrollBarBounds(bounds, null);
16801                     mRoundScrollbarRenderer.drawRoundScrollbars(
16802                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16803                     if (invalidate) {
16804                         invalidate();
16805                     }
16806                 }
16807                 // Do not draw horizontal scroll bars for round wearable devices.
16808             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16809                 final ScrollBarDrawable scrollBar = cache.scrollBar;
16810 
16811                 if (drawHorizontalScrollBar) {
16812                     scrollBar.setParameters(computeHorizontalScrollRange(),
16813                             computeHorizontalScrollOffset(),
16814                             computeHorizontalScrollExtent(), false);
16815                     final Rect bounds = cache.mScrollBarBounds;
16816                     getHorizontalScrollBarBounds(bounds, null);
16817                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16818                             bounds.right, bounds.bottom);
16819                     if (invalidate) {
16820                         invalidate(bounds);
16821                     }
16822                 }
16823 
16824                 if (drawVerticalScrollBar) {
16825                     scrollBar.setParameters(computeVerticalScrollRange(),
16826                             computeVerticalScrollOffset(),
16827                             computeVerticalScrollExtent(), true);
16828                     final Rect bounds = cache.mScrollBarBounds;
16829                     getVerticalScrollBarBounds(bounds, null);
16830                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16831                             bounds.right, bounds.bottom);
16832                     if (invalidate) {
16833                         invalidate(bounds);
16834                     }
16835                 }
16836             }
16837         }
16838     }
16839 
16840     /**
16841      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16842      * FastScroller is visible.
16843      * @return whether to temporarily hide the vertical scrollbar
16844      * @hide
16845      */
16846     protected boolean isVerticalScrollBarHidden() {
16847         return false;
16848     }
16849 
16850     /**
16851      * <p>Draw the horizontal scrollbar if
16852      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16853      *
16854      * @param canvas the canvas on which to draw the scrollbar
16855      * @param scrollBar the scrollbar's drawable
16856      *
16857      * @see #isHorizontalScrollBarEnabled()
16858      * @see #computeHorizontalScrollRange()
16859      * @see #computeHorizontalScrollExtent()
16860      * @see #computeHorizontalScrollOffset()
16861      * @see android.widget.ScrollBarDrawable
16862      * @hide
16863      */
16864     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16865             int l, int t, int r, int b) {
16866         scrollBar.setBounds(l, t, r, b);
16867         scrollBar.draw(canvas);
16868     }
16869 
16870     /**
16871      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16872      * returns true.</p>
16873      *
16874      * @param canvas the canvas on which to draw the scrollbar
16875      * @param scrollBar the scrollbar's drawable
16876      *
16877      * @see #isVerticalScrollBarEnabled()
16878      * @see #computeVerticalScrollRange()
16879      * @see #computeVerticalScrollExtent()
16880      * @see #computeVerticalScrollOffset()
16881      * @see android.widget.ScrollBarDrawable
16882      * @hide
16883      */
16884     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16885             int l, int t, int r, int b) {
16886         scrollBar.setBounds(l, t, r, b);
16887         scrollBar.draw(canvas);
16888     }
16889 
16890     /**
16891      * Implement this to do your drawing.
16892      *
16893      * @param canvas the canvas on which the background will be drawn
16894      */
16895     protected void onDraw(Canvas canvas) {
16896     }
16897 
16898     /*
16899      * Caller is responsible for calling requestLayout if necessary.
16900      * (This allows addViewInLayout to not request a new layout.)
16901      */
16902     void assignParent(ViewParent parent) {
16903         if (mParent == null) {
16904             mParent = parent;
16905         } else if (parent == null) {
16906             mParent = null;
16907         } else {
16908             throw new RuntimeException("view " + this + " being added, but"
16909                     + " it already has a parent");
16910         }
16911     }
16912 
16913     /**
16914      * This is called when the view is attached to a window.  At this point it
16915      * has a Surface and will start drawing.  Note that this function is
16916      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16917      * however it may be called any time before the first onDraw -- including
16918      * before or after {@link #onMeasure(int, int)}.
16919      *
16920      * @see #onDetachedFromWindow()
16921      */
16922     @CallSuper
16923     protected void onAttachedToWindow() {
16924         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16925             mParent.requestTransparentRegion(this);
16926         }
16927 
16928         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16929 
16930         jumpDrawablesToCurrentState();
16931 
16932         resetSubtreeAccessibilityStateChanged();
16933 
16934         // rebuild, since Outline not maintained while View is detached
16935         rebuildOutline();
16936 
16937         if (isFocused()) {
16938             InputMethodManager imm = InputMethodManager.peekInstance();
16939             if (imm != null) {
16940                 imm.focusIn(this);
16941             }
16942         }
16943     }
16944 
16945     /**
16946      * Resolve all RTL related properties.
16947      *
16948      * @return true if resolution of RTL properties has been done
16949      *
16950      * @hide
16951      */
16952     public boolean resolveRtlPropertiesIfNeeded() {
16953         if (!needRtlPropertiesResolution()) return false;
16954 
16955         // Order is important here: LayoutDirection MUST be resolved first
16956         if (!isLayoutDirectionResolved()) {
16957             resolveLayoutDirection();
16958             resolveLayoutParams();
16959         }
16960         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16961         if (!isTextDirectionResolved()) {
16962             resolveTextDirection();
16963         }
16964         if (!isTextAlignmentResolved()) {
16965             resolveTextAlignment();
16966         }
16967         // Should resolve Drawables before Padding because we need the layout direction of the
16968         // Drawable to correctly resolve Padding.
16969         if (!areDrawablesResolved()) {
16970             resolveDrawables();
16971         }
16972         if (!isPaddingResolved()) {
16973             resolvePadding();
16974         }
16975         onRtlPropertiesChanged(getLayoutDirection());
16976         return true;
16977     }
16978 
16979     /**
16980      * Reset resolution of all RTL related properties.
16981      *
16982      * @hide
16983      */
16984     public void resetRtlProperties() {
16985         resetResolvedLayoutDirection();
16986         resetResolvedTextDirection();
16987         resetResolvedTextAlignment();
16988         resetResolvedPadding();
16989         resetResolvedDrawables();
16990     }
16991 
16992     /**
16993      * @see #onScreenStateChanged(int)
16994      */
16995     void dispatchScreenStateChanged(int screenState) {
16996         onScreenStateChanged(screenState);
16997     }
16998 
16999     /**
17000      * This method is called whenever the state of the screen this view is
17001      * attached to changes. A state change will usually occurs when the screen
17002      * turns on or off (whether it happens automatically or the user does it
17003      * manually.)
17004      *
17005      * @param screenState The new state of the screen. Can be either
17006      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
17007      */
17008     public void onScreenStateChanged(int screenState) {
17009     }
17010 
17011     /**
17012      * @see #onMovedToDisplay(int, Configuration)
17013      */
17014     void dispatchMovedToDisplay(Display display, Configuration config) {
17015         mAttachInfo.mDisplay = display;
17016         mAttachInfo.mDisplayState = display.getState();
17017         onMovedToDisplay(display.getDisplayId(), config);
17018     }
17019 
17020     /**
17021      * Called by the system when the hosting activity is moved from one display to another without
17022      * recreation. This means that the activity is declared to handle all changes to configuration
17023      * that happened when it was switched to another display, so it wasn't destroyed and created
17024      * again.
17025      *
17026      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
17027      * applied configuration actually changed. It is up to app developer to choose whether to handle
17028      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
17029      * call.
17030      *
17031      * <p>Use this callback to track changes to the displays if some functionality relies on an
17032      * association with some display properties.
17033      *
17034      * @param displayId The id of the display to which the view was moved.
17035      * @param config Configuration of the resources on new display after move.
17036      *
17037      * @see #onConfigurationChanged(Configuration)
17038      * @hide
17039      */
17040     public void onMovedToDisplay(int displayId, Configuration config) {
17041     }
17042 
17043     /**
17044      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
17045      */
17046     private boolean hasRtlSupport() {
17047         return mContext.getApplicationInfo().hasRtlSupport();
17048     }
17049 
17050     /**
17051      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
17052      * RTL not supported)
17053      */
17054     private boolean isRtlCompatibilityMode() {
17055         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
17056         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
17057     }
17058 
17059     /**
17060      * @return true if RTL properties need resolution.
17061      *
17062      */
17063     private boolean needRtlPropertiesResolution() {
17064         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
17065     }
17066 
17067     /**
17068      * Called when any RTL property (layout direction or text direction or text alignment) has
17069      * been changed.
17070      *
17071      * Subclasses need to override this method to take care of cached information that depends on the
17072      * resolved layout direction, or to inform child views that inherit their layout direction.
17073      *
17074      * The default implementation does nothing.
17075      *
17076      * @param layoutDirection the direction of the layout
17077      *
17078      * @see #LAYOUT_DIRECTION_LTR
17079      * @see #LAYOUT_DIRECTION_RTL
17080      */
17081     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
17082     }
17083 
17084     /**
17085      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
17086      * that the parent directionality can and will be resolved before its children.
17087      *
17088      * @return true if resolution has been done, false otherwise.
17089      *
17090      * @hide
17091      */
17092     public boolean resolveLayoutDirection() {
17093         // Clear any previous layout direction resolution
17094         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17095 
17096         if (hasRtlSupport()) {
17097             // Set resolved depending on layout direction
17098             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
17099                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
17100                 case LAYOUT_DIRECTION_INHERIT:
17101                     // We cannot resolve yet. LTR is by default and let the resolution happen again
17102                     // later to get the correct resolved value
17103                     if (!canResolveLayoutDirection()) return false;
17104 
17105                     // Parent has not yet resolved, LTR is still the default
17106                     try {
17107                         if (!mParent.isLayoutDirectionResolved()) return false;
17108 
17109                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
17110                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17111                         }
17112                     } catch (AbstractMethodError e) {
17113                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17114                                 " does not fully implement ViewParent", e);
17115                     }
17116                     break;
17117                 case LAYOUT_DIRECTION_RTL:
17118                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17119                     break;
17120                 case LAYOUT_DIRECTION_LOCALE:
17121                     if((LAYOUT_DIRECTION_RTL ==
17122                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
17123                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17124                     }
17125                     break;
17126                 default:
17127                     // Nothing to do, LTR by default
17128             }
17129         }
17130 
17131         // Set to resolved
17132         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17133         return true;
17134     }
17135 
17136     /**
17137      * Check if layout direction resolution can be done.
17138      *
17139      * @return true if layout direction resolution can be done otherwise return false.
17140      */
17141     public boolean canResolveLayoutDirection() {
17142         switch (getRawLayoutDirection()) {
17143             case LAYOUT_DIRECTION_INHERIT:
17144                 if (mParent != null) {
17145                     try {
17146                         return mParent.canResolveLayoutDirection();
17147                     } catch (AbstractMethodError e) {
17148                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17149                                 " does not fully implement ViewParent", e);
17150                     }
17151                 }
17152                 return false;
17153 
17154             default:
17155                 return true;
17156         }
17157     }
17158 
17159     /**
17160      * Reset the resolved layout direction. Layout direction will be resolved during a call to
17161      * {@link #onMeasure(int, int)}.
17162      *
17163      * @hide
17164      */
17165     public void resetResolvedLayoutDirection() {
17166         // Reset the current resolved bits
17167         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17168     }
17169 
17170     /**
17171      * @return true if the layout direction is inherited.
17172      *
17173      * @hide
17174      */
17175     public boolean isLayoutDirectionInherited() {
17176         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
17177     }
17178 
17179     /**
17180      * @return true if layout direction has been resolved.
17181      */
17182     public boolean isLayoutDirectionResolved() {
17183         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17184     }
17185 
17186     /**
17187      * Return if padding has been resolved
17188      *
17189      * @hide
17190      */
17191     boolean isPaddingResolved() {
17192         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
17193     }
17194 
17195     /**
17196      * Resolves padding depending on layout direction, if applicable, and
17197      * recomputes internal padding values to adjust for scroll bars.
17198      *
17199      * @hide
17200      */
17201     public void resolvePadding() {
17202         final int resolvedLayoutDirection = getLayoutDirection();
17203 
17204         if (!isRtlCompatibilityMode()) {
17205             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
17206             // If start / end padding are defined, they will be resolved (hence overriding) to
17207             // left / right or right / left depending on the resolved layout direction.
17208             // If start / end padding are not defined, use the left / right ones.
17209             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
17210                 Rect padding = sThreadLocal.get();
17211                 if (padding == null) {
17212                     padding = new Rect();
17213                     sThreadLocal.set(padding);
17214                 }
17215                 mBackground.getPadding(padding);
17216                 if (!mLeftPaddingDefined) {
17217                     mUserPaddingLeftInitial = padding.left;
17218                 }
17219                 if (!mRightPaddingDefined) {
17220                     mUserPaddingRightInitial = padding.right;
17221                 }
17222             }
17223             switch (resolvedLayoutDirection) {
17224                 case LAYOUT_DIRECTION_RTL:
17225                     if (mUserPaddingStart != UNDEFINED_PADDING) {
17226                         mUserPaddingRight = mUserPaddingStart;
17227                     } else {
17228                         mUserPaddingRight = mUserPaddingRightInitial;
17229                     }
17230                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
17231                         mUserPaddingLeft = mUserPaddingEnd;
17232                     } else {
17233                         mUserPaddingLeft = mUserPaddingLeftInitial;
17234                     }
17235                     break;
17236                 case LAYOUT_DIRECTION_LTR:
17237                 default:
17238                     if (mUserPaddingStart != UNDEFINED_PADDING) {
17239                         mUserPaddingLeft = mUserPaddingStart;
17240                     } else {
17241                         mUserPaddingLeft = mUserPaddingLeftInitial;
17242                     }
17243                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
17244                         mUserPaddingRight = mUserPaddingEnd;
17245                     } else {
17246                         mUserPaddingRight = mUserPaddingRightInitial;
17247                     }
17248             }
17249 
17250             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
17251         }
17252 
17253         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
17254         onRtlPropertiesChanged(resolvedLayoutDirection);
17255 
17256         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
17257     }
17258 
17259     /**
17260      * Reset the resolved layout direction.
17261      *
17262      * @hide
17263      */
17264     public void resetResolvedPadding() {
17265         resetResolvedPaddingInternal();
17266     }
17267 
17268     /**
17269      * Used when we only want to reset *this* view's padding and not trigger overrides
17270      * in ViewGroup that reset children too.
17271      */
17272     void resetResolvedPaddingInternal() {
17273         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
17274     }
17275 
17276     /**
17277      * This is called when the view is detached from a window.  At this point it
17278      * no longer has a surface for drawing.
17279      *
17280      * @see #onAttachedToWindow()
17281      */
17282     @CallSuper
17283     protected void onDetachedFromWindow() {
17284     }
17285 
17286     /**
17287      * This is a framework-internal mirror of onDetachedFromWindow() that's called
17288      * after onDetachedFromWindow().
17289      *
17290      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
17291      * The super method should be called at the end of the overridden method to ensure
17292      * subclasses are destroyed first
17293      *
17294      * @hide
17295      */
17296     @CallSuper
17297     protected void onDetachedFromWindowInternal() {
17298         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
17299         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
17300         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
17301 
17302         removeUnsetPressCallback();
17303         removeLongPressCallback();
17304         removePerformClickCallback();
17305         removeSendViewScrolledAccessibilityEventCallback();
17306         stopNestedScroll();
17307 
17308         // Anything that started animating right before detach should already
17309         // be in its final state when re-attached.
17310         jumpDrawablesToCurrentState();
17311 
17312         destroyDrawingCache();
17313 
17314         cleanupDraw();
17315         mCurrentAnimation = null;
17316 
17317         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
17318             hideTooltip();
17319         }
17320     }
17321 
17322     private void cleanupDraw() {
17323         resetDisplayList();
17324         if (mAttachInfo != null) {
17325             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
17326         }
17327     }
17328 
17329     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
17330     }
17331 
17332     /**
17333      * @return The number of times this view has been attached to a window
17334      */
17335     protected int getWindowAttachCount() {
17336         return mWindowAttachCount;
17337     }
17338 
17339     /**
17340      * Retrieve a unique token identifying the window this view is attached to.
17341      * @return Return the window's token for use in
17342      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
17343      */
17344     public IBinder getWindowToken() {
17345         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
17346     }
17347 
17348     /**
17349      * Retrieve the {@link WindowId} for the window this view is
17350      * currently attached to.
17351      */
17352     public WindowId getWindowId() {
17353         if (mAttachInfo == null) {
17354             return null;
17355         }
17356         if (mAttachInfo.mWindowId == null) {
17357             try {
17358                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
17359                         mAttachInfo.mWindowToken);
17360                 mAttachInfo.mWindowId = new WindowId(
17361                         mAttachInfo.mIWindowId);
17362             } catch (RemoteException e) {
17363             }
17364         }
17365         return mAttachInfo.mWindowId;
17366     }
17367 
17368     /**
17369      * Retrieve a unique token identifying the top-level "real" window of
17370      * the window that this view is attached to.  That is, this is like
17371      * {@link #getWindowToken}, except if the window this view in is a panel
17372      * window (attached to another containing window), then the token of
17373      * the containing window is returned instead.
17374      *
17375      * @return Returns the associated window token, either
17376      * {@link #getWindowToken()} or the containing window's token.
17377      */
17378     public IBinder getApplicationWindowToken() {
17379         AttachInfo ai = mAttachInfo;
17380         if (ai != null) {
17381             IBinder appWindowToken = ai.mPanelParentWindowToken;
17382             if (appWindowToken == null) {
17383                 appWindowToken = ai.mWindowToken;
17384             }
17385             return appWindowToken;
17386         }
17387         return null;
17388     }
17389 
17390     /**
17391      * Gets the logical display to which the view's window has been attached.
17392      *
17393      * @return The logical display, or null if the view is not currently attached to a window.
17394      */
17395     public Display getDisplay() {
17396         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
17397     }
17398 
17399     /**
17400      * Retrieve private session object this view hierarchy is using to
17401      * communicate with the window manager.
17402      * @return the session object to communicate with the window manager
17403      */
17404     /*package*/ IWindowSession getWindowSession() {
17405         return mAttachInfo != null ? mAttachInfo.mSession : null;
17406     }
17407 
17408     /**
17409      * Return the visibility value of the least visible component passed.
17410      */
17411     int combineVisibility(int vis1, int vis2) {
17412         // This works because VISIBLE < INVISIBLE < GONE.
17413         return Math.max(vis1, vis2);
17414     }
17415 
17416     /**
17417      * @param info the {@link android.view.View.AttachInfo} to associated with
17418      *        this view
17419      */
17420     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
17421         mAttachInfo = info;
17422         if (mOverlay != null) {
17423             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
17424         }
17425         mWindowAttachCount++;
17426         // We will need to evaluate the drawable state at least once.
17427         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17428         if (mFloatingTreeObserver != null) {
17429             info.mTreeObserver.merge(mFloatingTreeObserver);
17430             mFloatingTreeObserver = null;
17431         }
17432 
17433         registerPendingFrameMetricsObservers();
17434 
17435         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
17436             mAttachInfo.mScrollContainers.add(this);
17437             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
17438         }
17439         // Transfer all pending runnables.
17440         if (mRunQueue != null) {
17441             mRunQueue.executeActions(info.mHandler);
17442             mRunQueue = null;
17443         }
17444         performCollectViewAttributes(mAttachInfo, visibility);
17445         onAttachedToWindow();
17446 
17447         ListenerInfo li = mListenerInfo;
17448         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17449                 li != null ? li.mOnAttachStateChangeListeners : null;
17450         if (listeners != null && listeners.size() > 0) {
17451             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17452             // perform the dispatching. The iterator is a safe guard against listeners that
17453             // could mutate the list by calling the various add/remove methods. This prevents
17454             // the array from being modified while we iterate it.
17455             for (OnAttachStateChangeListener listener : listeners) {
17456                 listener.onViewAttachedToWindow(this);
17457             }
17458         }
17459 
17460         int vis = info.mWindowVisibility;
17461         if (vis != GONE) {
17462             onWindowVisibilityChanged(vis);
17463             if (isShown()) {
17464                 // Calling onVisibilityAggregated directly here since the subtree will also
17465                 // receive dispatchAttachedToWindow and this same call
17466                 onVisibilityAggregated(vis == VISIBLE);
17467             }
17468         }
17469 
17470         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17471         // As all views in the subtree will already receive dispatchAttachedToWindow
17472         // traversing the subtree again here is not desired.
17473         onVisibilityChanged(this, visibility);
17474 
17475         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17476             // If nobody has evaluated the drawable state yet, then do it now.
17477             refreshDrawableState();
17478         }
17479         needGlobalAttributesUpdate(false);
17480 
17481         notifyEnterOrExitForAutoFillIfNeeded(true);
17482     }
17483 
17484     void dispatchDetachedFromWindow() {
17485         AttachInfo info = mAttachInfo;
17486         if (info != null) {
17487             int vis = info.mWindowVisibility;
17488             if (vis != GONE) {
17489                 onWindowVisibilityChanged(GONE);
17490                 if (isShown()) {
17491                     // Invoking onVisibilityAggregated directly here since the subtree
17492                     // will also receive detached from window
17493                     onVisibilityAggregated(false);
17494                 }
17495             }
17496         }
17497 
17498         onDetachedFromWindow();
17499         onDetachedFromWindowInternal();
17500 
17501         InputMethodManager imm = InputMethodManager.peekInstance();
17502         if (imm != null) {
17503             imm.onViewDetachedFromWindow(this);
17504         }
17505 
17506         ListenerInfo li = mListenerInfo;
17507         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17508                 li != null ? li.mOnAttachStateChangeListeners : null;
17509         if (listeners != null && listeners.size() > 0) {
17510             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17511             // perform the dispatching. The iterator is a safe guard against listeners that
17512             // could mutate the list by calling the various add/remove methods. This prevents
17513             // the array from being modified while we iterate it.
17514             for (OnAttachStateChangeListener listener : listeners) {
17515                 listener.onViewDetachedFromWindow(this);
17516             }
17517         }
17518 
17519         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17520             mAttachInfo.mScrollContainers.remove(this);
17521             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17522         }
17523 
17524         mAttachInfo = null;
17525         if (mOverlay != null) {
17526             mOverlay.getOverlayView().dispatchDetachedFromWindow();
17527         }
17528 
17529         notifyEnterOrExitForAutoFillIfNeeded(false);
17530     }
17531 
17532     /**
17533      * Cancel any deferred high-level input events that were previously posted to the event queue.
17534      *
17535      * <p>Many views post high-level events such as click handlers to the event queue
17536      * to run deferred in order to preserve a desired user experience - clearing visible
17537      * pressed states before executing, etc. This method will abort any events of this nature
17538      * that are currently in flight.</p>
17539      *
17540      * <p>Custom views that generate their own high-level deferred input events should override
17541      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17542      *
17543      * <p>This will also cancel pending input events for any child views.</p>
17544      *
17545      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17546      * This will not impact newer events posted after this call that may occur as a result of
17547      * lower-level input events still waiting in the queue. If you are trying to prevent
17548      * double-submitted  events for the duration of some sort of asynchronous transaction
17549      * you should also take other steps to protect against unexpected double inputs e.g. calling
17550      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17551      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17552      */
17553     public final void cancelPendingInputEvents() {
17554         dispatchCancelPendingInputEvents();
17555     }
17556 
17557     /**
17558      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17559      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17560      */
17561     void dispatchCancelPendingInputEvents() {
17562         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17563         onCancelPendingInputEvents();
17564         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17565             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17566                     " did not call through to super.onCancelPendingInputEvents()");
17567         }
17568     }
17569 
17570     /**
17571      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17572      * a parent view.
17573      *
17574      * <p>This method is responsible for removing any pending high-level input events that were
17575      * posted to the event queue to run later. Custom view classes that post their own deferred
17576      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17577      * {@link android.os.Handler} should override this method, call
17578      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17579      * </p>
17580      */
17581     public void onCancelPendingInputEvents() {
17582         removePerformClickCallback();
17583         cancelLongPress();
17584         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17585     }
17586 
17587     /**
17588      * Store this view hierarchy's frozen state into the given container.
17589      *
17590      * @param container The SparseArray in which to save the view's state.
17591      *
17592      * @see #restoreHierarchyState(android.util.SparseArray)
17593      * @see #dispatchSaveInstanceState(android.util.SparseArray)
17594      * @see #onSaveInstanceState()
17595      */
17596     public void saveHierarchyState(SparseArray<Parcelable> container) {
17597         dispatchSaveInstanceState(container);
17598     }
17599 
17600     /**
17601      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17602      * this view and its children. May be overridden to modify how freezing happens to a
17603      * view's children; for example, some views may want to not store state for their children.
17604      *
17605      * @param container The SparseArray in which to save the view's state.
17606      *
17607      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17608      * @see #saveHierarchyState(android.util.SparseArray)
17609      * @see #onSaveInstanceState()
17610      */
17611     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17612         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17613             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17614             Parcelable state = onSaveInstanceState();
17615             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17616                 throw new IllegalStateException(
17617                         "Derived class did not call super.onSaveInstanceState()");
17618             }
17619             if (state != null) {
17620                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17621                 // + ": " + state);
17622                 container.put(mID, state);
17623             }
17624         }
17625     }
17626 
17627     /**
17628      * Hook allowing a view to generate a representation of its internal state
17629      * that can later be used to create a new instance with that same state.
17630      * This state should only contain information that is not persistent or can
17631      * not be reconstructed later. For example, you will never store your
17632      * current position on screen because that will be computed again when a
17633      * new instance of the view is placed in its view hierarchy.
17634      * <p>
17635      * Some examples of things you may store here: the current cursor position
17636      * in a text view (but usually not the text itself since that is stored in a
17637      * content provider or other persistent storage), the currently selected
17638      * item in a list view.
17639      *
17640      * @return Returns a Parcelable object containing the view's current dynamic
17641      *         state, or null if there is nothing interesting to save.
17642      * @see #onRestoreInstanceState(Parcelable)
17643      * @see #saveHierarchyState(SparseArray)
17644      * @see #dispatchSaveInstanceState(SparseArray)
17645      * @see #setSaveEnabled(boolean)
17646      */
17647     @CallSuper
17648     @Nullable protected Parcelable onSaveInstanceState() {
17649         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17650         if (mStartActivityRequestWho != null || isAutofilled()
17651                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17652             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17653 
17654             if (mStartActivityRequestWho != null) {
17655                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17656             }
17657 
17658             if (isAutofilled()) {
17659                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17660             }
17661 
17662             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17663                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
17664             }
17665 
17666             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17667             state.mIsAutofilled = isAutofilled();
17668             state.mAutofillViewId = mAutofillViewId;
17669             return state;
17670         }
17671         return BaseSavedState.EMPTY_STATE;
17672     }
17673 
17674     /**
17675      * Restore this view hierarchy's frozen state from the given container.
17676      *
17677      * @param container The SparseArray which holds previously frozen states.
17678      *
17679      * @see #saveHierarchyState(android.util.SparseArray)
17680      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17681      * @see #onRestoreInstanceState(android.os.Parcelable)
17682      */
17683     public void restoreHierarchyState(SparseArray<Parcelable> container) {
17684         dispatchRestoreInstanceState(container);
17685     }
17686 
17687     /**
17688      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17689      * state for this view and its children. May be overridden to modify how restoring
17690      * happens to a view's children; for example, some views may want to not store state
17691      * for their children.
17692      *
17693      * @param container The SparseArray which holds previously saved state.
17694      *
17695      * @see #dispatchSaveInstanceState(android.util.SparseArray)
17696      * @see #restoreHierarchyState(android.util.SparseArray)
17697      * @see #onRestoreInstanceState(android.os.Parcelable)
17698      */
17699     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17700         if (mID != NO_ID) {
17701             Parcelable state = container.get(mID);
17702             if (state != null) {
17703                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17704                 // + ": " + state);
17705                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17706                 onRestoreInstanceState(state);
17707                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17708                     throw new IllegalStateException(
17709                             "Derived class did not call super.onRestoreInstanceState()");
17710                 }
17711             }
17712         }
17713     }
17714 
17715     /**
17716      * Hook allowing a view to re-apply a representation of its internal state that had previously
17717      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17718      * null state.
17719      *
17720      * @param state The frozen state that had previously been returned by
17721      *        {@link #onSaveInstanceState}.
17722      *
17723      * @see #onSaveInstanceState()
17724      * @see #restoreHierarchyState(android.util.SparseArray)
17725      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17726      */
17727     @CallSuper
17728     protected void onRestoreInstanceState(Parcelable state) {
17729         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17730         if (state != null && !(state instanceof AbsSavedState)) {
17731             throw new IllegalArgumentException("Wrong state class, expecting View State but "
17732                     + "received " + state.getClass().toString() + " instead. This usually happens "
17733                     + "when two views of different type have the same id in the same hierarchy. "
17734                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17735                     + "other views do not use the same id.");
17736         }
17737         if (state != null && state instanceof BaseSavedState) {
17738             BaseSavedState baseState = (BaseSavedState) state;
17739 
17740             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17741                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17742             }
17743             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17744                 setAutofilled(baseState.mIsAutofilled);
17745             }
17746             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
17747                 // It can happen that views have the same view id and the restoration path will not
17748                 // be able to distinguish between them. The autofill id needs to be unique though.
17749                 // Hence prevent the same autofill view id from being restored multiple times.
17750                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
17751 
17752                 mAutofillViewId = baseState.mAutofillViewId;
17753             }
17754         }
17755     }
17756 
17757     /**
17758      * <p>Return the time at which the drawing of the view hierarchy started.</p>
17759      *
17760      * @return the drawing start time in milliseconds
17761      */
17762     public long getDrawingTime() {
17763         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17764     }
17765 
17766     /**
17767      * <p>Enables or disables the duplication of the parent's state into this view. When
17768      * duplication is enabled, this view gets its drawable state from its parent rather
17769      * than from its own internal properties.</p>
17770      *
17771      * <p>Note: in the current implementation, setting this property to true after the
17772      * view was added to a ViewGroup might have no effect at all. This property should
17773      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17774      *
17775      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17776      * property is enabled, an exception will be thrown.</p>
17777      *
17778      * <p>Note: if the child view uses and updates additional states which are unknown to the
17779      * parent, these states should not be affected by this method.</p>
17780      *
17781      * @param enabled True to enable duplication of the parent's drawable state, false
17782      *                to disable it.
17783      *
17784      * @see #getDrawableState()
17785      * @see #isDuplicateParentStateEnabled()
17786      */
17787     public void setDuplicateParentStateEnabled(boolean enabled) {
17788         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17789     }
17790 
17791     /**
17792      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17793      *
17794      * @return True if this view's drawable state is duplicated from the parent,
17795      *         false otherwise
17796      *
17797      * @see #getDrawableState()
17798      * @see #setDuplicateParentStateEnabled(boolean)
17799      */
17800     public boolean isDuplicateParentStateEnabled() {
17801         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17802     }
17803 
17804     /**
17805      * <p>Specifies the type of layer backing this view. The layer can be
17806      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17807      * {@link #LAYER_TYPE_HARDWARE}.</p>
17808      *
17809      * <p>A layer is associated with an optional {@link android.graphics.Paint}
17810      * instance that controls how the layer is composed on screen. The following
17811      * properties of the paint are taken into account when composing the layer:</p>
17812      * <ul>
17813      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17814      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17815      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17816      * </ul>
17817      *
17818      * <p>If this view has an alpha value set to < 1.0 by calling
17819      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17820      * by this view's alpha value.</p>
17821      *
17822      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17823      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17824      * for more information on when and how to use layers.</p>
17825      *
17826      * @param layerType The type of layer to use with this view, must be one of
17827      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17828      *        {@link #LAYER_TYPE_HARDWARE}
17829      * @param paint The paint used to compose the layer. This argument is optional
17830      *        and can be null. It is ignored when the layer type is
17831      *        {@link #LAYER_TYPE_NONE}
17832      *
17833      * @see #getLayerType()
17834      * @see #LAYER_TYPE_NONE
17835      * @see #LAYER_TYPE_SOFTWARE
17836      * @see #LAYER_TYPE_HARDWARE
17837      * @see #setAlpha(float)
17838      *
17839      * @attr ref android.R.styleable#View_layerType
17840      */
17841     public void setLayerType(int layerType, @Nullable Paint paint) {
17842         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17843             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17844                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17845         }
17846 
17847         boolean typeChanged = mRenderNode.setLayerType(layerType);
17848 
17849         if (!typeChanged) {
17850             setLayerPaint(paint);
17851             return;
17852         }
17853 
17854         if (layerType != LAYER_TYPE_SOFTWARE) {
17855             // Destroy any previous software drawing cache if present
17856             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17857             // drawing cache created in View#draw when drawing to a SW canvas.
17858             destroyDrawingCache();
17859         }
17860 
17861         mLayerType = layerType;
17862         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17863         mRenderNode.setLayerPaint(mLayerPaint);
17864 
17865         // draw() behaves differently if we are on a layer, so we need to
17866         // invalidate() here
17867         invalidateParentCaches();
17868         invalidate(true);
17869     }
17870 
17871     /**
17872      * Updates the {@link Paint} object used with the current layer (used only if the current
17873      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17874      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17875      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17876      * ensure that the view gets redrawn immediately.
17877      *
17878      * <p>A layer is associated with an optional {@link android.graphics.Paint}
17879      * instance that controls how the layer is composed on screen. The following
17880      * properties of the paint are taken into account when composing the layer:</p>
17881      * <ul>
17882      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17883      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17884      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17885      * </ul>
17886      *
17887      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17888      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17889      *
17890      * @param paint The paint used to compose the layer. This argument is optional
17891      *        and can be null. It is ignored when the layer type is
17892      *        {@link #LAYER_TYPE_NONE}
17893      *
17894      * @see #setLayerType(int, android.graphics.Paint)
17895      */
17896     public void setLayerPaint(@Nullable Paint paint) {
17897         int layerType = getLayerType();
17898         if (layerType != LAYER_TYPE_NONE) {
17899             mLayerPaint = paint;
17900             if (layerType == LAYER_TYPE_HARDWARE) {
17901                 if (mRenderNode.setLayerPaint(paint)) {
17902                     invalidateViewProperty(false, false);
17903                 }
17904             } else {
17905                 invalidate();
17906             }
17907         }
17908     }
17909 
17910     /**
17911      * Indicates what type of layer is currently associated with this view. By default
17912      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17913      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17914      * for more information on the different types of layers.
17915      *
17916      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17917      *         {@link #LAYER_TYPE_HARDWARE}
17918      *
17919      * @see #setLayerType(int, android.graphics.Paint)
17920      * @see #buildLayer()
17921      * @see #LAYER_TYPE_NONE
17922      * @see #LAYER_TYPE_SOFTWARE
17923      * @see #LAYER_TYPE_HARDWARE
17924      */
17925     public int getLayerType() {
17926         return mLayerType;
17927     }
17928 
17929     /**
17930      * Forces this view's layer to be created and this view to be rendered
17931      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17932      * invoking this method will have no effect.
17933      *
17934      * This method can for instance be used to render a view into its layer before
17935      * starting an animation. If this view is complex, rendering into the layer
17936      * before starting the animation will avoid skipping frames.
17937      *
17938      * @throws IllegalStateException If this view is not attached to a window
17939      *
17940      * @see #setLayerType(int, android.graphics.Paint)
17941      */
17942     public void buildLayer() {
17943         if (mLayerType == LAYER_TYPE_NONE) return;
17944 
17945         final AttachInfo attachInfo = mAttachInfo;
17946         if (attachInfo == null) {
17947             throw new IllegalStateException("This view must be attached to a window first");
17948         }
17949 
17950         if (getWidth() == 0 || getHeight() == 0) {
17951             return;
17952         }
17953 
17954         switch (mLayerType) {
17955             case LAYER_TYPE_HARDWARE:
17956                 updateDisplayListIfDirty();
17957                 if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17958                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17959                 }
17960                 break;
17961             case LAYER_TYPE_SOFTWARE:
17962                 buildDrawingCache(true);
17963                 break;
17964         }
17965     }
17966 
17967     /**
17968      * Destroys all hardware rendering resources. This method is invoked
17969      * when the system needs to reclaim resources. Upon execution of this
17970      * method, you should free any OpenGL resources created by the view.
17971      *
17972      * Note: you <strong>must</strong> call
17973      * <code>super.destroyHardwareResources()</code> when overriding
17974      * this method.
17975      *
17976      * @hide
17977      */
17978     @CallSuper
17979     protected void destroyHardwareResources() {
17980         if (mOverlay != null) {
17981             mOverlay.getOverlayView().destroyHardwareResources();
17982         }
17983         if (mGhostView != null) {
17984             mGhostView.destroyHardwareResources();
17985         }
17986     }
17987 
17988     /**
17989      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17990      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17991      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17992      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17993      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17994      * null.</p>
17995      *
17996      * <p>Enabling the drawing cache is similar to
17997      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17998      * acceleration is turned off. When hardware acceleration is turned on, enabling the
17999      * drawing cache has no effect on rendering because the system uses a different mechanism
18000      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
18001      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
18002      * for information on how to enable software and hardware layers.</p>
18003      *
18004      * <p>This API can be used to manually generate
18005      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
18006      * {@link #getDrawingCache()}.</p>
18007      *
18008      * @param enabled true to enable the drawing cache, false otherwise
18009      *
18010      * @see #isDrawingCacheEnabled()
18011      * @see #getDrawingCache()
18012      * @see #buildDrawingCache()
18013      * @see #setLayerType(int, android.graphics.Paint)
18014      */
18015     public void setDrawingCacheEnabled(boolean enabled) {
18016         mCachingFailed = false;
18017         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
18018     }
18019 
18020     /**
18021      * <p>Indicates whether the drawing cache is enabled for this view.</p>
18022      *
18023      * @return true if the drawing cache is enabled
18024      *
18025      * @see #setDrawingCacheEnabled(boolean)
18026      * @see #getDrawingCache()
18027      */
18028     @ViewDebug.ExportedProperty(category = "drawing")
18029     public boolean isDrawingCacheEnabled() {
18030         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
18031     }
18032 
18033     /**
18034      * Debugging utility which recursively outputs the dirty state of a view and its
18035      * descendants.
18036      *
18037      * @hide
18038      */
18039     @SuppressWarnings({"UnusedDeclaration"})
18040     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
18041         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
18042                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
18043                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
18044                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
18045         if (clear) {
18046             mPrivateFlags &= clearMask;
18047         }
18048         if (this instanceof ViewGroup) {
18049             ViewGroup parent = (ViewGroup) this;
18050             final int count = parent.getChildCount();
18051             for (int i = 0; i < count; i++) {
18052                 final View child = parent.getChildAt(i);
18053                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
18054             }
18055         }
18056     }
18057 
18058     /**
18059      * This method is used by ViewGroup to cause its children to restore or recreate their
18060      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
18061      * to recreate its own display list, which would happen if it went through the normal
18062      * draw/dispatchDraw mechanisms.
18063      *
18064      * @hide
18065      */
18066     protected void dispatchGetDisplayList() {}
18067 
18068     /**
18069      * A view that is not attached or hardware accelerated cannot create a display list.
18070      * This method checks these conditions and returns the appropriate result.
18071      *
18072      * @return true if view has the ability to create a display list, false otherwise.
18073      *
18074      * @hide
18075      */
18076     public boolean canHaveDisplayList() {
18077         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
18078     }
18079 
18080     /**
18081      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
18082      * @hide
18083      */
18084     @NonNull
18085     public RenderNode updateDisplayListIfDirty() {
18086         final RenderNode renderNode = mRenderNode;
18087         if (!canHaveDisplayList()) {
18088             // can't populate RenderNode, don't try
18089             return renderNode;
18090         }
18091 
18092         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
18093                 || !renderNode.isValid()
18094                 || (mRecreateDisplayList)) {
18095             // Don't need to recreate the display list, just need to tell our
18096             // children to restore/recreate theirs
18097             if (renderNode.isValid()
18098                     && !mRecreateDisplayList) {
18099                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18100                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18101                 dispatchGetDisplayList();
18102 
18103                 return renderNode; // no work needed
18104             }
18105 
18106             // If we got here, we're recreating it. Mark it as such to ensure that
18107             // we copy in child display lists into ours in drawChild()
18108             mRecreateDisplayList = true;
18109 
18110             int width = mRight - mLeft;
18111             int height = mBottom - mTop;
18112             int layerType = getLayerType();
18113 
18114             final DisplayListCanvas canvas = renderNode.start(width, height);
18115             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
18116 
18117             try {
18118                 if (layerType == LAYER_TYPE_SOFTWARE) {
18119                     buildDrawingCache(true);
18120                     Bitmap cache = getDrawingCache(true);
18121                     if (cache != null) {
18122                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
18123                     }
18124                 } else {
18125                     computeScroll();
18126 
18127                     canvas.translate(-mScrollX, -mScrollY);
18128                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18129                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18130 
18131                     // Fast path for layouts with no backgrounds
18132                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18133                         dispatchDraw(canvas);
18134                         drawAutofilledHighlight(canvas);
18135                         if (mOverlay != null && !mOverlay.isEmpty()) {
18136                             mOverlay.getOverlayView().draw(canvas);
18137                         }
18138                         if (debugDraw()) {
18139                             debugDrawFocus(canvas);
18140                         }
18141                     } else {
18142                         draw(canvas);
18143                     }
18144                 }
18145             } finally {
18146                 renderNode.end(canvas);
18147                 setDisplayListProperties(renderNode);
18148             }
18149         } else {
18150             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18151             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18152         }
18153         return renderNode;
18154     }
18155 
18156     private void resetDisplayList() {
18157         mRenderNode.discardDisplayList();
18158         if (mBackgroundRenderNode != null) {
18159             mBackgroundRenderNode.discardDisplayList();
18160         }
18161     }
18162 
18163     /**
18164      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
18165      *
18166      * @return A non-scaled bitmap representing this view or null if cache is disabled.
18167      *
18168      * @see #getDrawingCache(boolean)
18169      */
18170     public Bitmap getDrawingCache() {
18171         return getDrawingCache(false);
18172     }
18173 
18174     /**
18175      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
18176      * is null when caching is disabled. If caching is enabled and the cache is not ready,
18177      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
18178      * draw from the cache when the cache is enabled. To benefit from the cache, you must
18179      * request the drawing cache by calling this method and draw it on screen if the
18180      * returned bitmap is not null.</p>
18181      *
18182      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18183      * this method will create a bitmap of the same size as this view. Because this bitmap
18184      * will be drawn scaled by the parent ViewGroup, the result on screen might show
18185      * scaling artifacts. To avoid such artifacts, you should call this method by setting
18186      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18187      * size than the view. This implies that your application must be able to handle this
18188      * size.</p>
18189      *
18190      * @param autoScale Indicates whether the generated bitmap should be scaled based on
18191      *        the current density of the screen when the application is in compatibility
18192      *        mode.
18193      *
18194      * @return A bitmap representing this view or null if cache is disabled.
18195      *
18196      * @see #setDrawingCacheEnabled(boolean)
18197      * @see #isDrawingCacheEnabled()
18198      * @see #buildDrawingCache(boolean)
18199      * @see #destroyDrawingCache()
18200      */
18201     public Bitmap getDrawingCache(boolean autoScale) {
18202         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
18203             return null;
18204         }
18205         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
18206             buildDrawingCache(autoScale);
18207         }
18208         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
18209     }
18210 
18211     /**
18212      * <p>Frees the resources used by the drawing cache. If you call
18213      * {@link #buildDrawingCache()} manually without calling
18214      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18215      * should cleanup the cache with this method afterwards.</p>
18216      *
18217      * @see #setDrawingCacheEnabled(boolean)
18218      * @see #buildDrawingCache()
18219      * @see #getDrawingCache()
18220      */
18221     public void destroyDrawingCache() {
18222         if (mDrawingCache != null) {
18223             mDrawingCache.recycle();
18224             mDrawingCache = null;
18225         }
18226         if (mUnscaledDrawingCache != null) {
18227             mUnscaledDrawingCache.recycle();
18228             mUnscaledDrawingCache = null;
18229         }
18230     }
18231 
18232     /**
18233      * Setting a solid background color for the drawing cache's bitmaps will improve
18234      * performance and memory usage. Note, though that this should only be used if this
18235      * view will always be drawn on top of a solid color.
18236      *
18237      * @param color The background color to use for the drawing cache's bitmap
18238      *
18239      * @see #setDrawingCacheEnabled(boolean)
18240      * @see #buildDrawingCache()
18241      * @see #getDrawingCache()
18242      */
18243     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
18244         if (color != mDrawingCacheBackgroundColor) {
18245             mDrawingCacheBackgroundColor = color;
18246             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18247         }
18248     }
18249 
18250     /**
18251      * @see #setDrawingCacheBackgroundColor(int)
18252      *
18253      * @return The background color to used for the drawing cache's bitmap
18254      */
18255     @ColorInt
18256     public int getDrawingCacheBackgroundColor() {
18257         return mDrawingCacheBackgroundColor;
18258     }
18259 
18260     /**
18261      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
18262      *
18263      * @see #buildDrawingCache(boolean)
18264      */
18265     public void buildDrawingCache() {
18266         buildDrawingCache(false);
18267     }
18268 
18269     /**
18270      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
18271      *
18272      * <p>If you call {@link #buildDrawingCache()} manually without calling
18273      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18274      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
18275      *
18276      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18277      * this method will create a bitmap of the same size as this view. Because this bitmap
18278      * will be drawn scaled by the parent ViewGroup, the result on screen might show
18279      * scaling artifacts. To avoid such artifacts, you should call this method by setting
18280      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18281      * size than the view. This implies that your application must be able to handle this
18282      * size.</p>
18283      *
18284      * <p>You should avoid calling this method when hardware acceleration is enabled. If
18285      * you do not need the drawing cache bitmap, calling this method will increase memory
18286      * usage and cause the view to be rendered in software once, thus negatively impacting
18287      * performance.</p>
18288      *
18289      * @see #getDrawingCache()
18290      * @see #destroyDrawingCache()
18291      */
18292     public void buildDrawingCache(boolean autoScale) {
18293         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
18294                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
18295             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
18296                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
18297                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
18298             }
18299             try {
18300                 buildDrawingCacheImpl(autoScale);
18301             } finally {
18302                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
18303             }
18304         }
18305     }
18306 
18307     /**
18308      * private, internal implementation of buildDrawingCache, used to enable tracing
18309      */
18310     private void buildDrawingCacheImpl(boolean autoScale) {
18311         mCachingFailed = false;
18312 
18313         int width = mRight - mLeft;
18314         int height = mBottom - mTop;
18315 
18316         final AttachInfo attachInfo = mAttachInfo;
18317         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
18318 
18319         if (autoScale && scalingRequired) {
18320             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
18321             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
18322         }
18323 
18324         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
18325         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
18326         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
18327 
18328         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
18329         final long drawingCacheSize =
18330                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
18331         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
18332             if (width > 0 && height > 0) {
18333                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
18334                         + " too large to fit into a software layer (or drawing cache), needs "
18335                         + projectedBitmapSize + " bytes, only "
18336                         + drawingCacheSize + " available");
18337             }
18338             destroyDrawingCache();
18339             mCachingFailed = true;
18340             return;
18341         }
18342 
18343         boolean clear = true;
18344         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
18345 
18346         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
18347             Bitmap.Config quality;
18348             if (!opaque) {
18349                 // Never pick ARGB_4444 because it looks awful
18350                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
18351                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
18352                     case DRAWING_CACHE_QUALITY_AUTO:
18353                     case DRAWING_CACHE_QUALITY_LOW:
18354                     case DRAWING_CACHE_QUALITY_HIGH:
18355                     default:
18356                         quality = Bitmap.Config.ARGB_8888;
18357                         break;
18358                 }
18359             } else {
18360                 // Optimization for translucent windows
18361                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
18362                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
18363             }
18364 
18365             // Try to cleanup memory
18366             if (bitmap != null) bitmap.recycle();
18367 
18368             try {
18369                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18370                         width, height, quality);
18371                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
18372                 if (autoScale) {
18373                     mDrawingCache = bitmap;
18374                 } else {
18375                     mUnscaledDrawingCache = bitmap;
18376                 }
18377                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
18378             } catch (OutOfMemoryError e) {
18379                 // If there is not enough memory to create the bitmap cache, just
18380                 // ignore the issue as bitmap caches are not required to draw the
18381                 // view hierarchy
18382                 if (autoScale) {
18383                     mDrawingCache = null;
18384                 } else {
18385                     mUnscaledDrawingCache = null;
18386                 }
18387                 mCachingFailed = true;
18388                 return;
18389             }
18390 
18391             clear = drawingCacheBackgroundColor != 0;
18392         }
18393 
18394         Canvas canvas;
18395         if (attachInfo != null) {
18396             canvas = attachInfo.mCanvas;
18397             if (canvas == null) {
18398                 canvas = new Canvas();
18399             }
18400             canvas.setBitmap(bitmap);
18401             // Temporarily clobber the cached Canvas in case one of our children
18402             // is also using a drawing cache. Without this, the children would
18403             // steal the canvas by attaching their own bitmap to it and bad, bad
18404             // thing would happen (invisible views, corrupted drawings, etc.)
18405             attachInfo.mCanvas = null;
18406         } else {
18407             // This case should hopefully never or seldom happen
18408             canvas = new Canvas(bitmap);
18409         }
18410 
18411         if (clear) {
18412             bitmap.eraseColor(drawingCacheBackgroundColor);
18413         }
18414 
18415         computeScroll();
18416         final int restoreCount = canvas.save();
18417 
18418         if (autoScale && scalingRequired) {
18419             final float scale = attachInfo.mApplicationScale;
18420             canvas.scale(scale, scale);
18421         }
18422 
18423         canvas.translate(-mScrollX, -mScrollY);
18424 
18425         mPrivateFlags |= PFLAG_DRAWN;
18426         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
18427                 mLayerType != LAYER_TYPE_NONE) {
18428             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
18429         }
18430 
18431         // Fast path for layouts with no backgrounds
18432         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18433             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18434             dispatchDraw(canvas);
18435             drawAutofilledHighlight(canvas);
18436             if (mOverlay != null && !mOverlay.isEmpty()) {
18437                 mOverlay.getOverlayView().draw(canvas);
18438             }
18439         } else {
18440             draw(canvas);
18441         }
18442 
18443         canvas.restoreToCount(restoreCount);
18444         canvas.setBitmap(null);
18445 
18446         if (attachInfo != null) {
18447             // Restore the cached Canvas for our siblings
18448             attachInfo.mCanvas = canvas;
18449         }
18450     }
18451 
18452     /**
18453      * Create a snapshot of the view into a bitmap.  We should probably make
18454      * some form of this public, but should think about the API.
18455      *
18456      * @hide
18457      */
18458     public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18459         int width = mRight - mLeft;
18460         int height = mBottom - mTop;
18461 
18462         final AttachInfo attachInfo = mAttachInfo;
18463         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18464         width = (int) ((width * scale) + 0.5f);
18465         height = (int) ((height * scale) + 0.5f);
18466 
18467         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18468                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
18469         if (bitmap == null) {
18470             throw new OutOfMemoryError();
18471         }
18472 
18473         Resources resources = getResources();
18474         if (resources != null) {
18475             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18476         }
18477 
18478         Canvas canvas;
18479         if (attachInfo != null) {
18480             canvas = attachInfo.mCanvas;
18481             if (canvas == null) {
18482                 canvas = new Canvas();
18483             }
18484             canvas.setBitmap(bitmap);
18485             // Temporarily clobber the cached Canvas in case one of our children
18486             // is also using a drawing cache. Without this, the children would
18487             // steal the canvas by attaching their own bitmap to it and bad, bad
18488             // things would happen (invisible views, corrupted drawings, etc.)
18489             attachInfo.mCanvas = null;
18490         } else {
18491             // This case should hopefully never or seldom happen
18492             canvas = new Canvas(bitmap);
18493         }
18494         boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18495         canvas.setHwBitmapsInSwModeEnabled(true);
18496         if ((backgroundColor & 0xff000000) != 0) {
18497             bitmap.eraseColor(backgroundColor);
18498         }
18499 
18500         computeScroll();
18501         final int restoreCount = canvas.save();
18502         canvas.scale(scale, scale);
18503         canvas.translate(-mScrollX, -mScrollY);
18504 
18505         // Temporarily remove the dirty mask
18506         int flags = mPrivateFlags;
18507         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18508 
18509         // Fast path for layouts with no backgrounds
18510         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18511             dispatchDraw(canvas);
18512             drawAutofilledHighlight(canvas);
18513             if (mOverlay != null && !mOverlay.isEmpty()) {
18514                 mOverlay.getOverlayView().draw(canvas);
18515             }
18516         } else {
18517             draw(canvas);
18518         }
18519 
18520         mPrivateFlags = flags;
18521 
18522         canvas.restoreToCount(restoreCount);
18523         canvas.setBitmap(null);
18524         canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18525 
18526         if (attachInfo != null) {
18527             // Restore the cached Canvas for our siblings
18528             attachInfo.mCanvas = canvas;
18529         }
18530 
18531         return bitmap;
18532     }
18533 
18534     /**
18535      * Indicates whether this View is currently in edit mode. A View is usually
18536      * in edit mode when displayed within a developer tool. For instance, if
18537      * this View is being drawn by a visual user interface builder, this method
18538      * should return true.
18539      *
18540      * Subclasses should check the return value of this method to provide
18541      * different behaviors if their normal behavior might interfere with the
18542      * host environment. For instance: the class spawns a thread in its
18543      * constructor, the drawing code relies on device-specific features, etc.
18544      *
18545      * This method is usually checked in the drawing code of custom widgets.
18546      *
18547      * @return True if this View is in edit mode, false otherwise.
18548      */
18549     public boolean isInEditMode() {
18550         return false;
18551     }
18552 
18553     /**
18554      * If the View draws content inside its padding and enables fading edges,
18555      * it needs to support padding offsets. Padding offsets are added to the
18556      * fading edges to extend the length of the fade so that it covers pixels
18557      * drawn inside the padding.
18558      *
18559      * Subclasses of this class should override this method if they need
18560      * to draw content inside the padding.
18561      *
18562      * @return True if padding offset must be applied, false otherwise.
18563      *
18564      * @see #getLeftPaddingOffset()
18565      * @see #getRightPaddingOffset()
18566      * @see #getTopPaddingOffset()
18567      * @see #getBottomPaddingOffset()
18568      *
18569      * @since CURRENT
18570      */
18571     protected boolean isPaddingOffsetRequired() {
18572         return false;
18573     }
18574 
18575     /**
18576      * Amount by which to extend the left fading region. Called only when
18577      * {@link #isPaddingOffsetRequired()} returns true.
18578      *
18579      * @return The left padding offset in pixels.
18580      *
18581      * @see #isPaddingOffsetRequired()
18582      *
18583      * @since CURRENT
18584      */
18585     protected int getLeftPaddingOffset() {
18586         return 0;
18587     }
18588 
18589     /**
18590      * Amount by which to extend the right fading region. Called only when
18591      * {@link #isPaddingOffsetRequired()} returns true.
18592      *
18593      * @return The right padding offset in pixels.
18594      *
18595      * @see #isPaddingOffsetRequired()
18596      *
18597      * @since CURRENT
18598      */
18599     protected int getRightPaddingOffset() {
18600         return 0;
18601     }
18602 
18603     /**
18604      * Amount by which to extend the top fading region. Called only when
18605      * {@link #isPaddingOffsetRequired()} returns true.
18606      *
18607      * @return The top padding offset in pixels.
18608      *
18609      * @see #isPaddingOffsetRequired()
18610      *
18611      * @since CURRENT
18612      */
18613     protected int getTopPaddingOffset() {
18614         return 0;
18615     }
18616 
18617     /**
18618      * Amount by which to extend the bottom fading region. Called only when
18619      * {@link #isPaddingOffsetRequired()} returns true.
18620      *
18621      * @return The bottom padding offset in pixels.
18622      *
18623      * @see #isPaddingOffsetRequired()
18624      *
18625      * @since CURRENT
18626      */
18627     protected int getBottomPaddingOffset() {
18628         return 0;
18629     }
18630 
18631     /**
18632      * @hide
18633      * @param offsetRequired
18634      */
18635     protected int getFadeTop(boolean offsetRequired) {
18636         int top = mPaddingTop;
18637         if (offsetRequired) top += getTopPaddingOffset();
18638         return top;
18639     }
18640 
18641     /**
18642      * @hide
18643      * @param offsetRequired
18644      */
18645     protected int getFadeHeight(boolean offsetRequired) {
18646         int padding = mPaddingTop;
18647         if (offsetRequired) padding += getTopPaddingOffset();
18648         return mBottom - mTop - mPaddingBottom - padding;
18649     }
18650 
18651     /**
18652      * <p>Indicates whether this view is attached to a hardware accelerated
18653      * window or not.</p>
18654      *
18655      * <p>Even if this method returns true, it does not mean that every call
18656      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18657      * accelerated {@link android.graphics.Canvas}. For instance, if this view
18658      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18659      * window is hardware accelerated,
18660      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18661      * return false, and this method will return true.</p>
18662      *
18663      * @return True if the view is attached to a window and the window is
18664      *         hardware accelerated; false in any other case.
18665      */
18666     @ViewDebug.ExportedProperty(category = "drawing")
18667     public boolean isHardwareAccelerated() {
18668         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18669     }
18670 
18671     /**
18672      * Sets a rectangular area on this view to which the view will be clipped
18673      * when it is drawn. Setting the value to null will remove the clip bounds
18674      * and the view will draw normally, using its full bounds.
18675      *
18676      * @param clipBounds The rectangular area, in the local coordinates of
18677      * this view, to which future drawing operations will be clipped.
18678      */
18679     public void setClipBounds(Rect clipBounds) {
18680         if (clipBounds == mClipBounds
18681                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18682             return;
18683         }
18684         if (clipBounds != null) {
18685             if (mClipBounds == null) {
18686                 mClipBounds = new Rect(clipBounds);
18687             } else {
18688                 mClipBounds.set(clipBounds);
18689             }
18690         } else {
18691             mClipBounds = null;
18692         }
18693         mRenderNode.setClipBounds(mClipBounds);
18694         invalidateViewProperty(false, false);
18695     }
18696 
18697     /**
18698      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18699      *
18700      * @return A copy of the current clip bounds if clip bounds are set,
18701      * otherwise null.
18702      */
18703     public Rect getClipBounds() {
18704         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18705     }
18706 
18707 
18708     /**
18709      * Populates an output rectangle with the clip bounds of the view,
18710      * returning {@code true} if successful or {@code false} if the view's
18711      * clip bounds are {@code null}.
18712      *
18713      * @param outRect rectangle in which to place the clip bounds of the view
18714      * @return {@code true} if successful or {@code false} if the view's
18715      *         clip bounds are {@code null}
18716      */
18717     public boolean getClipBounds(Rect outRect) {
18718         if (mClipBounds != null) {
18719             outRect.set(mClipBounds);
18720             return true;
18721         }
18722         return false;
18723     }
18724 
18725     /**
18726      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18727      * case of an active Animation being run on the view.
18728      */
18729     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18730             Animation a, boolean scalingRequired) {
18731         Transformation invalidationTransform;
18732         final int flags = parent.mGroupFlags;
18733         final boolean initialized = a.isInitialized();
18734         if (!initialized) {
18735             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18736             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18737             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18738             onAnimationStart();
18739         }
18740 
18741         final Transformation t = parent.getChildTransformation();
18742         boolean more = a.getTransformation(drawingTime, t, 1f);
18743         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18744             if (parent.mInvalidationTransformation == null) {
18745                 parent.mInvalidationTransformation = new Transformation();
18746             }
18747             invalidationTransform = parent.mInvalidationTransformation;
18748             a.getTransformation(drawingTime, invalidationTransform, 1f);
18749         } else {
18750             invalidationTransform = t;
18751         }
18752 
18753         if (more) {
18754             if (!a.willChangeBounds()) {
18755                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18756                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18757                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18758                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18759                     // The child need to draw an animation, potentially offscreen, so
18760                     // make sure we do not cancel invalidate requests
18761                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18762                     parent.invalidate(mLeft, mTop, mRight, mBottom);
18763                 }
18764             } else {
18765                 if (parent.mInvalidateRegion == null) {
18766                     parent.mInvalidateRegion = new RectF();
18767                 }
18768                 final RectF region = parent.mInvalidateRegion;
18769                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18770                         invalidationTransform);
18771 
18772                 // The child need to draw an animation, potentially offscreen, so
18773                 // make sure we do not cancel invalidate requests
18774                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18775 
18776                 final int left = mLeft + (int) region.left;
18777                 final int top = mTop + (int) region.top;
18778                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
18779                         top + (int) (region.height() + .5f));
18780             }
18781         }
18782         return more;
18783     }
18784 
18785     /**
18786      * This method is called by getDisplayList() when a display list is recorded for a View.
18787      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18788      */
18789     void setDisplayListProperties(RenderNode renderNode) {
18790         if (renderNode != null) {
18791             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18792             renderNode.setClipToBounds(mParent instanceof ViewGroup
18793                     && ((ViewGroup) mParent).getClipChildren());
18794 
18795             float alpha = 1;
18796             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18797                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18798                 ViewGroup parentVG = (ViewGroup) mParent;
18799                 final Transformation t = parentVG.getChildTransformation();
18800                 if (parentVG.getChildStaticTransformation(this, t)) {
18801                     final int transformType = t.getTransformationType();
18802                     if (transformType != Transformation.TYPE_IDENTITY) {
18803                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18804                             alpha = t.getAlpha();
18805                         }
18806                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18807                             renderNode.setStaticMatrix(t.getMatrix());
18808                         }
18809                     }
18810                 }
18811             }
18812             if (mTransformationInfo != null) {
18813                 alpha *= getFinalAlpha();
18814                 if (alpha < 1) {
18815                     final int multipliedAlpha = (int) (255 * alpha);
18816                     if (onSetAlpha(multipliedAlpha)) {
18817                         alpha = 1;
18818                     }
18819                 }
18820                 renderNode.setAlpha(alpha);
18821             } else if (alpha < 1) {
18822                 renderNode.setAlpha(alpha);
18823             }
18824         }
18825     }
18826 
18827     /**
18828      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18829      *
18830      * This is where the View specializes rendering behavior based on layer type,
18831      * and hardware acceleration.
18832      */
18833     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18834         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18835         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18836          *
18837          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18838          * HW accelerated, it can't handle drawing RenderNodes.
18839          */
18840         boolean drawingWithRenderNode = mAttachInfo != null
18841                 && mAttachInfo.mHardwareAccelerated
18842                 && hardwareAcceleratedCanvas;
18843 
18844         boolean more = false;
18845         final boolean childHasIdentityMatrix = hasIdentityMatrix();
18846         final int parentFlags = parent.mGroupFlags;
18847 
18848         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18849             parent.getChildTransformation().clear();
18850             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18851         }
18852 
18853         Transformation transformToApply = null;
18854         boolean concatMatrix = false;
18855         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18856         final Animation a = getAnimation();
18857         if (a != null) {
18858             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18859             concatMatrix = a.willChangeTransformationMatrix();
18860             if (concatMatrix) {
18861                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18862             }
18863             transformToApply = parent.getChildTransformation();
18864         } else {
18865             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18866                 // No longer animating: clear out old animation matrix
18867                 mRenderNode.setAnimationMatrix(null);
18868                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18869             }
18870             if (!drawingWithRenderNode
18871                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18872                 final Transformation t = parent.getChildTransformation();
18873                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18874                 if (hasTransform) {
18875                     final int transformType = t.getTransformationType();
18876                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18877                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18878                 }
18879             }
18880         }
18881 
18882         concatMatrix |= !childHasIdentityMatrix;
18883 
18884         // Sets the flag as early as possible to allow draw() implementations
18885         // to call invalidate() successfully when doing animations
18886         mPrivateFlags |= PFLAG_DRAWN;
18887 
18888         if (!concatMatrix &&
18889                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18890                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18891                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18892                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18893             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18894             return more;
18895         }
18896         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18897 
18898         if (hardwareAcceleratedCanvas) {
18899             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18900             // retain the flag's value temporarily in the mRecreateDisplayList flag
18901             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18902             mPrivateFlags &= ~PFLAG_INVALIDATED;
18903         }
18904 
18905         RenderNode renderNode = null;
18906         Bitmap cache = null;
18907         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18908         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18909              if (layerType != LAYER_TYPE_NONE) {
18910                  // If not drawing with RenderNode, treat HW layers as SW
18911                  layerType = LAYER_TYPE_SOFTWARE;
18912                  buildDrawingCache(true);
18913             }
18914             cache = getDrawingCache(true);
18915         }
18916 
18917         if (drawingWithRenderNode) {
18918             // Delay getting the display list until animation-driven alpha values are
18919             // set up and possibly passed on to the view
18920             renderNode = updateDisplayListIfDirty();
18921             if (!renderNode.isValid()) {
18922                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
18923                 // to getDisplayList(), the display list will be marked invalid and we should not
18924                 // try to use it again.
18925                 renderNode = null;
18926                 drawingWithRenderNode = false;
18927             }
18928         }
18929 
18930         int sx = 0;
18931         int sy = 0;
18932         if (!drawingWithRenderNode) {
18933             computeScroll();
18934             sx = mScrollX;
18935             sy = mScrollY;
18936         }
18937 
18938         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18939         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18940 
18941         int restoreTo = -1;
18942         if (!drawingWithRenderNode || transformToApply != null) {
18943             restoreTo = canvas.save();
18944         }
18945         if (offsetForScroll) {
18946             canvas.translate(mLeft - sx, mTop - sy);
18947         } else {
18948             if (!drawingWithRenderNode) {
18949                 canvas.translate(mLeft, mTop);
18950             }
18951             if (scalingRequired) {
18952                 if (drawingWithRenderNode) {
18953                     // TODO: Might not need this if we put everything inside the DL
18954                     restoreTo = canvas.save();
18955                 }
18956                 // mAttachInfo cannot be null, otherwise scalingRequired == false
18957                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
18958                 canvas.scale(scale, scale);
18959             }
18960         }
18961 
18962         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18963         if (transformToApply != null
18964                 || alpha < 1
18965                 || !hasIdentityMatrix()
18966                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18967             if (transformToApply != null || !childHasIdentityMatrix) {
18968                 int transX = 0;
18969                 int transY = 0;
18970 
18971                 if (offsetForScroll) {
18972                     transX = -sx;
18973                     transY = -sy;
18974                 }
18975 
18976                 if (transformToApply != null) {
18977                     if (concatMatrix) {
18978                         if (drawingWithRenderNode) {
18979                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
18980                         } else {
18981                             // Undo the scroll translation, apply the transformation matrix,
18982                             // then redo the scroll translate to get the correct result.
18983                             canvas.translate(-transX, -transY);
18984                             canvas.concat(transformToApply.getMatrix());
18985                             canvas.translate(transX, transY);
18986                         }
18987                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18988                     }
18989 
18990                     float transformAlpha = transformToApply.getAlpha();
18991                     if (transformAlpha < 1) {
18992                         alpha *= transformAlpha;
18993                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18994                     }
18995                 }
18996 
18997                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18998                     canvas.translate(-transX, -transY);
18999                     canvas.concat(getMatrix());
19000                     canvas.translate(transX, transY);
19001                 }
19002             }
19003 
19004             // Deal with alpha if it is or used to be <1
19005             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
19006                 if (alpha < 1) {
19007                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
19008                 } else {
19009                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
19010                 }
19011                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
19012                 if (!drawingWithDrawingCache) {
19013                     final int multipliedAlpha = (int) (255 * alpha);
19014                     if (!onSetAlpha(multipliedAlpha)) {
19015                         if (drawingWithRenderNode) {
19016                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
19017                         } else if (layerType == LAYER_TYPE_NONE) {
19018                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
19019                                     multipliedAlpha);
19020                         }
19021                     } else {
19022                         // Alpha is handled by the child directly, clobber the layer's alpha
19023                         mPrivateFlags |= PFLAG_ALPHA_SET;
19024                     }
19025                 }
19026             }
19027         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
19028             onSetAlpha(255);
19029             mPrivateFlags &= ~PFLAG_ALPHA_SET;
19030         }
19031 
19032         if (!drawingWithRenderNode) {
19033             // apply clips directly, since RenderNode won't do it for this draw
19034             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
19035                 if (offsetForScroll) {
19036                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
19037                 } else {
19038                     if (!scalingRequired || cache == null) {
19039                         canvas.clipRect(0, 0, getWidth(), getHeight());
19040                     } else {
19041                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
19042                     }
19043                 }
19044             }
19045 
19046             if (mClipBounds != null) {
19047                 // clip bounds ignore scroll
19048                 canvas.clipRect(mClipBounds);
19049             }
19050         }
19051 
19052         if (!drawingWithDrawingCache) {
19053             if (drawingWithRenderNode) {
19054                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19055                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19056             } else {
19057                 // Fast path for layouts with no backgrounds
19058                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
19059                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19060                     dispatchDraw(canvas);
19061                 } else {
19062                     draw(canvas);
19063                 }
19064             }
19065         } else if (cache != null) {
19066             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19067             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
19068                 // no layer paint, use temporary paint to draw bitmap
19069                 Paint cachePaint = parent.mCachePaint;
19070                 if (cachePaint == null) {
19071                     cachePaint = new Paint();
19072                     cachePaint.setDither(false);
19073                     parent.mCachePaint = cachePaint;
19074                 }
19075                 cachePaint.setAlpha((int) (alpha * 255));
19076                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
19077             } else {
19078                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
19079                 int layerPaintAlpha = mLayerPaint.getAlpha();
19080                 if (alpha < 1) {
19081                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
19082                 }
19083                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
19084                 if (alpha < 1) {
19085                     mLayerPaint.setAlpha(layerPaintAlpha);
19086                 }
19087             }
19088         }
19089 
19090         if (restoreTo >= 0) {
19091             canvas.restoreToCount(restoreTo);
19092         }
19093 
19094         if (a != null && !more) {
19095             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
19096                 onSetAlpha(255);
19097             }
19098             parent.finishAnimatingView(this, a);
19099         }
19100 
19101         if (more && hardwareAcceleratedCanvas) {
19102             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
19103                 // alpha animations should cause the child to recreate its display list
19104                 invalidate(true);
19105             }
19106         }
19107 
19108         mRecreateDisplayList = false;
19109 
19110         return more;
19111     }
19112 
19113     static Paint getDebugPaint() {
19114         if (sDebugPaint == null) {
19115             sDebugPaint = new Paint();
19116             sDebugPaint.setAntiAlias(false);
19117         }
19118         return sDebugPaint;
19119     }
19120 
19121     final int dipsToPixels(int dips) {
19122         float scale = getContext().getResources().getDisplayMetrics().density;
19123         return (int) (dips * scale + 0.5f);
19124     }
19125 
19126     final private void debugDrawFocus(Canvas canvas) {
19127         if (isFocused()) {
19128             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
19129             final int l = mScrollX;
19130             final int r = l + mRight - mLeft;
19131             final int t = mScrollY;
19132             final int b = t + mBottom - mTop;
19133 
19134             final Paint paint = getDebugPaint();
19135             paint.setColor(DEBUG_CORNERS_COLOR);
19136 
19137             // Draw squares in corners.
19138             paint.setStyle(Paint.Style.FILL);
19139             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
19140             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
19141             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
19142             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
19143 
19144             // Draw big X across the view.
19145             paint.setStyle(Paint.Style.STROKE);
19146             canvas.drawLine(l, t, r, b, paint);
19147             canvas.drawLine(l, b, r, t, paint);
19148         }
19149     }
19150 
19151     /**
19152      * Manually render this view (and all of its children) to the given Canvas.
19153      * The view must have already done a full layout before this function is
19154      * called.  When implementing a view, implement
19155      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
19156      * If you do need to override this method, call the superclass version.
19157      *
19158      * @param canvas The Canvas to which the View is rendered.
19159      */
19160     @CallSuper
19161     public void draw(Canvas canvas) {
19162         final int privateFlags = mPrivateFlags;
19163         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
19164                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
19165         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
19166 
19167         /*
19168          * Draw traversal performs several drawing steps which must be executed
19169          * in the appropriate order:
19170          *
19171          *      1. Draw the background
19172          *      2. If necessary, save the canvas' layers to prepare for fading
19173          *      3. Draw view's content
19174          *      4. Draw children
19175          *      5. If necessary, draw the fading edges and restore layers
19176          *      6. Draw decorations (scrollbars for instance)
19177          */
19178 
19179         // Step 1, draw the background, if needed
19180         int saveCount;
19181 
19182         if (!dirtyOpaque) {
19183             drawBackground(canvas);
19184         }
19185 
19186         // skip step 2 & 5 if possible (common case)
19187         final int viewFlags = mViewFlags;
19188         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
19189         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
19190         if (!verticalEdges && !horizontalEdges) {
19191             // Step 3, draw the content
19192             if (!dirtyOpaque) onDraw(canvas);
19193 
19194             // Step 4, draw the children
19195             dispatchDraw(canvas);
19196 
19197             drawAutofilledHighlight(canvas);
19198 
19199             // Overlay is part of the content and draws beneath Foreground
19200             if (mOverlay != null && !mOverlay.isEmpty()) {
19201                 mOverlay.getOverlayView().dispatchDraw(canvas);
19202             }
19203 
19204             // Step 6, draw decorations (foreground, scrollbars)
19205             onDrawForeground(canvas);
19206 
19207             // Step 7, draw the default focus highlight
19208             drawDefaultFocusHighlight(canvas);
19209 
19210             if (debugDraw()) {
19211                 debugDrawFocus(canvas);
19212             }
19213 
19214             // we're done...
19215             return;
19216         }
19217 
19218         /*
19219          * Here we do the full fledged routine...
19220          * (this is an uncommon case where speed matters less,
19221          * this is why we repeat some of the tests that have been
19222          * done above)
19223          */
19224 
19225         boolean drawTop = false;
19226         boolean drawBottom = false;
19227         boolean drawLeft = false;
19228         boolean drawRight = false;
19229 
19230         float topFadeStrength = 0.0f;
19231         float bottomFadeStrength = 0.0f;
19232         float leftFadeStrength = 0.0f;
19233         float rightFadeStrength = 0.0f;
19234 
19235         // Step 2, save the canvas' layers
19236         int paddingLeft = mPaddingLeft;
19237 
19238         final boolean offsetRequired = isPaddingOffsetRequired();
19239         if (offsetRequired) {
19240             paddingLeft += getLeftPaddingOffset();
19241         }
19242 
19243         int left = mScrollX + paddingLeft;
19244         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
19245         int top = mScrollY + getFadeTop(offsetRequired);
19246         int bottom = top + getFadeHeight(offsetRequired);
19247 
19248         if (offsetRequired) {
19249             right += getRightPaddingOffset();
19250             bottom += getBottomPaddingOffset();
19251         }
19252 
19253         final ScrollabilityCache scrollabilityCache = mScrollCache;
19254         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
19255         int length = (int) fadeHeight;
19256 
19257         // clip the fade length if top and bottom fades overlap
19258         // overlapping fades produce odd-looking artifacts
19259         if (verticalEdges && (top + length > bottom - length)) {
19260             length = (bottom - top) / 2;
19261         }
19262 
19263         // also clip horizontal fades if necessary
19264         if (horizontalEdges && (left + length > right - length)) {
19265             length = (right - left) / 2;
19266         }
19267 
19268         if (verticalEdges) {
19269             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
19270             drawTop = topFadeStrength * fadeHeight > 1.0f;
19271             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
19272             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
19273         }
19274 
19275         if (horizontalEdges) {
19276             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
19277             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
19278             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
19279             drawRight = rightFadeStrength * fadeHeight > 1.0f;
19280         }
19281 
19282         saveCount = canvas.getSaveCount();
19283 
19284         int solidColor = getSolidColor();
19285         if (solidColor == 0) {
19286             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
19287 
19288             if (drawTop) {
19289                 canvas.saveLayer(left, top, right, top + length, null, flags);
19290             }
19291 
19292             if (drawBottom) {
19293                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
19294             }
19295 
19296             if (drawLeft) {
19297                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
19298             }
19299 
19300             if (drawRight) {
19301                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
19302             }
19303         } else {
19304             scrollabilityCache.setFadeColor(solidColor);
19305         }
19306 
19307         // Step 3, draw the content
19308         if (!dirtyOpaque) onDraw(canvas);
19309 
19310         // Step 4, draw the children
19311         dispatchDraw(canvas);
19312 
19313         // Step 5, draw the fade effect and restore layers
19314         final Paint p = scrollabilityCache.paint;
19315         final Matrix matrix = scrollabilityCache.matrix;
19316         final Shader fade = scrollabilityCache.shader;
19317 
19318         if (drawTop) {
19319             matrix.setScale(1, fadeHeight * topFadeStrength);
19320             matrix.postTranslate(left, top);
19321             fade.setLocalMatrix(matrix);
19322             p.setShader(fade);
19323             canvas.drawRect(left, top, right, top + length, p);
19324         }
19325 
19326         if (drawBottom) {
19327             matrix.setScale(1, fadeHeight * bottomFadeStrength);
19328             matrix.postRotate(180);
19329             matrix.postTranslate(left, bottom);
19330             fade.setLocalMatrix(matrix);
19331             p.setShader(fade);
19332             canvas.drawRect(left, bottom - length, right, bottom, p);
19333         }
19334 
19335         if (drawLeft) {
19336             matrix.setScale(1, fadeHeight * leftFadeStrength);
19337             matrix.postRotate(-90);
19338             matrix.postTranslate(left, top);
19339             fade.setLocalMatrix(matrix);
19340             p.setShader(fade);
19341             canvas.drawRect(left, top, left + length, bottom, p);
19342         }
19343 
19344         if (drawRight) {
19345             matrix.setScale(1, fadeHeight * rightFadeStrength);
19346             matrix.postRotate(90);
19347             matrix.postTranslate(right, top);
19348             fade.setLocalMatrix(matrix);
19349             p.setShader(fade);
19350             canvas.drawRect(right - length, top, right, bottom, p);
19351         }
19352 
19353         canvas.restoreToCount(saveCount);
19354 
19355         drawAutofilledHighlight(canvas);
19356 
19357         // Overlay is part of the content and draws beneath Foreground
19358         if (mOverlay != null && !mOverlay.isEmpty()) {
19359             mOverlay.getOverlayView().dispatchDraw(canvas);
19360         }
19361 
19362         // Step 6, draw decorations (foreground, scrollbars)
19363         onDrawForeground(canvas);
19364 
19365         if (debugDraw()) {
19366             debugDrawFocus(canvas);
19367         }
19368     }
19369 
19370     /**
19371      * Draws the background onto the specified canvas.
19372      *
19373      * @param canvas Canvas on which to draw the background
19374      */
19375     private void drawBackground(Canvas canvas) {
19376         final Drawable background = mBackground;
19377         if (background == null) {
19378             return;
19379         }
19380 
19381         setBackgroundBounds();
19382 
19383         // Attempt to use a display list if requested.
19384         if (canvas.isHardwareAccelerated() && mAttachInfo != null
19385                 && mAttachInfo.mThreadedRenderer != null) {
19386             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
19387 
19388             final RenderNode renderNode = mBackgroundRenderNode;
19389             if (renderNode != null && renderNode.isValid()) {
19390                 setBackgroundRenderNodeProperties(renderNode);
19391                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19392                 return;
19393             }
19394         }
19395 
19396         final int scrollX = mScrollX;
19397         final int scrollY = mScrollY;
19398         if ((scrollX | scrollY) == 0) {
19399             background.draw(canvas);
19400         } else {
19401             canvas.translate(scrollX, scrollY);
19402             background.draw(canvas);
19403             canvas.translate(-scrollX, -scrollY);
19404         }
19405     }
19406 
19407     /**
19408      * Sets the correct background bounds and rebuilds the outline, if needed.
19409      * <p/>
19410      * This is called by LayoutLib.
19411      */
19412     void setBackgroundBounds() {
19413         if (mBackgroundSizeChanged && mBackground != null) {
19414             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
19415             mBackgroundSizeChanged = false;
19416             rebuildOutline();
19417         }
19418     }
19419 
19420     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
19421         renderNode.setTranslationX(mScrollX);
19422         renderNode.setTranslationY(mScrollY);
19423     }
19424 
19425     /**
19426      * Creates a new display list or updates the existing display list for the
19427      * specified Drawable.
19428      *
19429      * @param drawable Drawable for which to create a display list
19430      * @param renderNode Existing RenderNode, or {@code null}
19431      * @return A valid display list for the specified drawable
19432      */
19433     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
19434         if (renderNode == null) {
19435             renderNode = RenderNode.create(drawable.getClass().getName(), this);
19436         }
19437 
19438         final Rect bounds = drawable.getBounds();
19439         final int width = bounds.width();
19440         final int height = bounds.height();
19441         final DisplayListCanvas canvas = renderNode.start(width, height);
19442 
19443         // Reverse left/top translation done by drawable canvas, which will
19444         // instead be applied by rendernode's LTRB bounds below. This way, the
19445         // drawable's bounds match with its rendernode bounds and its content
19446         // will lie within those bounds in the rendernode tree.
19447         canvas.translate(-bounds.left, -bounds.top);
19448 
19449         try {
19450             drawable.draw(canvas);
19451         } finally {
19452             renderNode.end(canvas);
19453         }
19454 
19455         // Set up drawable properties that are view-independent.
19456         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19457         renderNode.setProjectBackwards(drawable.isProjected());
19458         renderNode.setProjectionReceiver(true);
19459         renderNode.setClipToBounds(false);
19460         return renderNode;
19461     }
19462 
19463     /**
19464      * Returns the overlay for this view, creating it if it does not yet exist.
19465      * Adding drawables to the overlay will cause them to be displayed whenever
19466      * the view itself is redrawn. Objects in the overlay should be actively
19467      * managed: remove them when they should not be displayed anymore. The
19468      * overlay will always have the same size as its host view.
19469      *
19470      * <p>Note: Overlays do not currently work correctly with {@link
19471      * SurfaceView} or {@link TextureView}; contents in overlays for these
19472      * types of views may not display correctly.</p>
19473      *
19474      * @return The ViewOverlay object for this view.
19475      * @see ViewOverlay
19476      */
19477     public ViewOverlay getOverlay() {
19478         if (mOverlay == null) {
19479             mOverlay = new ViewOverlay(mContext, this);
19480         }
19481         return mOverlay;
19482     }
19483 
19484     /**
19485      * Override this if your view is known to always be drawn on top of a solid color background,
19486      * and needs to draw fading edges. Returning a non-zero color enables the view system to
19487      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19488      * should be set to 0xFF.
19489      *
19490      * @see #setVerticalFadingEdgeEnabled(boolean)
19491      * @see #setHorizontalFadingEdgeEnabled(boolean)
19492      *
19493      * @return The known solid color background for this view, or 0 if the color may vary
19494      */
19495     @ViewDebug.ExportedProperty(category = "drawing")
19496     @ColorInt
19497     public int getSolidColor() {
19498         return 0;
19499     }
19500 
19501     /**
19502      * Build a human readable string representation of the specified view flags.
19503      *
19504      * @param flags the view flags to convert to a string
19505      * @return a String representing the supplied flags
19506      */
19507     private static String printFlags(int flags) {
19508         String output = "";
19509         int numFlags = 0;
19510         if ((flags & FOCUSABLE) == FOCUSABLE) {
19511             output += "TAKES_FOCUS";
19512             numFlags++;
19513         }
19514 
19515         switch (flags & VISIBILITY_MASK) {
19516         case INVISIBLE:
19517             if (numFlags > 0) {
19518                 output += " ";
19519             }
19520             output += "INVISIBLE";
19521             // USELESS HERE numFlags++;
19522             break;
19523         case GONE:
19524             if (numFlags > 0) {
19525                 output += " ";
19526             }
19527             output += "GONE";
19528             // USELESS HERE numFlags++;
19529             break;
19530         default:
19531             break;
19532         }
19533         return output;
19534     }
19535 
19536     /**
19537      * Build a human readable string representation of the specified private
19538      * view flags.
19539      *
19540      * @param privateFlags the private view flags to convert to a string
19541      * @return a String representing the supplied flags
19542      */
19543     private static String printPrivateFlags(int privateFlags) {
19544         String output = "";
19545         int numFlags = 0;
19546 
19547         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19548             output += "WANTS_FOCUS";
19549             numFlags++;
19550         }
19551 
19552         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19553             if (numFlags > 0) {
19554                 output += " ";
19555             }
19556             output += "FOCUSED";
19557             numFlags++;
19558         }
19559 
19560         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19561             if (numFlags > 0) {
19562                 output += " ";
19563             }
19564             output += "SELECTED";
19565             numFlags++;
19566         }
19567 
19568         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19569             if (numFlags > 0) {
19570                 output += " ";
19571             }
19572             output += "IS_ROOT_NAMESPACE";
19573             numFlags++;
19574         }
19575 
19576         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19577             if (numFlags > 0) {
19578                 output += " ";
19579             }
19580             output += "HAS_BOUNDS";
19581             numFlags++;
19582         }
19583 
19584         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19585             if (numFlags > 0) {
19586                 output += " ";
19587             }
19588             output += "DRAWN";
19589             // USELESS HERE numFlags++;
19590         }
19591         return output;
19592     }
19593 
19594     /**
19595      * <p>Indicates whether or not this view's layout will be requested during
19596      * the next hierarchy layout pass.</p>
19597      *
19598      * @return true if the layout will be forced during next layout pass
19599      */
19600     public boolean isLayoutRequested() {
19601         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19602     }
19603 
19604     /**
19605      * Return true if o is a ViewGroup that is laying out using optical bounds.
19606      * @hide
19607      */
19608     public static boolean isLayoutModeOptical(Object o) {
19609         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19610     }
19611 
19612     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19613         Insets parentInsets = mParent instanceof View ?
19614                 ((View) mParent).getOpticalInsets() : Insets.NONE;
19615         Insets childInsets = getOpticalInsets();
19616         return setFrame(
19617                 left   + parentInsets.left - childInsets.left,
19618                 top    + parentInsets.top  - childInsets.top,
19619                 right  + parentInsets.left + childInsets.right,
19620                 bottom + parentInsets.top  + childInsets.bottom);
19621     }
19622 
19623     /**
19624      * Assign a size and position to a view and all of its
19625      * descendants
19626      *
19627      * <p>This is the second phase of the layout mechanism.
19628      * (The first is measuring). In this phase, each parent calls
19629      * layout on all of its children to position them.
19630      * This is typically done using the child measurements
19631      * that were stored in the measure pass().</p>
19632      *
19633      * <p>Derived classes should not override this method.
19634      * Derived classes with children should override
19635      * onLayout. In that method, they should
19636      * call layout on each of their children.</p>
19637      *
19638      * @param l Left position, relative to parent
19639      * @param t Top position, relative to parent
19640      * @param r Right position, relative to parent
19641      * @param b Bottom position, relative to parent
19642      */
19643     @SuppressWarnings({"unchecked"})
19644     public void layout(int l, int t, int r, int b) {
19645         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19646             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19647             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19648         }
19649 
19650         int oldL = mLeft;
19651         int oldT = mTop;
19652         int oldB = mBottom;
19653         int oldR = mRight;
19654 
19655         boolean changed = isLayoutModeOptical(mParent) ?
19656                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19657 
19658         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19659             onLayout(changed, l, t, r, b);
19660 
19661             if (shouldDrawRoundScrollbar()) {
19662                 if(mRoundScrollbarRenderer == null) {
19663                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19664                 }
19665             } else {
19666                 mRoundScrollbarRenderer = null;
19667             }
19668 
19669             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19670 
19671             ListenerInfo li = mListenerInfo;
19672             if (li != null && li.mOnLayoutChangeListeners != null) {
19673                 ArrayList<OnLayoutChangeListener> listenersCopy =
19674                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19675                 int numListeners = listenersCopy.size();
19676                 for (int i = 0; i < numListeners; ++i) {
19677                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19678                 }
19679             }
19680         }
19681 
19682         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19683         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19684 
19685         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
19686             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
19687             notifyEnterOrExitForAutoFillIfNeeded(true);
19688         }
19689     }
19690 
19691     /**
19692      * Called from layout when this view should
19693      * assign a size and position to each of its children.
19694      *
19695      * Derived classes with children should override
19696      * this method and call layout on each of
19697      * their children.
19698      * @param changed This is a new size or position for this view
19699      * @param left Left position, relative to parent
19700      * @param top Top position, relative to parent
19701      * @param right Right position, relative to parent
19702      * @param bottom Bottom position, relative to parent
19703      */
19704     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19705     }
19706 
19707     /**
19708      * Assign a size and position to this view.
19709      *
19710      * This is called from layout.
19711      *
19712      * @param left Left position, relative to parent
19713      * @param top Top position, relative to parent
19714      * @param right Right position, relative to parent
19715      * @param bottom Bottom position, relative to parent
19716      * @return true if the new size and position are different than the
19717      *         previous ones
19718      * {@hide}
19719      */
19720     protected boolean setFrame(int left, int top, int right, int bottom) {
19721         boolean changed = false;
19722 
19723         if (DBG) {
19724             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19725                     + right + "," + bottom + ")");
19726         }
19727 
19728         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19729             changed = true;
19730 
19731             // Remember our drawn bit
19732             int drawn = mPrivateFlags & PFLAG_DRAWN;
19733 
19734             int oldWidth = mRight - mLeft;
19735             int oldHeight = mBottom - mTop;
19736             int newWidth = right - left;
19737             int newHeight = bottom - top;
19738             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19739 
19740             // Invalidate our old position
19741             invalidate(sizeChanged);
19742 
19743             mLeft = left;
19744             mTop = top;
19745             mRight = right;
19746             mBottom = bottom;
19747             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19748 
19749             mPrivateFlags |= PFLAG_HAS_BOUNDS;
19750 
19751 
19752             if (sizeChanged) {
19753                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19754             }
19755 
19756             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19757                 // If we are visible, force the DRAWN bit to on so that
19758                 // this invalidate will go through (at least to our parent).
19759                 // This is because someone may have invalidated this view
19760                 // before this call to setFrame came in, thereby clearing
19761                 // the DRAWN bit.
19762                 mPrivateFlags |= PFLAG_DRAWN;
19763                 invalidate(sizeChanged);
19764                 // parent display list may need to be recreated based on a change in the bounds
19765                 // of any child
19766                 invalidateParentCaches();
19767             }
19768 
19769             // Reset drawn bit to original value (invalidate turns it off)
19770             mPrivateFlags |= drawn;
19771 
19772             mBackgroundSizeChanged = true;
19773             mDefaultFocusHighlightSizeChanged = true;
19774             if (mForegroundInfo != null) {
19775                 mForegroundInfo.mBoundsChanged = true;
19776             }
19777 
19778             notifySubtreeAccessibilityStateChangedIfNeeded();
19779         }
19780         return changed;
19781     }
19782 
19783     /**
19784      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19785      * @hide
19786      */
19787     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19788         setFrame(left, top, right, bottom);
19789     }
19790 
19791     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19792         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19793         if (mOverlay != null) {
19794             mOverlay.getOverlayView().setRight(newWidth);
19795             mOverlay.getOverlayView().setBottom(newHeight);
19796         }
19797         rebuildOutline();
19798     }
19799 
19800     /**
19801      * Finalize inflating a view from XML.  This is called as the last phase
19802      * of inflation, after all child views have been added.
19803      *
19804      * <p>Even if the subclass overrides onFinishInflate, they should always be
19805      * sure to call the super method, so that we get called.
19806      */
19807     @CallSuper
19808     protected void onFinishInflate() {
19809     }
19810 
19811     /**
19812      * Returns the resources associated with this view.
19813      *
19814      * @return Resources object.
19815      */
19816     public Resources getResources() {
19817         return mResources;
19818     }
19819 
19820     /**
19821      * Invalidates the specified Drawable.
19822      *
19823      * @param drawable the drawable to invalidate
19824      */
19825     @Override
19826     public void invalidateDrawable(@NonNull Drawable drawable) {
19827         if (verifyDrawable(drawable)) {
19828             final Rect dirty = drawable.getDirtyBounds();
19829             final int scrollX = mScrollX;
19830             final int scrollY = mScrollY;
19831 
19832             invalidate(dirty.left + scrollX, dirty.top + scrollY,
19833                     dirty.right + scrollX, dirty.bottom + scrollY);
19834             rebuildOutline();
19835         }
19836     }
19837 
19838     /**
19839      * Schedules an action on a drawable to occur at a specified time.
19840      *
19841      * @param who the recipient of the action
19842      * @param what the action to run on the drawable
19843      * @param when the time at which the action must occur. Uses the
19844      *        {@link SystemClock#uptimeMillis} timebase.
19845      */
19846     @Override
19847     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19848         if (verifyDrawable(who) && what != null) {
19849             final long delay = when - SystemClock.uptimeMillis();
19850             if (mAttachInfo != null) {
19851                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19852                         Choreographer.CALLBACK_ANIMATION, what, who,
19853                         Choreographer.subtractFrameDelay(delay));
19854             } else {
19855                 // Postpone the runnable until we know
19856                 // on which thread it needs to run.
19857                 getRunQueue().postDelayed(what, delay);
19858             }
19859         }
19860     }
19861 
19862     /**
19863      * Cancels a scheduled action on a drawable.
19864      *
19865      * @param who the recipient of the action
19866      * @param what the action to cancel
19867      */
19868     @Override
19869     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19870         if (verifyDrawable(who) && what != null) {
19871             if (mAttachInfo != null) {
19872                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19873                         Choreographer.CALLBACK_ANIMATION, what, who);
19874             }
19875             getRunQueue().removeCallbacks(what);
19876         }
19877     }
19878 
19879     /**
19880      * Unschedule any events associated with the given Drawable.  This can be
19881      * used when selecting a new Drawable into a view, so that the previous
19882      * one is completely unscheduled.
19883      *
19884      * @param who The Drawable to unschedule.
19885      *
19886      * @see #drawableStateChanged
19887      */
19888     public void unscheduleDrawable(Drawable who) {
19889         if (mAttachInfo != null && who != null) {
19890             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19891                     Choreographer.CALLBACK_ANIMATION, null, who);
19892         }
19893     }
19894 
19895     /**
19896      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19897      * that the View directionality can and will be resolved before its Drawables.
19898      *
19899      * Will call {@link View#onResolveDrawables} when resolution is done.
19900      *
19901      * @hide
19902      */
19903     protected void resolveDrawables() {
19904         // Drawables resolution may need to happen before resolving the layout direction (which is
19905         // done only during the measure() call).
19906         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19907         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19908         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19909         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19910         // direction to be resolved as its resolved value will be the same as its raw value.
19911         if (!isLayoutDirectionResolved() &&
19912                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19913             return;
19914         }
19915 
19916         final int layoutDirection = isLayoutDirectionResolved() ?
19917                 getLayoutDirection() : getRawLayoutDirection();
19918 
19919         if (mBackground != null) {
19920             mBackground.setLayoutDirection(layoutDirection);
19921         }
19922         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19923             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19924         }
19925         if (mDefaultFocusHighlight != null) {
19926             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19927         }
19928         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19929         onResolveDrawables(layoutDirection);
19930     }
19931 
19932     boolean areDrawablesResolved() {
19933         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19934     }
19935 
19936     /**
19937      * Called when layout direction has been resolved.
19938      *
19939      * The default implementation does nothing.
19940      *
19941      * @param layoutDirection The resolved layout direction.
19942      *
19943      * @see #LAYOUT_DIRECTION_LTR
19944      * @see #LAYOUT_DIRECTION_RTL
19945      *
19946      * @hide
19947      */
19948     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19949     }
19950 
19951     /**
19952      * @hide
19953      */
19954     protected void resetResolvedDrawables() {
19955         resetResolvedDrawablesInternal();
19956     }
19957 
19958     void resetResolvedDrawablesInternal() {
19959         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19960     }
19961 
19962     /**
19963      * If your view subclass is displaying its own Drawable objects, it should
19964      * override this function and return true for any Drawable it is
19965      * displaying.  This allows animations for those drawables to be
19966      * scheduled.
19967      *
19968      * <p>Be sure to call through to the super class when overriding this
19969      * function.
19970      *
19971      * @param who The Drawable to verify.  Return true if it is one you are
19972      *            displaying, else return the result of calling through to the
19973      *            super class.
19974      *
19975      * @return boolean If true than the Drawable is being displayed in the
19976      *         view; else false and it is not allowed to animate.
19977      *
19978      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19979      * @see #drawableStateChanged()
19980      */
19981     @CallSuper
19982     protected boolean verifyDrawable(@NonNull Drawable who) {
19983         // Avoid verifying the scroll bar drawable so that we don't end up in
19984         // an invalidation loop. This effectively prevents the scroll bar
19985         // drawable from triggering invalidations and scheduling runnables.
19986         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19987                 || (mDefaultFocusHighlight == who);
19988     }
19989 
19990     /**
19991      * This function is called whenever the state of the view changes in such
19992      * a way that it impacts the state of drawables being shown.
19993      * <p>
19994      * If the View has a StateListAnimator, it will also be called to run necessary state
19995      * change animations.
19996      * <p>
19997      * Be sure to call through to the superclass when overriding this function.
19998      *
19999      * @see Drawable#setState(int[])
20000      */
20001     @CallSuper
20002     protected void drawableStateChanged() {
20003         final int[] state = getDrawableState();
20004         boolean changed = false;
20005 
20006         final Drawable bg = mBackground;
20007         if (bg != null && bg.isStateful()) {
20008             changed |= bg.setState(state);
20009         }
20010 
20011         final Drawable hl = mDefaultFocusHighlight;
20012         if (hl != null && hl.isStateful()) {
20013             changed |= hl.setState(state);
20014         }
20015 
20016         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20017         if (fg != null && fg.isStateful()) {
20018             changed |= fg.setState(state);
20019         }
20020 
20021         if (mScrollCache != null) {
20022             final Drawable scrollBar = mScrollCache.scrollBar;
20023             if (scrollBar != null && scrollBar.isStateful()) {
20024                 changed |= scrollBar.setState(state)
20025                         && mScrollCache.state != ScrollabilityCache.OFF;
20026             }
20027         }
20028 
20029         if (mStateListAnimator != null) {
20030             mStateListAnimator.setState(state);
20031         }
20032 
20033         if (changed) {
20034             invalidate();
20035         }
20036     }
20037 
20038     /**
20039      * This function is called whenever the view hotspot changes and needs to
20040      * be propagated to drawables or child views managed by the view.
20041      * <p>
20042      * Dispatching to child views is handled by
20043      * {@link #dispatchDrawableHotspotChanged(float, float)}.
20044      * <p>
20045      * Be sure to call through to the superclass when overriding this function.
20046      *
20047      * @param x hotspot x coordinate
20048      * @param y hotspot y coordinate
20049      */
20050     @CallSuper
20051     public void drawableHotspotChanged(float x, float y) {
20052         if (mBackground != null) {
20053             mBackground.setHotspot(x, y);
20054         }
20055         if (mDefaultFocusHighlight != null) {
20056             mDefaultFocusHighlight.setHotspot(x, y);
20057         }
20058         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20059             mForegroundInfo.mDrawable.setHotspot(x, y);
20060         }
20061 
20062         dispatchDrawableHotspotChanged(x, y);
20063     }
20064 
20065     /**
20066      * Dispatches drawableHotspotChanged to all of this View's children.
20067      *
20068      * @param x hotspot x coordinate
20069      * @param y hotspot y coordinate
20070      * @see #drawableHotspotChanged(float, float)
20071      */
20072     public void dispatchDrawableHotspotChanged(float x, float y) {
20073     }
20074 
20075     /**
20076      * Call this to force a view to update its drawable state. This will cause
20077      * drawableStateChanged to be called on this view. Views that are interested
20078      * in the new state should call getDrawableState.
20079      *
20080      * @see #drawableStateChanged
20081      * @see #getDrawableState
20082      */
20083     public void refreshDrawableState() {
20084         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20085         drawableStateChanged();
20086 
20087         ViewParent parent = mParent;
20088         if (parent != null) {
20089             parent.childDrawableStateChanged(this);
20090         }
20091     }
20092 
20093     /**
20094      * Create a default focus highlight if it doesn't exist.
20095      * @return a default focus highlight.
20096      */
20097     private Drawable getDefaultFocusHighlightDrawable() {
20098         if (mDefaultFocusHighlightCache == null) {
20099             if (mContext != null) {
20100                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
20101                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
20102                 mDefaultFocusHighlightCache = ta.getDrawable(0);
20103                 ta.recycle();
20104             }
20105         }
20106         return mDefaultFocusHighlightCache;
20107     }
20108 
20109     /**
20110      * Set the current default focus highlight.
20111      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
20112      */
20113     private void setDefaultFocusHighlight(Drawable highlight) {
20114         mDefaultFocusHighlight = highlight;
20115         mDefaultFocusHighlightSizeChanged = true;
20116         if (highlight != null) {
20117             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20118                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20119             }
20120             highlight.setLayoutDirection(getLayoutDirection());
20121             if (highlight.isStateful()) {
20122                 highlight.setState(getDrawableState());
20123             }
20124             if (isAttachedToWindow()) {
20125                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20126             }
20127             // Set callback last, since the view may still be initializing.
20128             highlight.setCallback(this);
20129         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20130                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20131             mPrivateFlags |= PFLAG_SKIP_DRAW;
20132         }
20133         invalidate();
20134     }
20135 
20136     /**
20137      * Check whether we need to draw a default focus highlight when this view gets focused,
20138      * which requires:
20139      * <ul>
20140      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
20141      *         is not defined.</li>
20142      *     <li>This view is not in touch mode.</li>
20143      *     <li>This view doesn't opt out for a default focus highlight, via
20144      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
20145      *     <li>This view is attached to window.</li>
20146      * </ul>
20147      * @return {@code true} if a default focus highlight is needed.
20148      * @hide
20149      */
20150     @TestApi
20151     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
20152         final boolean lackFocusState = (background == null || !background.isStateful()
20153                 || !background.hasFocusStateSpecified())
20154                 && (foreground == null || !foreground.isStateful()
20155                 || !foreground.hasFocusStateSpecified());
20156         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
20157                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
20158     }
20159 
20160     /**
20161      * When this view is focused, switches on/off the default focused highlight.
20162      * <p>
20163      * This always happens when this view is focused, and only at this moment the default focus
20164      * highlight can be visible.
20165      */
20166     private void switchDefaultFocusHighlight() {
20167         if (isFocused()) {
20168             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
20169                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
20170             final boolean active = mDefaultFocusHighlight != null;
20171             if (needed && !active) {
20172                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
20173             } else if (!needed && active) {
20174                 // The highlight is no longer needed, so tear it down.
20175                 setDefaultFocusHighlight(null);
20176             }
20177         }
20178     }
20179 
20180     /**
20181      * Draw the default focus highlight onto the canvas.
20182      * @param canvas the canvas where we're drawing the highlight.
20183      */
20184     private void drawDefaultFocusHighlight(Canvas canvas) {
20185         if (mDefaultFocusHighlight != null) {
20186             if (mDefaultFocusHighlightSizeChanged) {
20187                 mDefaultFocusHighlightSizeChanged = false;
20188                 final int l = mScrollX;
20189                 final int r = l + mRight - mLeft;
20190                 final int t = mScrollY;
20191                 final int b = t + mBottom - mTop;
20192                 mDefaultFocusHighlight.setBounds(l, t, r, b);
20193             }
20194             mDefaultFocusHighlight.draw(canvas);
20195         }
20196     }
20197 
20198     /**
20199      * Return an array of resource IDs of the drawable states representing the
20200      * current state of the view.
20201      *
20202      * @return The current drawable state
20203      *
20204      * @see Drawable#setState(int[])
20205      * @see #drawableStateChanged()
20206      * @see #onCreateDrawableState(int)
20207      */
20208     public final int[] getDrawableState() {
20209         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
20210             return mDrawableState;
20211         } else {
20212             mDrawableState = onCreateDrawableState(0);
20213             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
20214             return mDrawableState;
20215         }
20216     }
20217 
20218     /**
20219      * Generate the new {@link android.graphics.drawable.Drawable} state for
20220      * this view. This is called by the view
20221      * system when the cached Drawable state is determined to be invalid.  To
20222      * retrieve the current state, you should use {@link #getDrawableState}.
20223      *
20224      * @param extraSpace if non-zero, this is the number of extra entries you
20225      * would like in the returned array in which you can place your own
20226      * states.
20227      *
20228      * @return Returns an array holding the current {@link Drawable} state of
20229      * the view.
20230      *
20231      * @see #mergeDrawableStates(int[], int[])
20232      */
20233     protected int[] onCreateDrawableState(int extraSpace) {
20234         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
20235                 mParent instanceof View) {
20236             return ((View) mParent).onCreateDrawableState(extraSpace);
20237         }
20238 
20239         int[] drawableState;
20240 
20241         int privateFlags = mPrivateFlags;
20242 
20243         int viewStateIndex = 0;
20244         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
20245         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
20246         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
20247         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
20248         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
20249         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
20250         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
20251                 ThreadedRenderer.isAvailable()) {
20252             // This is set if HW acceleration is requested, even if the current
20253             // process doesn't allow it.  This is just to allow app preview
20254             // windows to better match their app.
20255             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
20256         }
20257         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
20258 
20259         final int privateFlags2 = mPrivateFlags2;
20260         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
20261             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
20262         }
20263         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
20264             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
20265         }
20266 
20267         drawableState = StateSet.get(viewStateIndex);
20268 
20269         //noinspection ConstantIfStatement
20270         if (false) {
20271             Log.i("View", "drawableStateIndex=" + viewStateIndex);
20272             Log.i("View", toString()
20273                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
20274                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
20275                     + " fo=" + hasFocus()
20276                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
20277                     + " wf=" + hasWindowFocus()
20278                     + ": " + Arrays.toString(drawableState));
20279         }
20280 
20281         if (extraSpace == 0) {
20282             return drawableState;
20283         }
20284 
20285         final int[] fullState;
20286         if (drawableState != null) {
20287             fullState = new int[drawableState.length + extraSpace];
20288             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
20289         } else {
20290             fullState = new int[extraSpace];
20291         }
20292 
20293         return fullState;
20294     }
20295 
20296     /**
20297      * Merge your own state values in <var>additionalState</var> into the base
20298      * state values <var>baseState</var> that were returned by
20299      * {@link #onCreateDrawableState(int)}.
20300      *
20301      * @param baseState The base state values returned by
20302      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
20303      * own additional state values.
20304      *
20305      * @param additionalState The additional state values you would like
20306      * added to <var>baseState</var>; this array is not modified.
20307      *
20308      * @return As a convenience, the <var>baseState</var> array you originally
20309      * passed into the function is returned.
20310      *
20311      * @see #onCreateDrawableState(int)
20312      */
20313     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
20314         final int N = baseState.length;
20315         int i = N - 1;
20316         while (i >= 0 && baseState[i] == 0) {
20317             i--;
20318         }
20319         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
20320         return baseState;
20321     }
20322 
20323     /**
20324      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
20325      * on all Drawable objects associated with this view.
20326      * <p>
20327      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
20328      * attached to this view.
20329      */
20330     @CallSuper
20331     public void jumpDrawablesToCurrentState() {
20332         if (mBackground != null) {
20333             mBackground.jumpToCurrentState();
20334         }
20335         if (mStateListAnimator != null) {
20336             mStateListAnimator.jumpToCurrentState();
20337         }
20338         if (mDefaultFocusHighlight != null) {
20339             mDefaultFocusHighlight.jumpToCurrentState();
20340         }
20341         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20342             mForegroundInfo.mDrawable.jumpToCurrentState();
20343         }
20344     }
20345 
20346     /**
20347      * Sets the background color for this view.
20348      * @param color the color of the background
20349      */
20350     @RemotableViewMethod
20351     public void setBackgroundColor(@ColorInt int color) {
20352         if (mBackground instanceof ColorDrawable) {
20353             ((ColorDrawable) mBackground.mutate()).setColor(color);
20354             computeOpaqueFlags();
20355             mBackgroundResource = 0;
20356         } else {
20357             setBackground(new ColorDrawable(color));
20358         }
20359     }
20360 
20361     /**
20362      * Set the background to a given resource. The resource should refer to
20363      * a Drawable object or 0 to remove the background.
20364      * @param resid The identifier of the resource.
20365      *
20366      * @attr ref android.R.styleable#View_background
20367      */
20368     @RemotableViewMethod
20369     public void setBackgroundResource(@DrawableRes int resid) {
20370         if (resid != 0 && resid == mBackgroundResource) {
20371             return;
20372         }
20373 
20374         Drawable d = null;
20375         if (resid != 0) {
20376             d = mContext.getDrawable(resid);
20377         }
20378         setBackground(d);
20379 
20380         mBackgroundResource = resid;
20381     }
20382 
20383     /**
20384      * Set the background to a given Drawable, or remove the background. If the
20385      * background has padding, this View's padding is set to the background's
20386      * padding. However, when a background is removed, this View's padding isn't
20387      * touched. If setting the padding is desired, please use
20388      * {@link #setPadding(int, int, int, int)}.
20389      *
20390      * @param background The Drawable to use as the background, or null to remove the
20391      *        background
20392      */
20393     public void setBackground(Drawable background) {
20394         //noinspection deprecation
20395         setBackgroundDrawable(background);
20396     }
20397 
20398     /**
20399      * @deprecated use {@link #setBackground(Drawable)} instead
20400      */
20401     @Deprecated
20402     public void setBackgroundDrawable(Drawable background) {
20403         computeOpaqueFlags();
20404 
20405         if (background == mBackground) {
20406             return;
20407         }
20408 
20409         boolean requestLayout = false;
20410 
20411         mBackgroundResource = 0;
20412 
20413         /*
20414          * Regardless of whether we're setting a new background or not, we want
20415          * to clear the previous drawable. setVisible first while we still have the callback set.
20416          */
20417         if (mBackground != null) {
20418             if (isAttachedToWindow()) {
20419                 mBackground.setVisible(false, false);
20420             }
20421             mBackground.setCallback(null);
20422             unscheduleDrawable(mBackground);
20423         }
20424 
20425         if (background != null) {
20426             Rect padding = sThreadLocal.get();
20427             if (padding == null) {
20428                 padding = new Rect();
20429                 sThreadLocal.set(padding);
20430             }
20431             resetResolvedDrawablesInternal();
20432             background.setLayoutDirection(getLayoutDirection());
20433             if (background.getPadding(padding)) {
20434                 resetResolvedPaddingInternal();
20435                 switch (background.getLayoutDirection()) {
20436                     case LAYOUT_DIRECTION_RTL:
20437                         mUserPaddingLeftInitial = padding.right;
20438                         mUserPaddingRightInitial = padding.left;
20439                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
20440                         break;
20441                     case LAYOUT_DIRECTION_LTR:
20442                     default:
20443                         mUserPaddingLeftInitial = padding.left;
20444                         mUserPaddingRightInitial = padding.right;
20445                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
20446                 }
20447                 mLeftPaddingDefined = false;
20448                 mRightPaddingDefined = false;
20449             }
20450 
20451             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
20452             // if it has a different minimum size, we should layout again
20453             if (mBackground == null
20454                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
20455                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
20456                 requestLayout = true;
20457             }
20458 
20459             // Set mBackground before we set this as the callback and start making other
20460             // background drawable state change calls. In particular, the setVisible call below
20461             // can result in drawables attempting to start animations or otherwise invalidate,
20462             // which requires the view set as the callback (us) to recognize the drawable as
20463             // belonging to it as per verifyDrawable.
20464             mBackground = background;
20465             if (background.isStateful()) {
20466                 background.setState(getDrawableState());
20467             }
20468             if (isAttachedToWindow()) {
20469                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20470             }
20471 
20472             applyBackgroundTint();
20473 
20474             // Set callback last, since the view may still be initializing.
20475             background.setCallback(this);
20476 
20477             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20478                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20479                 requestLayout = true;
20480             }
20481         } else {
20482             /* Remove the background */
20483             mBackground = null;
20484             if ((mViewFlags & WILL_NOT_DRAW) != 0
20485                     && (mDefaultFocusHighlight == null)
20486                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20487                 mPrivateFlags |= PFLAG_SKIP_DRAW;
20488             }
20489 
20490             /*
20491              * When the background is set, we try to apply its padding to this
20492              * View. When the background is removed, we don't touch this View's
20493              * padding. This is noted in the Javadocs. Hence, we don't need to
20494              * requestLayout(), the invalidate() below is sufficient.
20495              */
20496 
20497             // The old background's minimum size could have affected this
20498             // View's layout, so let's requestLayout
20499             requestLayout = true;
20500         }
20501 
20502         computeOpaqueFlags();
20503 
20504         if (requestLayout) {
20505             requestLayout();
20506         }
20507 
20508         mBackgroundSizeChanged = true;
20509         invalidate(true);
20510         invalidateOutline();
20511     }
20512 
20513     /**
20514      * Gets the background drawable
20515      *
20516      * @return The drawable used as the background for this view, if any.
20517      *
20518      * @see #setBackground(Drawable)
20519      *
20520      * @attr ref android.R.styleable#View_background
20521      */
20522     public Drawable getBackground() {
20523         return mBackground;
20524     }
20525 
20526     /**
20527      * Applies a tint to the background drawable. Does not modify the current tint
20528      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20529      * <p>
20530      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20531      * mutate the drawable and apply the specified tint and tint mode using
20532      * {@link Drawable#setTintList(ColorStateList)}.
20533      *
20534      * @param tint the tint to apply, may be {@code null} to clear tint
20535      *
20536      * @attr ref android.R.styleable#View_backgroundTint
20537      * @see #getBackgroundTintList()
20538      * @see Drawable#setTintList(ColorStateList)
20539      */
20540     public void setBackgroundTintList(@Nullable ColorStateList tint) {
20541         if (mBackgroundTint == null) {
20542             mBackgroundTint = new TintInfo();
20543         }
20544         mBackgroundTint.mTintList = tint;
20545         mBackgroundTint.mHasTintList = true;
20546 
20547         applyBackgroundTint();
20548     }
20549 
20550     /**
20551      * Return the tint applied to the background drawable, if specified.
20552      *
20553      * @return the tint applied to the background drawable
20554      * @attr ref android.R.styleable#View_backgroundTint
20555      * @see #setBackgroundTintList(ColorStateList)
20556      */
20557     @Nullable
20558     public ColorStateList getBackgroundTintList() {
20559         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20560     }
20561 
20562     /**
20563      * Specifies the blending mode used to apply the tint specified by
20564      * {@link #setBackgroundTintList(ColorStateList)}} to the background
20565      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20566      *
20567      * @param tintMode the blending mode used to apply the tint, may be
20568      *                 {@code null} to clear tint
20569      * @attr ref android.R.styleable#View_backgroundTintMode
20570      * @see #getBackgroundTintMode()
20571      * @see Drawable#setTintMode(PorterDuff.Mode)
20572      */
20573     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20574         if (mBackgroundTint == null) {
20575             mBackgroundTint = new TintInfo();
20576         }
20577         mBackgroundTint.mTintMode = tintMode;
20578         mBackgroundTint.mHasTintMode = true;
20579 
20580         applyBackgroundTint();
20581     }
20582 
20583     /**
20584      * Return the blending mode used to apply the tint to the background
20585      * drawable, if specified.
20586      *
20587      * @return the blending mode used to apply the tint to the background
20588      *         drawable
20589      * @attr ref android.R.styleable#View_backgroundTintMode
20590      * @see #setBackgroundTintMode(PorterDuff.Mode)
20591      */
20592     @Nullable
20593     public PorterDuff.Mode getBackgroundTintMode() {
20594         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20595     }
20596 
20597     private void applyBackgroundTint() {
20598         if (mBackground != null && mBackgroundTint != null) {
20599             final TintInfo tintInfo = mBackgroundTint;
20600             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20601                 mBackground = mBackground.mutate();
20602 
20603                 if (tintInfo.mHasTintList) {
20604                     mBackground.setTintList(tintInfo.mTintList);
20605                 }
20606 
20607                 if (tintInfo.mHasTintMode) {
20608                     mBackground.setTintMode(tintInfo.mTintMode);
20609                 }
20610 
20611                 // The drawable (or one of its children) may not have been
20612                 // stateful before applying the tint, so let's try again.
20613                 if (mBackground.isStateful()) {
20614                     mBackground.setState(getDrawableState());
20615                 }
20616             }
20617         }
20618     }
20619 
20620     /**
20621      * Returns the drawable used as the foreground of this View. The
20622      * foreground drawable, if non-null, is always drawn on top of the view's content.
20623      *
20624      * @return a Drawable or null if no foreground was set
20625      *
20626      * @see #onDrawForeground(Canvas)
20627      */
20628     public Drawable getForeground() {
20629         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20630     }
20631 
20632     /**
20633      * Supply a Drawable that is to be rendered on top of all of the content in the view.
20634      *
20635      * @param foreground the Drawable to be drawn on top of the children
20636      *
20637      * @attr ref android.R.styleable#View_foreground
20638      */
20639     public void setForeground(Drawable foreground) {
20640         if (mForegroundInfo == null) {
20641             if (foreground == null) {
20642                 // Nothing to do.
20643                 return;
20644             }
20645             mForegroundInfo = new ForegroundInfo();
20646         }
20647 
20648         if (foreground == mForegroundInfo.mDrawable) {
20649             // Nothing to do
20650             return;
20651         }
20652 
20653         if (mForegroundInfo.mDrawable != null) {
20654             if (isAttachedToWindow()) {
20655                 mForegroundInfo.mDrawable.setVisible(false, false);
20656             }
20657             mForegroundInfo.mDrawable.setCallback(null);
20658             unscheduleDrawable(mForegroundInfo.mDrawable);
20659         }
20660 
20661         mForegroundInfo.mDrawable = foreground;
20662         mForegroundInfo.mBoundsChanged = true;
20663         if (foreground != null) {
20664             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20665                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20666             }
20667             foreground.setLayoutDirection(getLayoutDirection());
20668             if (foreground.isStateful()) {
20669                 foreground.setState(getDrawableState());
20670             }
20671             applyForegroundTint();
20672             if (isAttachedToWindow()) {
20673                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20674             }
20675             // Set callback last, since the view may still be initializing.
20676             foreground.setCallback(this);
20677         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20678                 && (mDefaultFocusHighlight == null)) {
20679             mPrivateFlags |= PFLAG_SKIP_DRAW;
20680         }
20681         requestLayout();
20682         invalidate();
20683     }
20684 
20685     /**
20686      * Magic bit used to support features of framework-internal window decor implementation details.
20687      * This used to live exclusively in FrameLayout.
20688      *
20689      * @return true if the foreground should draw inside the padding region or false
20690      *         if it should draw inset by the view's padding
20691      * @hide internal use only; only used by FrameLayout and internal screen layouts.
20692      */
20693     public boolean isForegroundInsidePadding() {
20694         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20695     }
20696 
20697     /**
20698      * Describes how the foreground is positioned.
20699      *
20700      * @return foreground gravity.
20701      *
20702      * @see #setForegroundGravity(int)
20703      *
20704      * @attr ref android.R.styleable#View_foregroundGravity
20705      */
20706     public int getForegroundGravity() {
20707         return mForegroundInfo != null ? mForegroundInfo.mGravity
20708                 : Gravity.START | Gravity.TOP;
20709     }
20710 
20711     /**
20712      * Describes how the foreground is positioned. Defaults to START and TOP.
20713      *
20714      * @param gravity see {@link android.view.Gravity}
20715      *
20716      * @see #getForegroundGravity()
20717      *
20718      * @attr ref android.R.styleable#View_foregroundGravity
20719      */
20720     public void setForegroundGravity(int gravity) {
20721         if (mForegroundInfo == null) {
20722             mForegroundInfo = new ForegroundInfo();
20723         }
20724 
20725         if (mForegroundInfo.mGravity != gravity) {
20726             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20727                 gravity |= Gravity.START;
20728             }
20729 
20730             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20731                 gravity |= Gravity.TOP;
20732             }
20733 
20734             mForegroundInfo.mGravity = gravity;
20735             requestLayout();
20736         }
20737     }
20738 
20739     /**
20740      * Applies a tint to the foreground drawable. Does not modify the current tint
20741      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20742      * <p>
20743      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20744      * mutate the drawable and apply the specified tint and tint mode using
20745      * {@link Drawable#setTintList(ColorStateList)}.
20746      *
20747      * @param tint the tint to apply, may be {@code null} to clear tint
20748      *
20749      * @attr ref android.R.styleable#View_foregroundTint
20750      * @see #getForegroundTintList()
20751      * @see Drawable#setTintList(ColorStateList)
20752      */
20753     public void setForegroundTintList(@Nullable ColorStateList tint) {
20754         if (mForegroundInfo == null) {
20755             mForegroundInfo = new ForegroundInfo();
20756         }
20757         if (mForegroundInfo.mTintInfo == null) {
20758             mForegroundInfo.mTintInfo = new TintInfo();
20759         }
20760         mForegroundInfo.mTintInfo.mTintList = tint;
20761         mForegroundInfo.mTintInfo.mHasTintList = true;
20762 
20763         applyForegroundTint();
20764     }
20765 
20766     /**
20767      * Return the tint applied to the foreground drawable, if specified.
20768      *
20769      * @return the tint applied to the foreground drawable
20770      * @attr ref android.R.styleable#View_foregroundTint
20771      * @see #setForegroundTintList(ColorStateList)
20772      */
20773     @Nullable
20774     public ColorStateList getForegroundTintList() {
20775         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20776                 ? mForegroundInfo.mTintInfo.mTintList : null;
20777     }
20778 
20779     /**
20780      * Specifies the blending mode used to apply the tint specified by
20781      * {@link #setForegroundTintList(ColorStateList)}} to the background
20782      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20783      *
20784      * @param tintMode the blending mode used to apply the tint, may be
20785      *                 {@code null} to clear tint
20786      * @attr ref android.R.styleable#View_foregroundTintMode
20787      * @see #getForegroundTintMode()
20788      * @see Drawable#setTintMode(PorterDuff.Mode)
20789      */
20790     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20791         if (mForegroundInfo == null) {
20792             mForegroundInfo = new ForegroundInfo();
20793         }
20794         if (mForegroundInfo.mTintInfo == null) {
20795             mForegroundInfo.mTintInfo = new TintInfo();
20796         }
20797         mForegroundInfo.mTintInfo.mTintMode = tintMode;
20798         mForegroundInfo.mTintInfo.mHasTintMode = true;
20799 
20800         applyForegroundTint();
20801     }
20802 
20803     /**
20804      * Return the blending mode used to apply the tint to the foreground
20805      * drawable, if specified.
20806      *
20807      * @return the blending mode used to apply the tint to the foreground
20808      *         drawable
20809      * @attr ref android.R.styleable#View_foregroundTintMode
20810      * @see #setForegroundTintMode(PorterDuff.Mode)
20811      */
20812     @Nullable
20813     public PorterDuff.Mode getForegroundTintMode() {
20814         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20815                 ? mForegroundInfo.mTintInfo.mTintMode : null;
20816     }
20817 
20818     private void applyForegroundTint() {
20819         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20820                 && mForegroundInfo.mTintInfo != null) {
20821             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20822             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20823                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20824 
20825                 if (tintInfo.mHasTintList) {
20826                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20827                 }
20828 
20829                 if (tintInfo.mHasTintMode) {
20830                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20831                 }
20832 
20833                 // The drawable (or one of its children) may not have been
20834                 // stateful before applying the tint, so let's try again.
20835                 if (mForegroundInfo.mDrawable.isStateful()) {
20836                     mForegroundInfo.mDrawable.setState(getDrawableState());
20837                 }
20838             }
20839         }
20840     }
20841 
20842     /**
20843      * Get the drawable to be overlayed when a view is autofilled
20844      *
20845      * @return The drawable
20846      *
20847      * @throws IllegalStateException if the drawable could not be found.
20848      */
20849     @Nullable private Drawable getAutofilledDrawable() {
20850         if (mAttachInfo == null) {
20851             return null;
20852         }
20853         // Lazily load the isAutofilled drawable.
20854         if (mAttachInfo.mAutofilledDrawable == null) {
20855             Context rootContext = getRootView().getContext();
20856             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
20857             int attributeResourceId = a.getResourceId(0, 0);
20858             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
20859             a.recycle();
20860         }
20861 
20862         return mAttachInfo.mAutofilledDrawable;
20863     }
20864 
20865     /**
20866      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20867      *
20868      * @param canvas The canvas to draw on
20869      */
20870     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20871         if (isAutofilled()) {
20872             Drawable autofilledHighlight = getAutofilledDrawable();
20873 
20874             if (autofilledHighlight != null) {
20875                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20876                 autofilledHighlight.draw(canvas);
20877             }
20878         }
20879     }
20880 
20881     /**
20882      * Draw any foreground content for this view.
20883      *
20884      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20885      * drawable or other view-specific decorations. The foreground is drawn on top of the
20886      * primary view content.</p>
20887      *
20888      * @param canvas canvas to draw into
20889      */
20890     public void onDrawForeground(Canvas canvas) {
20891         onDrawScrollIndicators(canvas);
20892         onDrawScrollBars(canvas);
20893 
20894         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20895         if (foreground != null) {
20896             if (mForegroundInfo.mBoundsChanged) {
20897                 mForegroundInfo.mBoundsChanged = false;
20898                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
20899                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20900 
20901                 if (mForegroundInfo.mInsidePadding) {
20902                     selfBounds.set(0, 0, getWidth(), getHeight());
20903                 } else {
20904                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
20905                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20906                 }
20907 
20908                 final int ld = getLayoutDirection();
20909                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20910                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20911                 foreground.setBounds(overlayBounds);
20912             }
20913 
20914             foreground.draw(canvas);
20915         }
20916     }
20917 
20918     /**
20919      * Sets the padding. The view may add on the space required to display
20920      * the scrollbars, depending on the style and visibility of the scrollbars.
20921      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20922      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20923      * from the values set in this call.
20924      *
20925      * @attr ref android.R.styleable#View_padding
20926      * @attr ref android.R.styleable#View_paddingBottom
20927      * @attr ref android.R.styleable#View_paddingLeft
20928      * @attr ref android.R.styleable#View_paddingRight
20929      * @attr ref android.R.styleable#View_paddingTop
20930      * @param left the left padding in pixels
20931      * @param top the top padding in pixels
20932      * @param right the right padding in pixels
20933      * @param bottom the bottom padding in pixels
20934      */
20935     public void setPadding(int left, int top, int right, int bottom) {
20936         resetResolvedPaddingInternal();
20937 
20938         mUserPaddingStart = UNDEFINED_PADDING;
20939         mUserPaddingEnd = UNDEFINED_PADDING;
20940 
20941         mUserPaddingLeftInitial = left;
20942         mUserPaddingRightInitial = right;
20943 
20944         mLeftPaddingDefined = true;
20945         mRightPaddingDefined = true;
20946 
20947         internalSetPadding(left, top, right, bottom);
20948     }
20949 
20950     /**
20951      * @hide
20952      */
20953     protected void internalSetPadding(int left, int top, int right, int bottom) {
20954         mUserPaddingLeft = left;
20955         mUserPaddingRight = right;
20956         mUserPaddingBottom = bottom;
20957 
20958         final int viewFlags = mViewFlags;
20959         boolean changed = false;
20960 
20961         // Common case is there are no scroll bars.
20962         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20963             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20964                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20965                         ? 0 : getVerticalScrollbarWidth();
20966                 switch (mVerticalScrollbarPosition) {
20967                     case SCROLLBAR_POSITION_DEFAULT:
20968                         if (isLayoutRtl()) {
20969                             left += offset;
20970                         } else {
20971                             right += offset;
20972                         }
20973                         break;
20974                     case SCROLLBAR_POSITION_RIGHT:
20975                         right += offset;
20976                         break;
20977                     case SCROLLBAR_POSITION_LEFT:
20978                         left += offset;
20979                         break;
20980                 }
20981             }
20982             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20983                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20984                         ? 0 : getHorizontalScrollbarHeight();
20985             }
20986         }
20987 
20988         if (mPaddingLeft != left) {
20989             changed = true;
20990             mPaddingLeft = left;
20991         }
20992         if (mPaddingTop != top) {
20993             changed = true;
20994             mPaddingTop = top;
20995         }
20996         if (mPaddingRight != right) {
20997             changed = true;
20998             mPaddingRight = right;
20999         }
21000         if (mPaddingBottom != bottom) {
21001             changed = true;
21002             mPaddingBottom = bottom;
21003         }
21004 
21005         if (changed) {
21006             requestLayout();
21007             invalidateOutline();
21008         }
21009     }
21010 
21011     /**
21012      * Sets the relative padding. The view may add on the space required to display
21013      * the scrollbars, depending on the style and visibility of the scrollbars.
21014      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
21015      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
21016      * from the values set in this call.
21017      *
21018      * @attr ref android.R.styleable#View_padding
21019      * @attr ref android.R.styleable#View_paddingBottom
21020      * @attr ref android.R.styleable#View_paddingStart
21021      * @attr ref android.R.styleable#View_paddingEnd
21022      * @attr ref android.R.styleable#View_paddingTop
21023      * @param start the start padding in pixels
21024      * @param top the top padding in pixels
21025      * @param end the end padding in pixels
21026      * @param bottom the bottom padding in pixels
21027      */
21028     public void setPaddingRelative(int start, int top, int end, int bottom) {
21029         resetResolvedPaddingInternal();
21030 
21031         mUserPaddingStart = start;
21032         mUserPaddingEnd = end;
21033         mLeftPaddingDefined = true;
21034         mRightPaddingDefined = true;
21035 
21036         switch(getLayoutDirection()) {
21037             case LAYOUT_DIRECTION_RTL:
21038                 mUserPaddingLeftInitial = end;
21039                 mUserPaddingRightInitial = start;
21040                 internalSetPadding(end, top, start, bottom);
21041                 break;
21042             case LAYOUT_DIRECTION_LTR:
21043             default:
21044                 mUserPaddingLeftInitial = start;
21045                 mUserPaddingRightInitial = end;
21046                 internalSetPadding(start, top, end, bottom);
21047         }
21048     }
21049 
21050     /**
21051      * Returns the top padding of this view.
21052      *
21053      * @return the top padding in pixels
21054      */
21055     public int getPaddingTop() {
21056         return mPaddingTop;
21057     }
21058 
21059     /**
21060      * Returns the bottom padding of this view. If there are inset and enabled
21061      * scrollbars, this value may include the space required to display the
21062      * scrollbars as well.
21063      *
21064      * @return the bottom padding in pixels
21065      */
21066     public int getPaddingBottom() {
21067         return mPaddingBottom;
21068     }
21069 
21070     /**
21071      * Returns the left padding of this view. If there are inset and enabled
21072      * scrollbars, this value may include the space required to display the
21073      * scrollbars as well.
21074      *
21075      * @return the left padding in pixels
21076      */
21077     public int getPaddingLeft() {
21078         if (!isPaddingResolved()) {
21079             resolvePadding();
21080         }
21081         return mPaddingLeft;
21082     }
21083 
21084     /**
21085      * Returns the start padding of this view depending on its resolved layout direction.
21086      * If there are inset and enabled scrollbars, this value may include the space
21087      * required to display the scrollbars as well.
21088      *
21089      * @return the start padding in pixels
21090      */
21091     public int getPaddingStart() {
21092         if (!isPaddingResolved()) {
21093             resolvePadding();
21094         }
21095         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21096                 mPaddingRight : mPaddingLeft;
21097     }
21098 
21099     /**
21100      * Returns the right padding of this view. If there are inset and enabled
21101      * scrollbars, this value may include the space required to display the
21102      * scrollbars as well.
21103      *
21104      * @return the right padding in pixels
21105      */
21106     public int getPaddingRight() {
21107         if (!isPaddingResolved()) {
21108             resolvePadding();
21109         }
21110         return mPaddingRight;
21111     }
21112 
21113     /**
21114      * Returns the end padding of this view depending on its resolved layout direction.
21115      * If there are inset and enabled scrollbars, this value may include the space
21116      * required to display the scrollbars as well.
21117      *
21118      * @return the end padding in pixels
21119      */
21120     public int getPaddingEnd() {
21121         if (!isPaddingResolved()) {
21122             resolvePadding();
21123         }
21124         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21125                 mPaddingLeft : mPaddingRight;
21126     }
21127 
21128     /**
21129      * Return if the padding has been set through relative values
21130      * {@link #setPaddingRelative(int, int, int, int)} or through
21131      * @attr ref android.R.styleable#View_paddingStart or
21132      * @attr ref android.R.styleable#View_paddingEnd
21133      *
21134      * @return true if the padding is relative or false if it is not.
21135      */
21136     public boolean isPaddingRelative() {
21137         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
21138     }
21139 
21140     Insets computeOpticalInsets() {
21141         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
21142     }
21143 
21144     /**
21145      * @hide
21146      */
21147     public void resetPaddingToInitialValues() {
21148         if (isRtlCompatibilityMode()) {
21149             mPaddingLeft = mUserPaddingLeftInitial;
21150             mPaddingRight = mUserPaddingRightInitial;
21151             return;
21152         }
21153         if (isLayoutRtl()) {
21154             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
21155             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
21156         } else {
21157             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
21158             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
21159         }
21160     }
21161 
21162     /**
21163      * @hide
21164      */
21165     public Insets getOpticalInsets() {
21166         if (mLayoutInsets == null) {
21167             mLayoutInsets = computeOpticalInsets();
21168         }
21169         return mLayoutInsets;
21170     }
21171 
21172     /**
21173      * Set this view's optical insets.
21174      *
21175      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
21176      * property. Views that compute their own optical insets should call it as part of measurement.
21177      * This method does not request layout. If you are setting optical insets outside of
21178      * measure/layout itself you will want to call requestLayout() yourself.
21179      * </p>
21180      * @hide
21181      */
21182     public void setOpticalInsets(Insets insets) {
21183         mLayoutInsets = insets;
21184     }
21185 
21186     /**
21187      * Changes the selection state of this view. A view can be selected or not.
21188      * Note that selection is not the same as focus. Views are typically
21189      * selected in the context of an AdapterView like ListView or GridView;
21190      * the selected view is the view that is highlighted.
21191      *
21192      * @param selected true if the view must be selected, false otherwise
21193      */
21194     public void setSelected(boolean selected) {
21195         //noinspection DoubleNegation
21196         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
21197             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
21198             if (!selected) resetPressedState();
21199             invalidate(true);
21200             refreshDrawableState();
21201             dispatchSetSelected(selected);
21202             if (selected) {
21203                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
21204             } else {
21205                 notifyViewAccessibilityStateChangedIfNeeded(
21206                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
21207             }
21208         }
21209     }
21210 
21211     /**
21212      * Dispatch setSelected to all of this View's children.
21213      *
21214      * @see #setSelected(boolean)
21215      *
21216      * @param selected The new selected state
21217      */
21218     protected void dispatchSetSelected(boolean selected) {
21219     }
21220 
21221     /**
21222      * Indicates the selection state of this view.
21223      *
21224      * @return true if the view is selected, false otherwise
21225      */
21226     @ViewDebug.ExportedProperty
21227     public boolean isSelected() {
21228         return (mPrivateFlags & PFLAG_SELECTED) != 0;
21229     }
21230 
21231     /**
21232      * Changes the activated state of this view. A view can be activated or not.
21233      * Note that activation is not the same as selection.  Selection is
21234      * a transient property, representing the view (hierarchy) the user is
21235      * currently interacting with.  Activation is a longer-term state that the
21236      * user can move views in and out of.  For example, in a list view with
21237      * single or multiple selection enabled, the views in the current selection
21238      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
21239      * here.)  The activated state is propagated down to children of the view it
21240      * is set on.
21241      *
21242      * @param activated true if the view must be activated, false otherwise
21243      */
21244     public void setActivated(boolean activated) {
21245         //noinspection DoubleNegation
21246         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
21247             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
21248             invalidate(true);
21249             refreshDrawableState();
21250             dispatchSetActivated(activated);
21251         }
21252     }
21253 
21254     /**
21255      * Dispatch setActivated to all of this View's children.
21256      *
21257      * @see #setActivated(boolean)
21258      *
21259      * @param activated The new activated state
21260      */
21261     protected void dispatchSetActivated(boolean activated) {
21262     }
21263 
21264     /**
21265      * Indicates the activation state of this view.
21266      *
21267      * @return true if the view is activated, false otherwise
21268      */
21269     @ViewDebug.ExportedProperty
21270     public boolean isActivated() {
21271         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
21272     }
21273 
21274     /**
21275      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
21276      * observer can be used to get notifications when global events, like
21277      * layout, happen.
21278      *
21279      * The returned ViewTreeObserver observer is not guaranteed to remain
21280      * valid for the lifetime of this View. If the caller of this method keeps
21281      * a long-lived reference to ViewTreeObserver, it should always check for
21282      * the return value of {@link ViewTreeObserver#isAlive()}.
21283      *
21284      * @return The ViewTreeObserver for this view's hierarchy.
21285      */
21286     public ViewTreeObserver getViewTreeObserver() {
21287         if (mAttachInfo != null) {
21288             return mAttachInfo.mTreeObserver;
21289         }
21290         if (mFloatingTreeObserver == null) {
21291             mFloatingTreeObserver = new ViewTreeObserver(mContext);
21292         }
21293         return mFloatingTreeObserver;
21294     }
21295 
21296     /**
21297      * <p>Finds the topmost view in the current view hierarchy.</p>
21298      *
21299      * @return the topmost view containing this view
21300      */
21301     public View getRootView() {
21302         if (mAttachInfo != null) {
21303             final View v = mAttachInfo.mRootView;
21304             if (v != null) {
21305                 return v;
21306             }
21307         }
21308 
21309         View parent = this;
21310 
21311         while (parent.mParent != null && parent.mParent instanceof View) {
21312             parent = (View) parent.mParent;
21313         }
21314 
21315         return parent;
21316     }
21317 
21318     /**
21319      * Transforms a motion event from view-local coordinates to on-screen
21320      * coordinates.
21321      *
21322      * @param ev the view-local motion event
21323      * @return false if the transformation could not be applied
21324      * @hide
21325      */
21326     public boolean toGlobalMotionEvent(MotionEvent ev) {
21327         final AttachInfo info = mAttachInfo;
21328         if (info == null) {
21329             return false;
21330         }
21331 
21332         final Matrix m = info.mTmpMatrix;
21333         m.set(Matrix.IDENTITY_MATRIX);
21334         transformMatrixToGlobal(m);
21335         ev.transform(m);
21336         return true;
21337     }
21338 
21339     /**
21340      * Transforms a motion event from on-screen coordinates to view-local
21341      * coordinates.
21342      *
21343      * @param ev the on-screen motion event
21344      * @return false if the transformation could not be applied
21345      * @hide
21346      */
21347     public boolean toLocalMotionEvent(MotionEvent ev) {
21348         final AttachInfo info = mAttachInfo;
21349         if (info == null) {
21350             return false;
21351         }
21352 
21353         final Matrix m = info.mTmpMatrix;
21354         m.set(Matrix.IDENTITY_MATRIX);
21355         transformMatrixToLocal(m);
21356         ev.transform(m);
21357         return true;
21358     }
21359 
21360     /**
21361      * Modifies the input matrix such that it maps view-local coordinates to
21362      * on-screen coordinates.
21363      *
21364      * @param m input matrix to modify
21365      * @hide
21366      */
21367     public void transformMatrixToGlobal(Matrix m) {
21368         final ViewParent parent = mParent;
21369         if (parent instanceof View) {
21370             final View vp = (View) parent;
21371             vp.transformMatrixToGlobal(m);
21372             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
21373         } else if (parent instanceof ViewRootImpl) {
21374             final ViewRootImpl vr = (ViewRootImpl) parent;
21375             vr.transformMatrixToGlobal(m);
21376             m.preTranslate(0, -vr.mCurScrollY);
21377         }
21378 
21379         m.preTranslate(mLeft, mTop);
21380 
21381         if (!hasIdentityMatrix()) {
21382             m.preConcat(getMatrix());
21383         }
21384     }
21385 
21386     /**
21387      * Modifies the input matrix such that it maps on-screen coordinates to
21388      * view-local coordinates.
21389      *
21390      * @param m input matrix to modify
21391      * @hide
21392      */
21393     public void transformMatrixToLocal(Matrix m) {
21394         final ViewParent parent = mParent;
21395         if (parent instanceof View) {
21396             final View vp = (View) parent;
21397             vp.transformMatrixToLocal(m);
21398             m.postTranslate(vp.mScrollX, vp.mScrollY);
21399         } else if (parent instanceof ViewRootImpl) {
21400             final ViewRootImpl vr = (ViewRootImpl) parent;
21401             vr.transformMatrixToLocal(m);
21402             m.postTranslate(0, vr.mCurScrollY);
21403         }
21404 
21405         m.postTranslate(-mLeft, -mTop);
21406 
21407         if (!hasIdentityMatrix()) {
21408             m.postConcat(getInverseMatrix());
21409         }
21410     }
21411 
21412     /**
21413      * @hide
21414      */
21415     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
21416             @ViewDebug.IntToString(from = 0, to = "x"),
21417             @ViewDebug.IntToString(from = 1, to = "y")
21418     })
21419     public int[] getLocationOnScreen() {
21420         int[] location = new int[2];
21421         getLocationOnScreen(location);
21422         return location;
21423     }
21424 
21425     /**
21426      * <p>Computes the coordinates of this view on the screen. The argument
21427      * must be an array of two integers. After the method returns, the array
21428      * contains the x and y location in that order.</p>
21429      *
21430      * @param outLocation an array of two integers in which to hold the coordinates
21431      */
21432     public void getLocationOnScreen(@Size(2) int[] outLocation) {
21433         getLocationInWindow(outLocation);
21434 
21435         final AttachInfo info = mAttachInfo;
21436         if (info != null) {
21437             outLocation[0] += info.mWindowLeft;
21438             outLocation[1] += info.mWindowTop;
21439         }
21440     }
21441 
21442     /**
21443      * <p>Computes the coordinates of this view in its window. The argument
21444      * must be an array of two integers. After the method returns, the array
21445      * contains the x and y location in that order.</p>
21446      *
21447      * @param outLocation an array of two integers in which to hold the coordinates
21448      */
21449     public void getLocationInWindow(@Size(2) int[] outLocation) {
21450         if (outLocation == null || outLocation.length < 2) {
21451             throw new IllegalArgumentException("outLocation must be an array of two integers");
21452         }
21453 
21454         outLocation[0] = 0;
21455         outLocation[1] = 0;
21456 
21457         transformFromViewToWindowSpace(outLocation);
21458     }
21459 
21460     /** @hide */
21461     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
21462         if (inOutLocation == null || inOutLocation.length < 2) {
21463             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
21464         }
21465 
21466         if (mAttachInfo == null) {
21467             // When the view is not attached to a window, this method does not make sense
21468             inOutLocation[0] = inOutLocation[1] = 0;
21469             return;
21470         }
21471 
21472         float position[] = mAttachInfo.mTmpTransformLocation;
21473         position[0] = inOutLocation[0];
21474         position[1] = inOutLocation[1];
21475 
21476         if (!hasIdentityMatrix()) {
21477             getMatrix().mapPoints(position);
21478         }
21479 
21480         position[0] += mLeft;
21481         position[1] += mTop;
21482 
21483         ViewParent viewParent = mParent;
21484         while (viewParent instanceof View) {
21485             final View view = (View) viewParent;
21486 
21487             position[0] -= view.mScrollX;
21488             position[1] -= view.mScrollY;
21489 
21490             if (!view.hasIdentityMatrix()) {
21491                 view.getMatrix().mapPoints(position);
21492             }
21493 
21494             position[0] += view.mLeft;
21495             position[1] += view.mTop;
21496 
21497             viewParent = view.mParent;
21498          }
21499 
21500         if (viewParent instanceof ViewRootImpl) {
21501             // *cough*
21502             final ViewRootImpl vr = (ViewRootImpl) viewParent;
21503             position[1] -= vr.mCurScrollY;
21504         }
21505 
21506         inOutLocation[0] = Math.round(position[0]);
21507         inOutLocation[1] = Math.round(position[1]);
21508     }
21509 
21510     /**
21511      * @param id the id of the view to be found
21512      * @return the view of the specified id, null if cannot be found
21513      * @hide
21514      */
21515     protected <T extends View> T findViewTraversal(@IdRes int id) {
21516         if (id == mID) {
21517             return (T) this;
21518         }
21519         return null;
21520     }
21521 
21522     /**
21523      * @param tag the tag of the view to be found
21524      * @return the view of specified tag, null if cannot be found
21525      * @hide
21526      */
21527     protected <T extends View> T findViewWithTagTraversal(Object tag) {
21528         if (tag != null && tag.equals(mTag)) {
21529             return (T) this;
21530         }
21531         return null;
21532     }
21533 
21534     /**
21535      * @param predicate The predicate to evaluate.
21536      * @param childToSkip If not null, ignores this child during the recursive traversal.
21537      * @return The first view that matches the predicate or null.
21538      * @hide
21539      */
21540     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21541             View childToSkip) {
21542         if (predicate.test(this)) {
21543             return (T) this;
21544         }
21545         return null;
21546     }
21547 
21548     /**
21549      * Finds the first descendant view with the given ID, the view itself if
21550      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21551      * (< 0) or there is no matching view in the hierarchy.
21552      * <p>
21553      * <strong>Note:</strong> In most cases -- depending on compiler support --
21554      * the resulting view is automatically cast to the target class type. If
21555      * the target class type is unconstrained, an explicit cast may be
21556      * necessary.
21557      *
21558      * @param id the ID to search for
21559      * @return a view with given ID if found, or {@code null} otherwise
21560      * @see View#findViewById(int)
21561      */
21562     @Nullable
21563     public final <T extends View> T findViewById(@IdRes int id) {
21564         if (id == NO_ID) {
21565             return null;
21566         }
21567         return findViewTraversal(id);
21568     }
21569 
21570     /**
21571      * Finds a view by its unuque and stable accessibility id.
21572      *
21573      * @param accessibilityId The searched accessibility id.
21574      * @return The found view.
21575      */
21576     final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
21577         if (accessibilityId < 0) {
21578             return null;
21579         }
21580         T view = findViewByAccessibilityIdTraversal(accessibilityId);
21581         if (view != null) {
21582             return view.includeForAccessibility() ? view : null;
21583         }
21584         return null;
21585     }
21586 
21587     /**
21588      * Performs the traversal to find a view by its unique and stable accessibility id.
21589      *
21590      * <strong>Note:</strong>This method does not stop at the root namespace
21591      * boundary since the user can touch the screen at an arbitrary location
21592      * potentially crossing the root namespace boundary which will send an
21593      * accessibility event to accessibility services and they should be able
21594      * to obtain the event source. Also accessibility ids are guaranteed to be
21595      * unique in the window.
21596      *
21597      * @param accessibilityId The accessibility id.
21598      * @return The found view.
21599      * @hide
21600      */
21601     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21602         if (getAccessibilityViewId() == accessibilityId) {
21603             return (T) this;
21604         }
21605         return null;
21606     }
21607 
21608     /**
21609      * Performs the traversal to find a view by its autofill id.
21610      *
21611      * <strong>Note:</strong>This method does not stop at the root namespace
21612      * boundary.
21613      *
21614      * @param autofillId The autofill id.
21615      * @return The found view.
21616      * @hide
21617      */
21618     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
21619         if (getAutofillViewId() == autofillId) {
21620             return (T) this;
21621         }
21622         return null;
21623     }
21624 
21625     /**
21626      * Look for a child view with the given tag.  If this view has the given
21627      * tag, return this view.
21628      *
21629      * @param tag The tag to search for, using "tag.equals(getTag())".
21630      * @return The View that has the given tag in the hierarchy or null
21631      */
21632     public final <T extends View> T findViewWithTag(Object tag) {
21633         if (tag == null) {
21634             return null;
21635         }
21636         return findViewWithTagTraversal(tag);
21637     }
21638 
21639     /**
21640      * Look for a child view that matches the specified predicate.
21641      * If this view matches the predicate, return this view.
21642      *
21643      * @param predicate The predicate to evaluate.
21644      * @return The first view that matches the predicate or null.
21645      * @hide
21646      */
21647     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21648         return findViewByPredicateTraversal(predicate, null);
21649     }
21650 
21651     /**
21652      * Look for a child view that matches the specified predicate,
21653      * starting with the specified view and its descendents and then
21654      * recusively searching the ancestors and siblings of that view
21655      * until this view is reached.
21656      *
21657      * This method is useful in cases where the predicate does not match
21658      * a single unique view (perhaps multiple views use the same id)
21659      * and we are trying to find the view that is "closest" in scope to the
21660      * starting view.
21661      *
21662      * @param start The view to start from.
21663      * @param predicate The predicate to evaluate.
21664      * @return The first view that matches the predicate or null.
21665      * @hide
21666      */
21667     public final <T extends View> T findViewByPredicateInsideOut(
21668             View start, Predicate<View> predicate) {
21669         View childToSkip = null;
21670         for (;;) {
21671             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21672             if (view != null || start == this) {
21673                 return view;
21674             }
21675 
21676             ViewParent parent = start.getParent();
21677             if (parent == null || !(parent instanceof View)) {
21678                 return null;
21679             }
21680 
21681             childToSkip = start;
21682             start = (View) parent;
21683         }
21684     }
21685 
21686     /**
21687      * Sets the identifier for this view. The identifier does not have to be
21688      * unique in this view's hierarchy. The identifier should be a positive
21689      * number.
21690      *
21691      * @see #NO_ID
21692      * @see #getId()
21693      * @see #findViewById(int)
21694      *
21695      * @param id a number used to identify the view
21696      *
21697      * @attr ref android.R.styleable#View_id
21698      */
21699     public void setId(@IdRes int id) {
21700         mID = id;
21701         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21702             mID = generateViewId();
21703         }
21704     }
21705 
21706     /**
21707      * {@hide}
21708      *
21709      * @param isRoot true if the view belongs to the root namespace, false
21710      *        otherwise
21711      */
21712     public void setIsRootNamespace(boolean isRoot) {
21713         if (isRoot) {
21714             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21715         } else {
21716             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21717         }
21718     }
21719 
21720     /**
21721      * {@hide}
21722      *
21723      * @return true if the view belongs to the root namespace, false otherwise
21724      */
21725     public boolean isRootNamespace() {
21726         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21727     }
21728 
21729     /**
21730      * Returns this view's identifier.
21731      *
21732      * @return a positive integer used to identify the view or {@link #NO_ID}
21733      *         if the view has no ID
21734      *
21735      * @see #setId(int)
21736      * @see #findViewById(int)
21737      * @attr ref android.R.styleable#View_id
21738      */
21739     @IdRes
21740     @ViewDebug.CapturedViewProperty
21741     public int getId() {
21742         return mID;
21743     }
21744 
21745     /**
21746      * Returns this view's tag.
21747      *
21748      * @return the Object stored in this view as a tag, or {@code null} if not
21749      *         set
21750      *
21751      * @see #setTag(Object)
21752      * @see #getTag(int)
21753      */
21754     @ViewDebug.ExportedProperty
21755     public Object getTag() {
21756         return mTag;
21757     }
21758 
21759     /**
21760      * Sets the tag associated with this view. A tag can be used to mark
21761      * a view in its hierarchy and does not have to be unique within the
21762      * hierarchy. Tags can also be used to store data within a view without
21763      * resorting to another data structure.
21764      *
21765      * @param tag an Object to tag the view with
21766      *
21767      * @see #getTag()
21768      * @see #setTag(int, Object)
21769      */
21770     public void setTag(final Object tag) {
21771         mTag = tag;
21772     }
21773 
21774     /**
21775      * Returns the tag associated with this view and the specified key.
21776      *
21777      * @param key The key identifying the tag
21778      *
21779      * @return the Object stored in this view as a tag, or {@code null} if not
21780      *         set
21781      *
21782      * @see #setTag(int, Object)
21783      * @see #getTag()
21784      */
21785     public Object getTag(int key) {
21786         if (mKeyedTags != null) return mKeyedTags.get(key);
21787         return null;
21788     }
21789 
21790     /**
21791      * Sets a tag associated with this view and a key. A tag can be used
21792      * to mark a view in its hierarchy and does not have to be unique within
21793      * the hierarchy. Tags can also be used to store data within a view
21794      * without resorting to another data structure.
21795      *
21796      * The specified key should be an id declared in the resources of the
21797      * application to ensure it is unique (see the <a
21798      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21799      * Keys identified as belonging to
21800      * the Android framework or not associated with any package will cause
21801      * an {@link IllegalArgumentException} to be thrown.
21802      *
21803      * @param key The key identifying the tag
21804      * @param tag An Object to tag the view with
21805      *
21806      * @throws IllegalArgumentException If they specified key is not valid
21807      *
21808      * @see #setTag(Object)
21809      * @see #getTag(int)
21810      */
21811     public void setTag(int key, final Object tag) {
21812         // If the package id is 0x00 or 0x01, it's either an undefined package
21813         // or a framework id
21814         if ((key >>> 24) < 2) {
21815             throw new IllegalArgumentException("The key must be an application-specific "
21816                     + "resource id.");
21817         }
21818 
21819         setKeyedTag(key, tag);
21820     }
21821 
21822     /**
21823      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21824      * framework id.
21825      *
21826      * @hide
21827      */
21828     public void setTagInternal(int key, Object tag) {
21829         if ((key >>> 24) != 0x1) {
21830             throw new IllegalArgumentException("The key must be a framework-specific "
21831                     + "resource id.");
21832         }
21833 
21834         setKeyedTag(key, tag);
21835     }
21836 
21837     private void setKeyedTag(int key, Object tag) {
21838         if (mKeyedTags == null) {
21839             mKeyedTags = new SparseArray<Object>(2);
21840         }
21841 
21842         mKeyedTags.put(key, tag);
21843     }
21844 
21845     /**
21846      * Prints information about this view in the log output, with the tag
21847      * {@link #VIEW_LOG_TAG}.
21848      *
21849      * @hide
21850      */
21851     public void debug() {
21852         debug(0);
21853     }
21854 
21855     /**
21856      * Prints information about this view in the log output, with the tag
21857      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21858      * indentation defined by the <code>depth</code>.
21859      *
21860      * @param depth the indentation level
21861      *
21862      * @hide
21863      */
21864     protected void debug(int depth) {
21865         String output = debugIndent(depth - 1);
21866 
21867         output += "+ " + this;
21868         int id = getId();
21869         if (id != -1) {
21870             output += " (id=" + id + ")";
21871         }
21872         Object tag = getTag();
21873         if (tag != null) {
21874             output += " (tag=" + tag + ")";
21875         }
21876         Log.d(VIEW_LOG_TAG, output);
21877 
21878         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21879             output = debugIndent(depth) + " FOCUSED";
21880             Log.d(VIEW_LOG_TAG, output);
21881         }
21882 
21883         output = debugIndent(depth);
21884         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21885                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21886                 + "} ";
21887         Log.d(VIEW_LOG_TAG, output);
21888 
21889         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21890                 || mPaddingBottom != 0) {
21891             output = debugIndent(depth);
21892             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21893                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21894             Log.d(VIEW_LOG_TAG, output);
21895         }
21896 
21897         output = debugIndent(depth);
21898         output += "mMeasureWidth=" + mMeasuredWidth +
21899                 " mMeasureHeight=" + mMeasuredHeight;
21900         Log.d(VIEW_LOG_TAG, output);
21901 
21902         output = debugIndent(depth);
21903         if (mLayoutParams == null) {
21904             output += "BAD! no layout params";
21905         } else {
21906             output = mLayoutParams.debug(output);
21907         }
21908         Log.d(VIEW_LOG_TAG, output);
21909 
21910         output = debugIndent(depth);
21911         output += "flags={";
21912         output += View.printFlags(mViewFlags);
21913         output += "}";
21914         Log.d(VIEW_LOG_TAG, output);
21915 
21916         output = debugIndent(depth);
21917         output += "privateFlags={";
21918         output += View.printPrivateFlags(mPrivateFlags);
21919         output += "}";
21920         Log.d(VIEW_LOG_TAG, output);
21921     }
21922 
21923     /**
21924      * Creates a string of whitespaces used for indentation.
21925      *
21926      * @param depth the indentation level
21927      * @return a String containing (depth * 2 + 3) * 2 white spaces
21928      *
21929      * @hide
21930      */
21931     protected static String debugIndent(int depth) {
21932         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21933         for (int i = 0; i < (depth * 2) + 3; i++) {
21934             spaces.append(' ').append(' ');
21935         }
21936         return spaces.toString();
21937     }
21938 
21939     /**
21940      * <p>Return the offset of the widget's text baseline from the widget's top
21941      * boundary. If this widget does not support baseline alignment, this
21942      * method returns -1. </p>
21943      *
21944      * @return the offset of the baseline within the widget's bounds or -1
21945      *         if baseline alignment is not supported
21946      */
21947     @ViewDebug.ExportedProperty(category = "layout")
21948     public int getBaseline() {
21949         return -1;
21950     }
21951 
21952     /**
21953      * Returns whether the view hierarchy is currently undergoing a layout pass. This
21954      * information is useful to avoid situations such as calling {@link #requestLayout()} during
21955      * a layout pass.
21956      *
21957      * @return whether the view hierarchy is currently undergoing a layout pass
21958      */
21959     public boolean isInLayout() {
21960         ViewRootImpl viewRoot = getViewRootImpl();
21961         return (viewRoot != null && viewRoot.isInLayout());
21962     }
21963 
21964     /**
21965      * Call this when something has changed which has invalidated the
21966      * layout of this view. This will schedule a layout pass of the view
21967      * tree. This should not be called while the view hierarchy is currently in a layout
21968      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21969      * end of the current layout pass (and then layout will run again) or after the current
21970      * frame is drawn and the next layout occurs.
21971      *
21972      * <p>Subclasses which override this method should call the superclass method to
21973      * handle possible request-during-layout errors correctly.</p>
21974      */
21975     @CallSuper
21976     public void requestLayout() {
21977         if (mMeasureCache != null) mMeasureCache.clear();
21978 
21979         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21980             // Only trigger request-during-layout logic if this is the view requesting it,
21981             // not the views in its parent hierarchy
21982             ViewRootImpl viewRoot = getViewRootImpl();
21983             if (viewRoot != null && viewRoot.isInLayout()) {
21984                 if (!viewRoot.requestLayoutDuringLayout(this)) {
21985                     return;
21986                 }
21987             }
21988             mAttachInfo.mViewRequestingLayout = this;
21989         }
21990 
21991         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21992         mPrivateFlags |= PFLAG_INVALIDATED;
21993 
21994         if (mParent != null && !mParent.isLayoutRequested()) {
21995             mParent.requestLayout();
21996         }
21997         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21998             mAttachInfo.mViewRequestingLayout = null;
21999         }
22000     }
22001 
22002     /**
22003      * Forces this view to be laid out during the next layout pass.
22004      * This method does not call requestLayout() or forceLayout()
22005      * on the parent.
22006      */
22007     public void forceLayout() {
22008         if (mMeasureCache != null) mMeasureCache.clear();
22009 
22010         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
22011         mPrivateFlags |= PFLAG_INVALIDATED;
22012     }
22013 
22014     /**
22015      * <p>
22016      * This is called to find out how big a view should be. The parent
22017      * supplies constraint information in the width and height parameters.
22018      * </p>
22019      *
22020      * <p>
22021      * The actual measurement work of a view is performed in
22022      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
22023      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
22024      * </p>
22025      *
22026      *
22027      * @param widthMeasureSpec Horizontal space requirements as imposed by the
22028      *        parent
22029      * @param heightMeasureSpec Vertical space requirements as imposed by the
22030      *        parent
22031      *
22032      * @see #onMeasure(int, int)
22033      */
22034     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
22035         boolean optical = isLayoutModeOptical(this);
22036         if (optical != isLayoutModeOptical(mParent)) {
22037             Insets insets = getOpticalInsets();
22038             int oWidth  = insets.left + insets.right;
22039             int oHeight = insets.top  + insets.bottom;
22040             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
22041             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
22042         }
22043 
22044         // Suppress sign extension for the low bytes
22045         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
22046         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
22047 
22048         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
22049 
22050         // Optimize layout by avoiding an extra EXACTLY pass when the view is
22051         // already measured as the correct size. In API 23 and below, this
22052         // extra pass is required to make LinearLayout re-distribute weight.
22053         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
22054                 || heightMeasureSpec != mOldHeightMeasureSpec;
22055         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
22056                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
22057         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
22058                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
22059         final boolean needsLayout = specChanged
22060                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
22061 
22062         if (forceLayout || needsLayout) {
22063             // first clears the measured dimension flag
22064             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
22065 
22066             resolveRtlPropertiesIfNeeded();
22067 
22068             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
22069             if (cacheIndex < 0 || sIgnoreMeasureCache) {
22070                 // measure ourselves, this should set the measured dimension flag back
22071                 onMeasure(widthMeasureSpec, heightMeasureSpec);
22072                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22073             } else {
22074                 long value = mMeasureCache.valueAt(cacheIndex);
22075                 // Casting a long to int drops the high 32 bits, no mask needed
22076                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
22077                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22078             }
22079 
22080             // flag not set, setMeasuredDimension() was not invoked, we raise
22081             // an exception to warn the developer
22082             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
22083                 throw new IllegalStateException("View with id " + getId() + ": "
22084                         + getClass().getName() + "#onMeasure() did not set the"
22085                         + " measured dimension by calling"
22086                         + " setMeasuredDimension()");
22087             }
22088 
22089             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
22090         }
22091 
22092         mOldWidthMeasureSpec = widthMeasureSpec;
22093         mOldHeightMeasureSpec = heightMeasureSpec;
22094 
22095         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
22096                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
22097     }
22098 
22099     /**
22100      * <p>
22101      * Measure the view and its content to determine the measured width and the
22102      * measured height. This method is invoked by {@link #measure(int, int)} and
22103      * should be overridden by subclasses to provide accurate and efficient
22104      * measurement of their contents.
22105      * </p>
22106      *
22107      * <p>
22108      * <strong>CONTRACT:</strong> When overriding this method, you
22109      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
22110      * measured width and height of this view. Failure to do so will trigger an
22111      * <code>IllegalStateException</code>, thrown by
22112      * {@link #measure(int, int)}. Calling the superclass'
22113      * {@link #onMeasure(int, int)} is a valid use.
22114      * </p>
22115      *
22116      * <p>
22117      * The base class implementation of measure defaults to the background size,
22118      * unless a larger size is allowed by the MeasureSpec. Subclasses should
22119      * override {@link #onMeasure(int, int)} to provide better measurements of
22120      * their content.
22121      * </p>
22122      *
22123      * <p>
22124      * If this method is overridden, it is the subclass's responsibility to make
22125      * sure the measured height and width are at least the view's minimum height
22126      * and width ({@link #getSuggestedMinimumHeight()} and
22127      * {@link #getSuggestedMinimumWidth()}).
22128      * </p>
22129      *
22130      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
22131      *                         The requirements are encoded with
22132      *                         {@link android.view.View.MeasureSpec}.
22133      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
22134      *                         The requirements are encoded with
22135      *                         {@link android.view.View.MeasureSpec}.
22136      *
22137      * @see #getMeasuredWidth()
22138      * @see #getMeasuredHeight()
22139      * @see #setMeasuredDimension(int, int)
22140      * @see #getSuggestedMinimumHeight()
22141      * @see #getSuggestedMinimumWidth()
22142      * @see android.view.View.MeasureSpec#getMode(int)
22143      * @see android.view.View.MeasureSpec#getSize(int)
22144      */
22145     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
22146         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
22147                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
22148     }
22149 
22150     /**
22151      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
22152      * measured width and measured height. Failing to do so will trigger an
22153      * exception at measurement time.</p>
22154      *
22155      * @param measuredWidth The measured width of this view.  May be a complex
22156      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22157      * {@link #MEASURED_STATE_TOO_SMALL}.
22158      * @param measuredHeight The measured height of this view.  May be a complex
22159      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22160      * {@link #MEASURED_STATE_TOO_SMALL}.
22161      */
22162     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
22163         boolean optical = isLayoutModeOptical(this);
22164         if (optical != isLayoutModeOptical(mParent)) {
22165             Insets insets = getOpticalInsets();
22166             int opticalWidth  = insets.left + insets.right;
22167             int opticalHeight = insets.top  + insets.bottom;
22168 
22169             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
22170             measuredHeight += optical ? opticalHeight : -opticalHeight;
22171         }
22172         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
22173     }
22174 
22175     /**
22176      * Sets the measured dimension without extra processing for things like optical bounds.
22177      * Useful for reapplying consistent values that have already been cooked with adjustments
22178      * for optical bounds, etc. such as those from the measurement cache.
22179      *
22180      * @param measuredWidth The measured width of this view.  May be a complex
22181      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22182      * {@link #MEASURED_STATE_TOO_SMALL}.
22183      * @param measuredHeight The measured height of this view.  May be a complex
22184      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22185      * {@link #MEASURED_STATE_TOO_SMALL}.
22186      */
22187     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
22188         mMeasuredWidth = measuredWidth;
22189         mMeasuredHeight = measuredHeight;
22190 
22191         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
22192     }
22193 
22194     /**
22195      * Merge two states as returned by {@link #getMeasuredState()}.
22196      * @param curState The current state as returned from a view or the result
22197      * of combining multiple views.
22198      * @param newState The new view state to combine.
22199      * @return Returns a new integer reflecting the combination of the two
22200      * states.
22201      */
22202     public static int combineMeasuredStates(int curState, int newState) {
22203         return curState | newState;
22204     }
22205 
22206     /**
22207      * Version of {@link #resolveSizeAndState(int, int, int)}
22208      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
22209      */
22210     public static int resolveSize(int size, int measureSpec) {
22211         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
22212     }
22213 
22214     /**
22215      * Utility to reconcile a desired size and state, with constraints imposed
22216      * by a MeasureSpec. Will take the desired size, unless a different size
22217      * is imposed by the constraints. The returned value is a compound integer,
22218      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
22219      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
22220      * resulting size is smaller than the size the view wants to be.
22221      *
22222      * @param size How big the view wants to be.
22223      * @param measureSpec Constraints imposed by the parent.
22224      * @param childMeasuredState Size information bit mask for the view's
22225      *                           children.
22226      * @return Size information bit mask as defined by
22227      *         {@link #MEASURED_SIZE_MASK} and
22228      *         {@link #MEASURED_STATE_TOO_SMALL}.
22229      */
22230     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
22231         final int specMode = MeasureSpec.getMode(measureSpec);
22232         final int specSize = MeasureSpec.getSize(measureSpec);
22233         final int result;
22234         switch (specMode) {
22235             case MeasureSpec.AT_MOST:
22236                 if (specSize < size) {
22237                     result = specSize | MEASURED_STATE_TOO_SMALL;
22238                 } else {
22239                     result = size;
22240                 }
22241                 break;
22242             case MeasureSpec.EXACTLY:
22243                 result = specSize;
22244                 break;
22245             case MeasureSpec.UNSPECIFIED:
22246             default:
22247                 result = size;
22248         }
22249         return result | (childMeasuredState & MEASURED_STATE_MASK);
22250     }
22251 
22252     /**
22253      * Utility to return a default size. Uses the supplied size if the
22254      * MeasureSpec imposed no constraints. Will get larger if allowed
22255      * by the MeasureSpec.
22256      *
22257      * @param size Default size for this view
22258      * @param measureSpec Constraints imposed by the parent
22259      * @return The size this view should be.
22260      */
22261     public static int getDefaultSize(int size, int measureSpec) {
22262         int result = size;
22263         int specMode = MeasureSpec.getMode(measureSpec);
22264         int specSize = MeasureSpec.getSize(measureSpec);
22265 
22266         switch (specMode) {
22267         case MeasureSpec.UNSPECIFIED:
22268             result = size;
22269             break;
22270         case MeasureSpec.AT_MOST:
22271         case MeasureSpec.EXACTLY:
22272             result = specSize;
22273             break;
22274         }
22275         return result;
22276     }
22277 
22278     /**
22279      * Returns the suggested minimum height that the view should use. This
22280      * returns the maximum of the view's minimum height
22281      * and the background's minimum height
22282      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
22283      * <p>
22284      * When being used in {@link #onMeasure(int, int)}, the caller should still
22285      * ensure the returned height is within the requirements of the parent.
22286      *
22287      * @return The suggested minimum height of the view.
22288      */
22289     protected int getSuggestedMinimumHeight() {
22290         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
22291 
22292     }
22293 
22294     /**
22295      * Returns the suggested minimum width that the view should use. This
22296      * returns the maximum of the view's minimum width
22297      * and the background's minimum width
22298      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
22299      * <p>
22300      * When being used in {@link #onMeasure(int, int)}, the caller should still
22301      * ensure the returned width is within the requirements of the parent.
22302      *
22303      * @return The suggested minimum width of the view.
22304      */
22305     protected int getSuggestedMinimumWidth() {
22306         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
22307     }
22308 
22309     /**
22310      * Returns the minimum height of the view.
22311      *
22312      * @return the minimum height the view will try to be, in pixels
22313      *
22314      * @see #setMinimumHeight(int)
22315      *
22316      * @attr ref android.R.styleable#View_minHeight
22317      */
22318     public int getMinimumHeight() {
22319         return mMinHeight;
22320     }
22321 
22322     /**
22323      * Sets the minimum height of the view. It is not guaranteed the view will
22324      * be able to achieve this minimum height (for example, if its parent layout
22325      * constrains it with less available height).
22326      *
22327      * @param minHeight The minimum height the view will try to be, in pixels
22328      *
22329      * @see #getMinimumHeight()
22330      *
22331      * @attr ref android.R.styleable#View_minHeight
22332      */
22333     @RemotableViewMethod
22334     public void setMinimumHeight(int minHeight) {
22335         mMinHeight = minHeight;
22336         requestLayout();
22337     }
22338 
22339     /**
22340      * Returns the minimum width of the view.
22341      *
22342      * @return the minimum width the view will try to be, in pixels
22343      *
22344      * @see #setMinimumWidth(int)
22345      *
22346      * @attr ref android.R.styleable#View_minWidth
22347      */
22348     public int getMinimumWidth() {
22349         return mMinWidth;
22350     }
22351 
22352     /**
22353      * Sets the minimum width of the view. It is not guaranteed the view will
22354      * be able to achieve this minimum width (for example, if its parent layout
22355      * constrains it with less available width).
22356      *
22357      * @param minWidth The minimum width the view will try to be, in pixels
22358      *
22359      * @see #getMinimumWidth()
22360      *
22361      * @attr ref android.R.styleable#View_minWidth
22362      */
22363     public void setMinimumWidth(int minWidth) {
22364         mMinWidth = minWidth;
22365         requestLayout();
22366 
22367     }
22368 
22369     /**
22370      * Get the animation currently associated with this view.
22371      *
22372      * @return The animation that is currently playing or
22373      *         scheduled to play for this view.
22374      */
22375     public Animation getAnimation() {
22376         return mCurrentAnimation;
22377     }
22378 
22379     /**
22380      * Start the specified animation now.
22381      *
22382      * @param animation the animation to start now
22383      */
22384     public void startAnimation(Animation animation) {
22385         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
22386         setAnimation(animation);
22387         invalidateParentCaches();
22388         invalidate(true);
22389     }
22390 
22391     /**
22392      * Cancels any animations for this view.
22393      */
22394     public void clearAnimation() {
22395         if (mCurrentAnimation != null) {
22396             mCurrentAnimation.detach();
22397         }
22398         mCurrentAnimation = null;
22399         invalidateParentIfNeeded();
22400     }
22401 
22402     /**
22403      * Sets the next animation to play for this view.
22404      * If you want the animation to play immediately, use
22405      * {@link #startAnimation(android.view.animation.Animation)} instead.
22406      * This method provides allows fine-grained
22407      * control over the start time and invalidation, but you
22408      * must make sure that 1) the animation has a start time set, and
22409      * 2) the view's parent (which controls animations on its children)
22410      * will be invalidated when the animation is supposed to
22411      * start.
22412      *
22413      * @param animation The next animation, or null.
22414      */
22415     public void setAnimation(Animation animation) {
22416         mCurrentAnimation = animation;
22417 
22418         if (animation != null) {
22419             // If the screen is off assume the animation start time is now instead of
22420             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
22421             // would cause the animation to start when the screen turns back on
22422             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
22423                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
22424                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
22425             }
22426             animation.reset();
22427         }
22428     }
22429 
22430     /**
22431      * Invoked by a parent ViewGroup to notify the start of the animation
22432      * currently associated with this view. If you override this method,
22433      * always call super.onAnimationStart();
22434      *
22435      * @see #setAnimation(android.view.animation.Animation)
22436      * @see #getAnimation()
22437      */
22438     @CallSuper
22439     protected void onAnimationStart() {
22440         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
22441     }
22442 
22443     /**
22444      * Invoked by a parent ViewGroup to notify the end of the animation
22445      * currently associated with this view. If you override this method,
22446      * always call super.onAnimationEnd();
22447      *
22448      * @see #setAnimation(android.view.animation.Animation)
22449      * @see #getAnimation()
22450      */
22451     @CallSuper
22452     protected void onAnimationEnd() {
22453         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
22454     }
22455 
22456     /**
22457      * Invoked if there is a Transform that involves alpha. Subclass that can
22458      * draw themselves with the specified alpha should return true, and then
22459      * respect that alpha when their onDraw() is called. If this returns false
22460      * then the view may be redirected to draw into an offscreen buffer to
22461      * fulfill the request, which will look fine, but may be slower than if the
22462      * subclass handles it internally. The default implementation returns false.
22463      *
22464      * @param alpha The alpha (0..255) to apply to the view's drawing
22465      * @return true if the view can draw with the specified alpha.
22466      */
22467     protected boolean onSetAlpha(int alpha) {
22468         return false;
22469     }
22470 
22471     /**
22472      * This is used by the RootView to perform an optimization when
22473      * the view hierarchy contains one or several SurfaceView.
22474      * SurfaceView is always considered transparent, but its children are not,
22475      * therefore all View objects remove themselves from the global transparent
22476      * region (passed as a parameter to this function).
22477      *
22478      * @param region The transparent region for this ViewAncestor (window).
22479      *
22480      * @return Returns true if the effective visibility of the view at this
22481      * point is opaque, regardless of the transparent region; returns false
22482      * if it is possible for underlying windows to be seen behind the view.
22483      *
22484      * {@hide}
22485      */
22486     public boolean gatherTransparentRegion(Region region) {
22487         final AttachInfo attachInfo = mAttachInfo;
22488         if (region != null && attachInfo != null) {
22489             final int pflags = mPrivateFlags;
22490             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22491                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22492                 // remove it from the transparent region.
22493                 final int[] location = attachInfo.mTransparentLocation;
22494                 getLocationInWindow(location);
22495                 // When a view has Z value, then it will be better to leave some area below the view
22496                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22497                 // the bottom part needs more offset than the left, top and right parts due to the
22498                 // spot light effects.
22499                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22500                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22501                         location[0] + mRight - mLeft + shadowOffset,
22502                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22503             } else {
22504                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22505                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22506                     // the background drawable's non-transparent parts from this transparent region.
22507                     applyDrawableToTransparentRegion(mBackground, region);
22508                 }
22509                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22510                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22511                     // Similarly, we remove the foreground drawable's non-transparent parts.
22512                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22513                 }
22514                 if (mDefaultFocusHighlight != null
22515                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22516                     // Similarly, we remove the default focus highlight's non-transparent parts.
22517                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22518                 }
22519             }
22520         }
22521         return true;
22522     }
22523 
22524     /**
22525      * Play a sound effect for this view.
22526      *
22527      * <p>The framework will play sound effects for some built in actions, such as
22528      * clicking, but you may wish to play these effects in your widget,
22529      * for instance, for internal navigation.
22530      *
22531      * <p>The sound effect will only be played if sound effects are enabled by the user, and
22532      * {@link #isSoundEffectsEnabled()} is true.
22533      *
22534      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22535      */
22536     public void playSoundEffect(int soundConstant) {
22537         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22538             return;
22539         }
22540         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22541     }
22542 
22543     /**
22544      * BZZZTT!!1!
22545      *
22546      * <p>Provide haptic feedback to the user for this view.
22547      *
22548      * <p>The framework will provide haptic feedback for some built in actions,
22549      * such as long presses, but you may wish to provide feedback for your
22550      * own widget.
22551      *
22552      * <p>The feedback will only be performed if
22553      * {@link #isHapticFeedbackEnabled()} is true.
22554      *
22555      * @param feedbackConstant One of the constants defined in
22556      * {@link HapticFeedbackConstants}
22557      */
22558     public boolean performHapticFeedback(int feedbackConstant) {
22559         return performHapticFeedback(feedbackConstant, 0);
22560     }
22561 
22562     /**
22563      * BZZZTT!!1!
22564      *
22565      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22566      *
22567      * @param feedbackConstant One of the constants defined in
22568      * {@link HapticFeedbackConstants}
22569      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22570      */
22571     public boolean performHapticFeedback(int feedbackConstant, int flags) {
22572         if (mAttachInfo == null) {
22573             return false;
22574         }
22575         //noinspection SimplifiableIfStatement
22576         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22577                 && !isHapticFeedbackEnabled()) {
22578             return false;
22579         }
22580         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22581                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22582     }
22583 
22584     /**
22585      * Request that the visibility of the status bar or other screen/window
22586      * decorations be changed.
22587      *
22588      * <p>This method is used to put the over device UI into temporary modes
22589      * where the user's attention is focused more on the application content,
22590      * by dimming or hiding surrounding system affordances.  This is typically
22591      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22592      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22593      * to be placed behind the action bar (and with these flags other system
22594      * affordances) so that smooth transitions between hiding and showing them
22595      * can be done.
22596      *
22597      * <p>Two representative examples of the use of system UI visibility is
22598      * implementing a content browsing application (like a magazine reader)
22599      * and a video playing application.
22600      *
22601      * <p>The first code shows a typical implementation of a View in a content
22602      * browsing application.  In this implementation, the application goes
22603      * into a content-oriented mode by hiding the status bar and action bar,
22604      * and putting the navigation elements into lights out mode.  The user can
22605      * then interact with content while in this mode.  Such an application should
22606      * provide an easy way for the user to toggle out of the mode (such as to
22607      * check information in the status bar or access notifications).  In the
22608      * implementation here, this is done simply by tapping on the content.
22609      *
22610      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22611      *      content}
22612      *
22613      * <p>This second code sample shows a typical implementation of a View
22614      * in a video playing application.  In this situation, while the video is
22615      * playing the application would like to go into a complete full-screen mode,
22616      * to use as much of the display as possible for the video.  When in this state
22617      * the user can not interact with the application; the system intercepts
22618      * touching on the screen to pop the UI out of full screen mode.  See
22619      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22620      *
22621      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22622      *      content}
22623      *
22624      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22625      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22626      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22627      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22628      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22629      */
22630     public void setSystemUiVisibility(int visibility) {
22631         if (visibility != mSystemUiVisibility) {
22632             mSystemUiVisibility = visibility;
22633             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22634                 mParent.recomputeViewAttributes(this);
22635             }
22636         }
22637     }
22638 
22639     /**
22640      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22641      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22642      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22643      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22644      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22645      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22646      */
22647     public int getSystemUiVisibility() {
22648         return mSystemUiVisibility;
22649     }
22650 
22651     /**
22652      * Returns the current system UI visibility that is currently set for
22653      * the entire window.  This is the combination of the
22654      * {@link #setSystemUiVisibility(int)} values supplied by all of the
22655      * views in the window.
22656      */
22657     public int getWindowSystemUiVisibility() {
22658         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22659     }
22660 
22661     /**
22662      * Override to find out when the window's requested system UI visibility
22663      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22664      * This is different from the callbacks received through
22665      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22666      * in that this is only telling you about the local request of the window,
22667      * not the actual values applied by the system.
22668      */
22669     public void onWindowSystemUiVisibilityChanged(int visible) {
22670     }
22671 
22672     /**
22673      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22674      * the view hierarchy.
22675      */
22676     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22677         onWindowSystemUiVisibilityChanged(visible);
22678     }
22679 
22680     /**
22681      * Set a listener to receive callbacks when the visibility of the system bar changes.
22682      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22683      */
22684     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22685         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22686         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22687             mParent.recomputeViewAttributes(this);
22688         }
22689     }
22690 
22691     /**
22692      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22693      * the view hierarchy.
22694      */
22695     public void dispatchSystemUiVisibilityChanged(int visibility) {
22696         ListenerInfo li = mListenerInfo;
22697         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22698             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22699                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22700         }
22701     }
22702 
22703     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22704         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22705         if (val != mSystemUiVisibility) {
22706             setSystemUiVisibility(val);
22707             return true;
22708         }
22709         return false;
22710     }
22711 
22712     /** @hide */
22713     public void setDisabledSystemUiVisibility(int flags) {
22714         if (mAttachInfo != null) {
22715             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22716                 mAttachInfo.mDisabledSystemUiVisibility = flags;
22717                 if (mParent != null) {
22718                     mParent.recomputeViewAttributes(this);
22719                 }
22720             }
22721         }
22722     }
22723 
22724     /**
22725      * Creates an image that the system displays during the drag and drop
22726      * operation. This is called a &quot;drag shadow&quot;. The default implementation
22727      * for a DragShadowBuilder based on a View returns an image that has exactly the same
22728      * appearance as the given View. The default also positions the center of the drag shadow
22729      * directly under the touch point. If no View is provided (the constructor with no parameters
22730      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22731      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22732      * default is an invisible drag shadow.
22733      * <p>
22734      * You are not required to use the View you provide to the constructor as the basis of the
22735      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22736      * anything you want as the drag shadow.
22737      * </p>
22738      * <p>
22739      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22740      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22741      *  size and position of the drag shadow. It uses this data to construct a
22742      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22743      *  so that your application can draw the shadow image in the Canvas.
22744      * </p>
22745      *
22746      * <div class="special reference">
22747      * <h3>Developer Guides</h3>
22748      * <p>For a guide to implementing drag and drop features, read the
22749      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22750      * </div>
22751      */
22752     public static class DragShadowBuilder {
22753         private final WeakReference<View> mView;
22754 
22755         /**
22756          * Constructs a shadow image builder based on a View. By default, the resulting drag
22757          * shadow will have the same appearance and dimensions as the View, with the touch point
22758          * over the center of the View.
22759          * @param view A View. Any View in scope can be used.
22760          */
22761         public DragShadowBuilder(View view) {
22762             mView = new WeakReference<View>(view);
22763         }
22764 
22765         /**
22766          * Construct a shadow builder object with no associated View.  This
22767          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22768          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22769          * to supply the drag shadow's dimensions and appearance without
22770          * reference to any View object. If they are not overridden, then the result is an
22771          * invisible drag shadow.
22772          */
22773         public DragShadowBuilder() {
22774             mView = new WeakReference<View>(null);
22775         }
22776 
22777         /**
22778          * Returns the View object that had been passed to the
22779          * {@link #View.DragShadowBuilder(View)}
22780          * constructor.  If that View parameter was {@code null} or if the
22781          * {@link #View.DragShadowBuilder()}
22782          * constructor was used to instantiate the builder object, this method will return
22783          * null.
22784          *
22785          * @return The View object associate with this builder object.
22786          */
22787         @SuppressWarnings({"JavadocReference"})
22788         final public View getView() {
22789             return mView.get();
22790         }
22791 
22792         /**
22793          * Provides the metrics for the shadow image. These include the dimensions of
22794          * the shadow image, and the point within that shadow that should
22795          * be centered under the touch location while dragging.
22796          * <p>
22797          * The default implementation sets the dimensions of the shadow to be the
22798          * same as the dimensions of the View itself and centers the shadow under
22799          * the touch point.
22800          * </p>
22801          *
22802          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22803          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22804          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22805          * image.
22806          *
22807          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22808          * shadow image that should be underneath the touch point during the drag and drop
22809          * operation. Your application must set {@link android.graphics.Point#x} to the
22810          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22811          */
22812         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22813             final View view = mView.get();
22814             if (view != null) {
22815                 outShadowSize.set(view.getWidth(), view.getHeight());
22816                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22817             } else {
22818                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22819             }
22820         }
22821 
22822         /**
22823          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22824          * based on the dimensions it received from the
22825          * {@link #onProvideShadowMetrics(Point, Point)} callback.
22826          *
22827          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22828          */
22829         public void onDrawShadow(Canvas canvas) {
22830             final View view = mView.get();
22831             if (view != null) {
22832                 view.draw(canvas);
22833             } else {
22834                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22835             }
22836         }
22837     }
22838 
22839     /**
22840      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22841      * startDragAndDrop()} for newer platform versions.
22842      */
22843     @Deprecated
22844     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22845                                    Object myLocalState, int flags) {
22846         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22847     }
22848 
22849     /**
22850      * Starts a drag and drop operation. When your application calls this method, it passes a
22851      * {@link android.view.View.DragShadowBuilder} object to the system. The
22852      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22853      * to get metrics for the drag shadow, and then calls the object's
22854      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22855      * <p>
22856      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22857      *  drag events to all the View objects in your application that are currently visible. It does
22858      *  this either by calling the View object's drag listener (an implementation of
22859      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22860      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22861      *  Both are passed a {@link android.view.DragEvent} object that has a
22862      *  {@link android.view.DragEvent#getAction()} value of
22863      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22864      * </p>
22865      * <p>
22866      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22867      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22868      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22869      * to the View the user selected for dragging.
22870      * </p>
22871      * @param data A {@link android.content.ClipData} object pointing to the data to be
22872      * transferred by the drag and drop operation.
22873      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22874      * drag shadow.
22875      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22876      * drop operation. When dispatching drag events to views in the same activity this object
22877      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22878      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22879      * will return null).
22880      * <p>
22881      * myLocalState is a lightweight mechanism for the sending information from the dragged View
22882      * to the target Views. For example, it can contain flags that differentiate between a
22883      * a copy operation and a move operation.
22884      * </p>
22885      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22886      * flags, or any combination of the following:
22887      *     <ul>
22888      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22889      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22890      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22891      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22892      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22893      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22894      *     </ul>
22895      * @return {@code true} if the method completes successfully, or
22896      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22897      * do a drag, and so no drag operation is in progress.
22898      */
22899     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22900             Object myLocalState, int flags) {
22901         if (ViewDebug.DEBUG_DRAG) {
22902             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22903         }
22904         if (mAttachInfo == null) {
22905             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22906             return false;
22907         }
22908 
22909         if (data != null) {
22910             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22911         }
22912 
22913         boolean okay = false;
22914 
22915         Point shadowSize = new Point();
22916         Point shadowTouchPoint = new Point();
22917         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22918 
22919         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22920                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22921             throw new IllegalStateException("Drag shadow dimensions must not be negative");
22922         }
22923 
22924         if (ViewDebug.DEBUG_DRAG) {
22925             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22926                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22927         }
22928         if (mAttachInfo.mDragSurface != null) {
22929             mAttachInfo.mDragSurface.release();
22930         }
22931         mAttachInfo.mDragSurface = new Surface();
22932         try {
22933             mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22934                     flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22935             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22936                     + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22937             if (mAttachInfo.mDragToken != null) {
22938                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22939                 try {
22940                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22941                     shadowBuilder.onDrawShadow(canvas);
22942                 } finally {
22943                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22944                 }
22945 
22946                 final ViewRootImpl root = getViewRootImpl();
22947 
22948                 // Cache the local state object for delivery with DragEvents
22949                 root.setLocalDragState(myLocalState);
22950 
22951                 // repurpose 'shadowSize' for the last touch point
22952                 root.getLastTouchPoint(shadowSize);
22953 
22954                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22955                         root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22956                         shadowTouchPoint.x, shadowTouchPoint.y, data);
22957                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22958             }
22959         } catch (Exception e) {
22960             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22961             mAttachInfo.mDragSurface.destroy();
22962             mAttachInfo.mDragSurface = null;
22963         }
22964 
22965         return okay;
22966     }
22967 
22968     /**
22969      * Cancels an ongoing drag and drop operation.
22970      * <p>
22971      * A {@link android.view.DragEvent} object with
22972      * {@link android.view.DragEvent#getAction()} value of
22973      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22974      * {@link android.view.DragEvent#getResult()} value of {@code false}
22975      * will be sent to every
22976      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22977      * even if they are not currently visible.
22978      * </p>
22979      * <p>
22980      * This method can be called on any View in the same window as the View on which
22981      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22982      * was called.
22983      * </p>
22984      */
22985     public final void cancelDragAndDrop() {
22986         if (ViewDebug.DEBUG_DRAG) {
22987             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22988         }
22989         if (mAttachInfo == null) {
22990             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22991             return;
22992         }
22993         if (mAttachInfo.mDragToken != null) {
22994             try {
22995                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22996             } catch (Exception e) {
22997                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22998             }
22999             mAttachInfo.mDragToken = null;
23000         } else {
23001             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
23002         }
23003     }
23004 
23005     /**
23006      * Updates the drag shadow for the ongoing drag and drop operation.
23007      *
23008      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
23009      * new drag shadow.
23010      */
23011     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
23012         if (ViewDebug.DEBUG_DRAG) {
23013             Log.d(VIEW_LOG_TAG, "updateDragShadow");
23014         }
23015         if (mAttachInfo == null) {
23016             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
23017             return;
23018         }
23019         if (mAttachInfo.mDragToken != null) {
23020             try {
23021                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
23022                 try {
23023                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
23024                     shadowBuilder.onDrawShadow(canvas);
23025                 } finally {
23026                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
23027                 }
23028             } catch (Exception e) {
23029                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
23030             }
23031         } else {
23032             Log.e(VIEW_LOG_TAG, "No active drag");
23033         }
23034     }
23035 
23036     /**
23037      * Starts a move from {startX, startY}, the amount of the movement will be the offset
23038      * between {startX, startY} and the new cursor positon.
23039      * @param startX horizontal coordinate where the move started.
23040      * @param startY vertical coordinate where the move started.
23041      * @return whether moving was started successfully.
23042      * @hide
23043      */
23044     public final boolean startMovingTask(float startX, float startY) {
23045         if (ViewDebug.DEBUG_POSITIONING) {
23046             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
23047         }
23048         try {
23049             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
23050         } catch (RemoteException e) {
23051             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
23052         }
23053         return false;
23054     }
23055 
23056     /**
23057      * Handles drag events sent by the system following a call to
23058      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
23059      * startDragAndDrop()}.
23060      *<p>
23061      * When the system calls this method, it passes a
23062      * {@link android.view.DragEvent} object. A call to
23063      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
23064      * in DragEvent. The method uses these to determine what is happening in the drag and drop
23065      * operation.
23066      * @param event The {@link android.view.DragEvent} sent by the system.
23067      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
23068      * in DragEvent, indicating the type of drag event represented by this object.
23069      * @return {@code true} if the method was successful, otherwise {@code false}.
23070      * <p>
23071      *  The method should return {@code true} in response to an action type of
23072      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
23073      *  operation.
23074      * </p>
23075      * <p>
23076      *  The method should also return {@code true} in response to an action type of
23077      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
23078      *  {@code false} if it didn't.
23079      * </p>
23080      * <p>
23081      *  For all other events, the return value is ignored.
23082      * </p>
23083      */
23084     public boolean onDragEvent(DragEvent event) {
23085         return false;
23086     }
23087 
23088     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
23089     boolean dispatchDragEnterExitInPreN(DragEvent event) {
23090         return callDragEventHandler(event);
23091     }
23092 
23093     /**
23094      * Detects if this View is enabled and has a drag event listener.
23095      * If both are true, then it calls the drag event listener with the
23096      * {@link android.view.DragEvent} it received. If the drag event listener returns
23097      * {@code true}, then dispatchDragEvent() returns {@code true}.
23098      * <p>
23099      * For all other cases, the method calls the
23100      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
23101      * method and returns its result.
23102      * </p>
23103      * <p>
23104      * This ensures that a drag event is always consumed, even if the View does not have a drag
23105      * event listener. However, if the View has a listener and the listener returns true, then
23106      * onDragEvent() is not called.
23107      * </p>
23108      */
23109     public boolean dispatchDragEvent(DragEvent event) {
23110         event.mEventHandlerWasCalled = true;
23111         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
23112             event.mAction == DragEvent.ACTION_DROP) {
23113             // About to deliver an event with coordinates to this view. Notify that now this view
23114             // has drag focus. This will send exit/enter events as needed.
23115             getViewRootImpl().setDragFocus(this, event);
23116         }
23117         return callDragEventHandler(event);
23118     }
23119 
23120     final boolean callDragEventHandler(DragEvent event) {
23121         final boolean result;
23122 
23123         ListenerInfo li = mListenerInfo;
23124         //noinspection SimplifiableIfStatement
23125         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
23126                 && li.mOnDragListener.onDrag(this, event)) {
23127             result = true;
23128         } else {
23129             result = onDragEvent(event);
23130         }
23131 
23132         switch (event.mAction) {
23133             case DragEvent.ACTION_DRAG_ENTERED: {
23134                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
23135                 refreshDrawableState();
23136             } break;
23137             case DragEvent.ACTION_DRAG_EXITED: {
23138                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
23139                 refreshDrawableState();
23140             } break;
23141             case DragEvent.ACTION_DRAG_ENDED: {
23142                 mPrivateFlags2 &= ~View.DRAG_MASK;
23143                 refreshDrawableState();
23144             } break;
23145         }
23146 
23147         return result;
23148     }
23149 
23150     boolean canAcceptDrag() {
23151         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
23152     }
23153 
23154     /**
23155      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
23156      * it is ever exposed at all.
23157      * @hide
23158      */
23159     public void onCloseSystemDialogs(String reason) {
23160     }
23161 
23162     /**
23163      * Given a Drawable whose bounds have been set to draw into this view,
23164      * update a Region being computed for
23165      * {@link #gatherTransparentRegion(android.graphics.Region)} so
23166      * that any non-transparent parts of the Drawable are removed from the
23167      * given transparent region.
23168      *
23169      * @param dr The Drawable whose transparency is to be applied to the region.
23170      * @param region A Region holding the current transparency information,
23171      * where any parts of the region that are set are considered to be
23172      * transparent.  On return, this region will be modified to have the
23173      * transparency information reduced by the corresponding parts of the
23174      * Drawable that are not transparent.
23175      * {@hide}
23176      */
23177     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
23178         if (DBG) {
23179             Log.i("View", "Getting transparent region for: " + this);
23180         }
23181         final Region r = dr.getTransparentRegion();
23182         final Rect db = dr.getBounds();
23183         final AttachInfo attachInfo = mAttachInfo;
23184         if (r != null && attachInfo != null) {
23185             final int w = getRight()-getLeft();
23186             final int h = getBottom()-getTop();
23187             if (db.left > 0) {
23188                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
23189                 r.op(0, 0, db.left, h, Region.Op.UNION);
23190             }
23191             if (db.right < w) {
23192                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
23193                 r.op(db.right, 0, w, h, Region.Op.UNION);
23194             }
23195             if (db.top > 0) {
23196                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
23197                 r.op(0, 0, w, db.top, Region.Op.UNION);
23198             }
23199             if (db.bottom < h) {
23200                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
23201                 r.op(0, db.bottom, w, h, Region.Op.UNION);
23202             }
23203             final int[] location = attachInfo.mTransparentLocation;
23204             getLocationInWindow(location);
23205             r.translate(location[0], location[1]);
23206             region.op(r, Region.Op.INTERSECT);
23207         } else {
23208             region.op(db, Region.Op.DIFFERENCE);
23209         }
23210     }
23211 
23212     private void checkForLongClick(int delayOffset, float x, float y) {
23213         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
23214             mHasPerformedLongPress = false;
23215 
23216             if (mPendingCheckForLongPress == null) {
23217                 mPendingCheckForLongPress = new CheckForLongPress();
23218             }
23219             mPendingCheckForLongPress.setAnchor(x, y);
23220             mPendingCheckForLongPress.rememberWindowAttachCount();
23221             mPendingCheckForLongPress.rememberPressedState();
23222             postDelayed(mPendingCheckForLongPress,
23223                     ViewConfiguration.getLongPressTimeout() - delayOffset);
23224         }
23225     }
23226 
23227     /**
23228      * Inflate a view from an XML resource.  This convenience method wraps the {@link
23229      * LayoutInflater} class, which provides a full range of options for view inflation.
23230      *
23231      * @param context The Context object for your activity or application.
23232      * @param resource The resource ID to inflate
23233      * @param root A view group that will be the parent.  Used to properly inflate the
23234      * layout_* parameters.
23235      * @see LayoutInflater
23236      */
23237     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
23238         LayoutInflater factory = LayoutInflater.from(context);
23239         return factory.inflate(resource, root);
23240     }
23241 
23242     /**
23243      * Scroll the view with standard behavior for scrolling beyond the normal
23244      * content boundaries. Views that call this method should override
23245      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
23246      * results of an over-scroll operation.
23247      *
23248      * Views can use this method to handle any touch or fling-based scrolling.
23249      *
23250      * @param deltaX Change in X in pixels
23251      * @param deltaY Change in Y in pixels
23252      * @param scrollX Current X scroll value in pixels before applying deltaX
23253      * @param scrollY Current Y scroll value in pixels before applying deltaY
23254      * @param scrollRangeX Maximum content scroll range along the X axis
23255      * @param scrollRangeY Maximum content scroll range along the Y axis
23256      * @param maxOverScrollX Number of pixels to overscroll by in either direction
23257      *          along the X axis.
23258      * @param maxOverScrollY Number of pixels to overscroll by in either direction
23259      *          along the Y axis.
23260      * @param isTouchEvent true if this scroll operation is the result of a touch event.
23261      * @return true if scrolling was clamped to an over-scroll boundary along either
23262      *          axis, false otherwise.
23263      */
23264     @SuppressWarnings({"UnusedParameters"})
23265     protected boolean overScrollBy(int deltaX, int deltaY,
23266             int scrollX, int scrollY,
23267             int scrollRangeX, int scrollRangeY,
23268             int maxOverScrollX, int maxOverScrollY,
23269             boolean isTouchEvent) {
23270         final int overScrollMode = mOverScrollMode;
23271         final boolean canScrollHorizontal =
23272                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
23273         final boolean canScrollVertical =
23274                 computeVerticalScrollRange() > computeVerticalScrollExtent();
23275         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
23276                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
23277         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
23278                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
23279 
23280         int newScrollX = scrollX + deltaX;
23281         if (!overScrollHorizontal) {
23282             maxOverScrollX = 0;
23283         }
23284 
23285         int newScrollY = scrollY + deltaY;
23286         if (!overScrollVertical) {
23287             maxOverScrollY = 0;
23288         }
23289 
23290         // Clamp values if at the limits and record
23291         final int left = -maxOverScrollX;
23292         final int right = maxOverScrollX + scrollRangeX;
23293         final int top = -maxOverScrollY;
23294         final int bottom = maxOverScrollY + scrollRangeY;
23295 
23296         boolean clampedX = false;
23297         if (newScrollX > right) {
23298             newScrollX = right;
23299             clampedX = true;
23300         } else if (newScrollX < left) {
23301             newScrollX = left;
23302             clampedX = true;
23303         }
23304 
23305         boolean clampedY = false;
23306         if (newScrollY > bottom) {
23307             newScrollY = bottom;
23308             clampedY = true;
23309         } else if (newScrollY < top) {
23310             newScrollY = top;
23311             clampedY = true;
23312         }
23313 
23314         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
23315 
23316         return clampedX || clampedY;
23317     }
23318 
23319     /**
23320      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
23321      * respond to the results of an over-scroll operation.
23322      *
23323      * @param scrollX New X scroll value in pixels
23324      * @param scrollY New Y scroll value in pixels
23325      * @param clampedX True if scrollX was clamped to an over-scroll boundary
23326      * @param clampedY True if scrollY was clamped to an over-scroll boundary
23327      */
23328     protected void onOverScrolled(int scrollX, int scrollY,
23329             boolean clampedX, boolean clampedY) {
23330         // Intentionally empty.
23331     }
23332 
23333     /**
23334      * Returns the over-scroll mode for this view. The result will be
23335      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23336      * (allow over-scrolling only if the view content is larger than the container),
23337      * or {@link #OVER_SCROLL_NEVER}.
23338      *
23339      * @return This view's over-scroll mode.
23340      */
23341     public int getOverScrollMode() {
23342         return mOverScrollMode;
23343     }
23344 
23345     /**
23346      * Set the over-scroll mode for this view. Valid over-scroll modes are
23347      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23348      * (allow over-scrolling only if the view content is larger than the container),
23349      * or {@link #OVER_SCROLL_NEVER}.
23350      *
23351      * Setting the over-scroll mode of a view will have an effect only if the
23352      * view is capable of scrolling.
23353      *
23354      * @param overScrollMode The new over-scroll mode for this view.
23355      */
23356     public void setOverScrollMode(int overScrollMode) {
23357         if (overScrollMode != OVER_SCROLL_ALWAYS &&
23358                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
23359                 overScrollMode != OVER_SCROLL_NEVER) {
23360             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
23361         }
23362         mOverScrollMode = overScrollMode;
23363     }
23364 
23365     /**
23366      * Enable or disable nested scrolling for this view.
23367      *
23368      * <p>If this property is set to true the view will be permitted to initiate nested
23369      * scrolling operations with a compatible parent view in the current hierarchy. If this
23370      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
23371      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
23372      * the nested scroll.</p>
23373      *
23374      * @param enabled true to enable nested scrolling, false to disable
23375      *
23376      * @see #isNestedScrollingEnabled()
23377      */
23378     public void setNestedScrollingEnabled(boolean enabled) {
23379         if (enabled) {
23380             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
23381         } else {
23382             stopNestedScroll();
23383             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
23384         }
23385     }
23386 
23387     /**
23388      * Returns true if nested scrolling is enabled for this view.
23389      *
23390      * <p>If nested scrolling is enabled and this View class implementation supports it,
23391      * this view will act as a nested scrolling child view when applicable, forwarding data
23392      * about the scroll operation in progress to a compatible and cooperating nested scrolling
23393      * parent.</p>
23394      *
23395      * @return true if nested scrolling is enabled
23396      *
23397      * @see #setNestedScrollingEnabled(boolean)
23398      */
23399     public boolean isNestedScrollingEnabled() {
23400         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
23401                 PFLAG3_NESTED_SCROLLING_ENABLED;
23402     }
23403 
23404     /**
23405      * Begin a nestable scroll operation along the given axes.
23406      *
23407      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
23408      *
23409      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
23410      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
23411      * In the case of touch scrolling the nested scroll will be terminated automatically in
23412      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
23413      * In the event of programmatic scrolling the caller must explicitly call
23414      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
23415      *
23416      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
23417      * If it returns false the caller may ignore the rest of this contract until the next scroll.
23418      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
23419      *
23420      * <p>At each incremental step of the scroll the caller should invoke
23421      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
23422      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
23423      * parent at least partially consumed the scroll and the caller should adjust the amount it
23424      * scrolls by.</p>
23425      *
23426      * <p>After applying the remainder of the scroll delta the caller should invoke
23427      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
23428      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
23429      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
23430      * </p>
23431      *
23432      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
23433      *             {@link #SCROLL_AXIS_VERTICAL}.
23434      * @return true if a cooperative parent was found and nested scrolling has been enabled for
23435      *         the current gesture.
23436      *
23437      * @see #stopNestedScroll()
23438      * @see #dispatchNestedPreScroll(int, int, int[], int[])
23439      * @see #dispatchNestedScroll(int, int, int, int, int[])
23440      */
23441     public boolean startNestedScroll(int axes) {
23442         if (hasNestedScrollingParent()) {
23443             // Already in progress
23444             return true;
23445         }
23446         if (isNestedScrollingEnabled()) {
23447             ViewParent p = getParent();
23448             View child = this;
23449             while (p != null) {
23450                 try {
23451                     if (p.onStartNestedScroll(child, this, axes)) {
23452                         mNestedScrollingParent = p;
23453                         p.onNestedScrollAccepted(child, this, axes);
23454                         return true;
23455                     }
23456                 } catch (AbstractMethodError e) {
23457                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
23458                             "method onStartNestedScroll", e);
23459                     // Allow the search upward to continue
23460                 }
23461                 if (p instanceof View) {
23462                     child = (View) p;
23463                 }
23464                 p = p.getParent();
23465             }
23466         }
23467         return false;
23468     }
23469 
23470     /**
23471      * Stop a nested scroll in progress.
23472      *
23473      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
23474      *
23475      * @see #startNestedScroll(int)
23476      */
23477     public void stopNestedScroll() {
23478         if (mNestedScrollingParent != null) {
23479             mNestedScrollingParent.onStopNestedScroll(this);
23480             mNestedScrollingParent = null;
23481         }
23482     }
23483 
23484     /**
23485      * Returns true if this view has a nested scrolling parent.
23486      *
23487      * <p>The presence of a nested scrolling parent indicates that this view has initiated
23488      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
23489      *
23490      * @return whether this view has a nested scrolling parent
23491      */
23492     public boolean hasNestedScrollingParent() {
23493         return mNestedScrollingParent != null;
23494     }
23495 
23496     /**
23497      * Dispatch one step of a nested scroll in progress.
23498      *
23499      * <p>Implementations of views that support nested scrolling should call this to report
23500      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23501      * is not currently in progress or nested scrolling is not
23502      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23503      *
23504      * <p>Compatible View implementations should also call
23505      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23506      * consuming a component of the scroll event themselves.</p>
23507      *
23508      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23509      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23510      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23511      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23512      * @param offsetInWindow Optional. If not null, on return this will contain the offset
23513      *                       in local view coordinates of this view from before this operation
23514      *                       to after it completes. View implementations may use this to adjust
23515      *                       expected input coordinate tracking.
23516      * @return true if the event was dispatched, false if it could not be dispatched.
23517      * @see #dispatchNestedPreScroll(int, int, int[], int[])
23518      */
23519     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23520             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23521         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23522             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23523                 int startX = 0;
23524                 int startY = 0;
23525                 if (offsetInWindow != null) {
23526                     getLocationInWindow(offsetInWindow);
23527                     startX = offsetInWindow[0];
23528                     startY = offsetInWindow[1];
23529                 }
23530 
23531                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23532                         dxUnconsumed, dyUnconsumed);
23533 
23534                 if (offsetInWindow != null) {
23535                     getLocationInWindow(offsetInWindow);
23536                     offsetInWindow[0] -= startX;
23537                     offsetInWindow[1] -= startY;
23538                 }
23539                 return true;
23540             } else if (offsetInWindow != null) {
23541                 // No motion, no dispatch. Keep offsetInWindow up to date.
23542                 offsetInWindow[0] = 0;
23543                 offsetInWindow[1] = 0;
23544             }
23545         }
23546         return false;
23547     }
23548 
23549     /**
23550      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23551      *
23552      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23553      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23554      * scrolling operation to consume some or all of the scroll operation before the child view
23555      * consumes it.</p>
23556      *
23557      * @param dx Horizontal scroll distance in pixels
23558      * @param dy Vertical scroll distance in pixels
23559      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23560      *                 and consumed[1] the consumed dy.
23561      * @param offsetInWindow Optional. If not null, on return this will contain the offset
23562      *                       in local view coordinates of this view from before this operation
23563      *                       to after it completes. View implementations may use this to adjust
23564      *                       expected input coordinate tracking.
23565      * @return true if the parent consumed some or all of the scroll delta
23566      * @see #dispatchNestedScroll(int, int, int, int, int[])
23567      */
23568     public boolean dispatchNestedPreScroll(int dx, int dy,
23569             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23570         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23571             if (dx != 0 || dy != 0) {
23572                 int startX = 0;
23573                 int startY = 0;
23574                 if (offsetInWindow != null) {
23575                     getLocationInWindow(offsetInWindow);
23576                     startX = offsetInWindow[0];
23577                     startY = offsetInWindow[1];
23578                 }
23579 
23580                 if (consumed == null) {
23581                     if (mTempNestedScrollConsumed == null) {
23582                         mTempNestedScrollConsumed = new int[2];
23583                     }
23584                     consumed = mTempNestedScrollConsumed;
23585                 }
23586                 consumed[0] = 0;
23587                 consumed[1] = 0;
23588                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23589 
23590                 if (offsetInWindow != null) {
23591                     getLocationInWindow(offsetInWindow);
23592                     offsetInWindow[0] -= startX;
23593                     offsetInWindow[1] -= startY;
23594                 }
23595                 return consumed[0] != 0 || consumed[1] != 0;
23596             } else if (offsetInWindow != null) {
23597                 offsetInWindow[0] = 0;
23598                 offsetInWindow[1] = 0;
23599             }
23600         }
23601         return false;
23602     }
23603 
23604     /**
23605      * Dispatch a fling to a nested scrolling parent.
23606      *
23607      * <p>This method should be used to indicate that a nested scrolling child has detected
23608      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23609      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23610      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23611      * along a scrollable axis.</p>
23612      *
23613      * <p>If a nested scrolling child view would normally fling but it is at the edge of
23614      * its own content, it can use this method to delegate the fling to its nested scrolling
23615      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23616      *
23617      * @param velocityX Horizontal fling velocity in pixels per second
23618      * @param velocityY Vertical fling velocity in pixels per second
23619      * @param consumed true if the child consumed the fling, false otherwise
23620      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23621      */
23622     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23623         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23624             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23625         }
23626         return false;
23627     }
23628 
23629     /**
23630      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23631      *
23632      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23633      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23634      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23635      * before the child view consumes it. If this method returns <code>true</code>, a nested
23636      * parent view consumed the fling and this view should not scroll as a result.</p>
23637      *
23638      * <p>For a better user experience, only one view in a nested scrolling chain should consume
23639      * the fling at a time. If a parent view consumed the fling this method will return false.
23640      * Custom view implementations should account for this in two ways:</p>
23641      *
23642      * <ul>
23643      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23644      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23645      *     position regardless.</li>
23646      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23647      *     even to settle back to a valid idle position.</li>
23648      * </ul>
23649      *
23650      * <p>Views should also not offer fling velocities to nested parent views along an axis
23651      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23652      * should not offer a horizontal fling velocity to its parents since scrolling along that
23653      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23654      *
23655      * @param velocityX Horizontal fling velocity in pixels per second
23656      * @param velocityY Vertical fling velocity in pixels per second
23657      * @return true if a nested scrolling parent consumed the fling
23658      */
23659     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23660         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23661             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23662         }
23663         return false;
23664     }
23665 
23666     /**
23667      * Gets a scale factor that determines the distance the view should scroll
23668      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23669      * @return The vertical scroll scale factor.
23670      * @hide
23671      */
23672     protected float getVerticalScrollFactor() {
23673         if (mVerticalScrollFactor == 0) {
23674             TypedValue outValue = new TypedValue();
23675             if (!mContext.getTheme().resolveAttribute(
23676                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23677                 throw new IllegalStateException(
23678                         "Expected theme to define listPreferredItemHeight.");
23679             }
23680             mVerticalScrollFactor = outValue.getDimension(
23681                     mContext.getResources().getDisplayMetrics());
23682         }
23683         return mVerticalScrollFactor;
23684     }
23685 
23686     /**
23687      * Gets a scale factor that determines the distance the view should scroll
23688      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23689      * @return The horizontal scroll scale factor.
23690      * @hide
23691      */
23692     protected float getHorizontalScrollFactor() {
23693         // TODO: Should use something else.
23694         return getVerticalScrollFactor();
23695     }
23696 
23697     /**
23698      * Return the value specifying the text direction or policy that was set with
23699      * {@link #setTextDirection(int)}.
23700      *
23701      * @return the defined text direction. It can be one of:
23702      *
23703      * {@link #TEXT_DIRECTION_INHERIT},
23704      * {@link #TEXT_DIRECTION_FIRST_STRONG},
23705      * {@link #TEXT_DIRECTION_ANY_RTL},
23706      * {@link #TEXT_DIRECTION_LTR},
23707      * {@link #TEXT_DIRECTION_RTL},
23708      * {@link #TEXT_DIRECTION_LOCALE},
23709      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23710      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23711      *
23712      * @attr ref android.R.styleable#View_textDirection
23713      *
23714      * @hide
23715      */
23716     @ViewDebug.ExportedProperty(category = "text", mapping = {
23717             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23718             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23719             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23720             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23721             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23722             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23723             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23724             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23725     })
23726     public int getRawTextDirection() {
23727         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23728     }
23729 
23730     /**
23731      * Set the text direction.
23732      *
23733      * @param textDirection the direction to set. Should be one of:
23734      *
23735      * {@link #TEXT_DIRECTION_INHERIT},
23736      * {@link #TEXT_DIRECTION_FIRST_STRONG},
23737      * {@link #TEXT_DIRECTION_ANY_RTL},
23738      * {@link #TEXT_DIRECTION_LTR},
23739      * {@link #TEXT_DIRECTION_RTL},
23740      * {@link #TEXT_DIRECTION_LOCALE}
23741      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23742      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23743      *
23744      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23745      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23746      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23747      *
23748      * @attr ref android.R.styleable#View_textDirection
23749      */
23750     public void setTextDirection(int textDirection) {
23751         if (getRawTextDirection() != textDirection) {
23752             // Reset the current text direction and the resolved one
23753             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23754             resetResolvedTextDirection();
23755             // Set the new text direction
23756             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23757             // Do resolution
23758             resolveTextDirection();
23759             // Notify change
23760             onRtlPropertiesChanged(getLayoutDirection());
23761             // Refresh
23762             requestLayout();
23763             invalidate(true);
23764         }
23765     }
23766 
23767     /**
23768      * Return the resolved text direction.
23769      *
23770      * @return the resolved text direction. Returns one of:
23771      *
23772      * {@link #TEXT_DIRECTION_FIRST_STRONG},
23773      * {@link #TEXT_DIRECTION_ANY_RTL},
23774      * {@link #TEXT_DIRECTION_LTR},
23775      * {@link #TEXT_DIRECTION_RTL},
23776      * {@link #TEXT_DIRECTION_LOCALE},
23777      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23778      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23779      *
23780      * @attr ref android.R.styleable#View_textDirection
23781      */
23782     @ViewDebug.ExportedProperty(category = "text", mapping = {
23783             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23784             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23785             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23786             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23787             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23788             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23789             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23790             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23791     })
23792     public int getTextDirection() {
23793         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23794     }
23795 
23796     /**
23797      * Resolve the text direction.
23798      *
23799      * @return true if resolution has been done, false otherwise.
23800      *
23801      * @hide
23802      */
23803     public boolean resolveTextDirection() {
23804         // Reset any previous text direction resolution
23805         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23806 
23807         if (hasRtlSupport()) {
23808             // Set resolved text direction flag depending on text direction flag
23809             final int textDirection = getRawTextDirection();
23810             switch(textDirection) {
23811                 case TEXT_DIRECTION_INHERIT:
23812                     if (!canResolveTextDirection()) {
23813                         // We cannot do the resolution if there is no parent, so use the default one
23814                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23815                         // Resolution will need to happen again later
23816                         return false;
23817                     }
23818 
23819                     // Parent has not yet resolved, so we still return the default
23820                     try {
23821                         if (!mParent.isTextDirectionResolved()) {
23822                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23823                             // Resolution will need to happen again later
23824                             return false;
23825                         }
23826                     } catch (AbstractMethodError e) {
23827                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23828                                 " does not fully implement ViewParent", e);
23829                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23830                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23831                         return true;
23832                     }
23833 
23834                     // Set current resolved direction to the same value as the parent's one
23835                     int parentResolvedDirection;
23836                     try {
23837                         parentResolvedDirection = mParent.getTextDirection();
23838                     } catch (AbstractMethodError e) {
23839                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23840                                 " does not fully implement ViewParent", e);
23841                         parentResolvedDirection = TEXT_DIRECTION_LTR;
23842                     }
23843                     switch (parentResolvedDirection) {
23844                         case TEXT_DIRECTION_FIRST_STRONG:
23845                         case TEXT_DIRECTION_ANY_RTL:
23846                         case TEXT_DIRECTION_LTR:
23847                         case TEXT_DIRECTION_RTL:
23848                         case TEXT_DIRECTION_LOCALE:
23849                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
23850                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
23851                             mPrivateFlags2 |=
23852                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23853                             break;
23854                         default:
23855                             // Default resolved direction is "first strong" heuristic
23856                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23857                     }
23858                     break;
23859                 case TEXT_DIRECTION_FIRST_STRONG:
23860                 case TEXT_DIRECTION_ANY_RTL:
23861                 case TEXT_DIRECTION_LTR:
23862                 case TEXT_DIRECTION_RTL:
23863                 case TEXT_DIRECTION_LOCALE:
23864                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
23865                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
23866                     // Resolved direction is the same as text direction
23867                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23868                     break;
23869                 default:
23870                     // Default resolved direction is "first strong" heuristic
23871                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23872             }
23873         } else {
23874             // Default resolved direction is "first strong" heuristic
23875             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23876         }
23877 
23878         // Set to resolved
23879         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23880         return true;
23881     }
23882 
23883     /**
23884      * Check if text direction resolution can be done.
23885      *
23886      * @return true if text direction resolution can be done otherwise return false.
23887      */
23888     public boolean canResolveTextDirection() {
23889         switch (getRawTextDirection()) {
23890             case TEXT_DIRECTION_INHERIT:
23891                 if (mParent != null) {
23892                     try {
23893                         return mParent.canResolveTextDirection();
23894                     } catch (AbstractMethodError e) {
23895                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23896                                 " does not fully implement ViewParent", e);
23897                     }
23898                 }
23899                 return false;
23900 
23901             default:
23902                 return true;
23903         }
23904     }
23905 
23906     /**
23907      * Reset resolved text direction. Text direction will be resolved during a call to
23908      * {@link #onMeasure(int, int)}.
23909      *
23910      * @hide
23911      */
23912     public void resetResolvedTextDirection() {
23913         // Reset any previous text direction resolution
23914         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23915         // Set to default value
23916         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23917     }
23918 
23919     /**
23920      * @return true if text direction is inherited.
23921      *
23922      * @hide
23923      */
23924     public boolean isTextDirectionInherited() {
23925         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23926     }
23927 
23928     /**
23929      * @return true if text direction is resolved.
23930      */
23931     public boolean isTextDirectionResolved() {
23932         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23933     }
23934 
23935     /**
23936      * Return the value specifying the text alignment or policy that was set with
23937      * {@link #setTextAlignment(int)}.
23938      *
23939      * @return the defined text alignment. It can be one of:
23940      *
23941      * {@link #TEXT_ALIGNMENT_INHERIT},
23942      * {@link #TEXT_ALIGNMENT_GRAVITY},
23943      * {@link #TEXT_ALIGNMENT_CENTER},
23944      * {@link #TEXT_ALIGNMENT_TEXT_START},
23945      * {@link #TEXT_ALIGNMENT_TEXT_END},
23946      * {@link #TEXT_ALIGNMENT_VIEW_START},
23947      * {@link #TEXT_ALIGNMENT_VIEW_END}
23948      *
23949      * @attr ref android.R.styleable#View_textAlignment
23950      *
23951      * @hide
23952      */
23953     @ViewDebug.ExportedProperty(category = "text", mapping = {
23954             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23955             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23956             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23957             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23958             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23959             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23960             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23961     })
23962     @TextAlignment
23963     public int getRawTextAlignment() {
23964         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23965     }
23966 
23967     /**
23968      * Set the text alignment.
23969      *
23970      * @param textAlignment The text alignment to set. Should be one of
23971      *
23972      * {@link #TEXT_ALIGNMENT_INHERIT},
23973      * {@link #TEXT_ALIGNMENT_GRAVITY},
23974      * {@link #TEXT_ALIGNMENT_CENTER},
23975      * {@link #TEXT_ALIGNMENT_TEXT_START},
23976      * {@link #TEXT_ALIGNMENT_TEXT_END},
23977      * {@link #TEXT_ALIGNMENT_VIEW_START},
23978      * {@link #TEXT_ALIGNMENT_VIEW_END}
23979      *
23980      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23981      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23982      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23983      *
23984      * @attr ref android.R.styleable#View_textAlignment
23985      */
23986     public void setTextAlignment(@TextAlignment int textAlignment) {
23987         if (textAlignment != getRawTextAlignment()) {
23988             // Reset the current and resolved text alignment
23989             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23990             resetResolvedTextAlignment();
23991             // Set the new text alignment
23992             mPrivateFlags2 |=
23993                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23994             // Do resolution
23995             resolveTextAlignment();
23996             // Notify change
23997             onRtlPropertiesChanged(getLayoutDirection());
23998             // Refresh
23999             requestLayout();
24000             invalidate(true);
24001         }
24002     }
24003 
24004     /**
24005      * Return the resolved text alignment.
24006      *
24007      * @return the resolved text alignment. Returns one of:
24008      *
24009      * {@link #TEXT_ALIGNMENT_GRAVITY},
24010      * {@link #TEXT_ALIGNMENT_CENTER},
24011      * {@link #TEXT_ALIGNMENT_TEXT_START},
24012      * {@link #TEXT_ALIGNMENT_TEXT_END},
24013      * {@link #TEXT_ALIGNMENT_VIEW_START},
24014      * {@link #TEXT_ALIGNMENT_VIEW_END}
24015      *
24016      * @attr ref android.R.styleable#View_textAlignment
24017      */
24018     @ViewDebug.ExportedProperty(category = "text", mapping = {
24019             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
24020             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
24021             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
24022             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
24023             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
24024             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
24025             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
24026     })
24027     @TextAlignment
24028     public int getTextAlignment() {
24029         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
24030                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
24031     }
24032 
24033     /**
24034      * Resolve the text alignment.
24035      *
24036      * @return true if resolution has been done, false otherwise.
24037      *
24038      * @hide
24039      */
24040     public boolean resolveTextAlignment() {
24041         // Reset any previous text alignment resolution
24042         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
24043 
24044         if (hasRtlSupport()) {
24045             // Set resolved text alignment flag depending on text alignment flag
24046             final int textAlignment = getRawTextAlignment();
24047             switch (textAlignment) {
24048                 case TEXT_ALIGNMENT_INHERIT:
24049                     // Check if we can resolve the text alignment
24050                     if (!canResolveTextAlignment()) {
24051                         // We cannot do the resolution if there is no parent so use the default
24052                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24053                         // Resolution will need to happen again later
24054                         return false;
24055                     }
24056 
24057                     // Parent has not yet resolved, so we still return the default
24058                     try {
24059                         if (!mParent.isTextAlignmentResolved()) {
24060                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24061                             // Resolution will need to happen again later
24062                             return false;
24063                         }
24064                     } catch (AbstractMethodError e) {
24065                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24066                                 " does not fully implement ViewParent", e);
24067                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
24068                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24069                         return true;
24070                     }
24071 
24072                     int parentResolvedTextAlignment;
24073                     try {
24074                         parentResolvedTextAlignment = mParent.getTextAlignment();
24075                     } catch (AbstractMethodError e) {
24076                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24077                                 " does not fully implement ViewParent", e);
24078                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
24079                     }
24080                     switch (parentResolvedTextAlignment) {
24081                         case TEXT_ALIGNMENT_GRAVITY:
24082                         case TEXT_ALIGNMENT_TEXT_START:
24083                         case TEXT_ALIGNMENT_TEXT_END:
24084                         case TEXT_ALIGNMENT_CENTER:
24085                         case TEXT_ALIGNMENT_VIEW_START:
24086                         case TEXT_ALIGNMENT_VIEW_END:
24087                             // Resolved text alignment is the same as the parent resolved
24088                             // text alignment
24089                             mPrivateFlags2 |=
24090                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
24091                             break;
24092                         default:
24093                             // Use default resolved text alignment
24094                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24095                     }
24096                     break;
24097                 case TEXT_ALIGNMENT_GRAVITY:
24098                 case TEXT_ALIGNMENT_TEXT_START:
24099                 case TEXT_ALIGNMENT_TEXT_END:
24100                 case TEXT_ALIGNMENT_CENTER:
24101                 case TEXT_ALIGNMENT_VIEW_START:
24102                 case TEXT_ALIGNMENT_VIEW_END:
24103                     // Resolved text alignment is the same as text alignment
24104                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
24105                     break;
24106                 default:
24107                     // Use default resolved text alignment
24108                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24109             }
24110         } else {
24111             // Use default resolved text alignment
24112             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24113         }
24114 
24115         // Set the resolved
24116         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24117         return true;
24118     }
24119 
24120     /**
24121      * Check if text alignment resolution can be done.
24122      *
24123      * @return true if text alignment resolution can be done otherwise return false.
24124      */
24125     public boolean canResolveTextAlignment() {
24126         switch (getRawTextAlignment()) {
24127             case TEXT_DIRECTION_INHERIT:
24128                 if (mParent != null) {
24129                     try {
24130                         return mParent.canResolveTextAlignment();
24131                     } catch (AbstractMethodError e) {
24132                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24133                                 " does not fully implement ViewParent", e);
24134                     }
24135                 }
24136                 return false;
24137 
24138             default:
24139                 return true;
24140         }
24141     }
24142 
24143     /**
24144      * Reset resolved text alignment. Text alignment will be resolved during a call to
24145      * {@link #onMeasure(int, int)}.
24146      *
24147      * @hide
24148      */
24149     public void resetResolvedTextAlignment() {
24150         // Reset any previous text alignment resolution
24151         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
24152         // Set to default
24153         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24154     }
24155 
24156     /**
24157      * @return true if text alignment is inherited.
24158      *
24159      * @hide
24160      */
24161     public boolean isTextAlignmentInherited() {
24162         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
24163     }
24164 
24165     /**
24166      * @return true if text alignment is resolved.
24167      */
24168     public boolean isTextAlignmentResolved() {
24169         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24170     }
24171 
24172     /**
24173      * Generate a value suitable for use in {@link #setId(int)}.
24174      * This value will not collide with ID values generated at build time by aapt for R.id.
24175      *
24176      * @return a generated ID value
24177      */
24178     public static int generateViewId() {
24179         for (;;) {
24180             final int result = sNextGeneratedId.get();
24181             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
24182             int newValue = result + 1;
24183             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
24184             if (sNextGeneratedId.compareAndSet(result, newValue)) {
24185                 return result;
24186             }
24187         }
24188     }
24189 
24190     private static boolean isViewIdGenerated(int id) {
24191         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
24192     }
24193 
24194     /**
24195      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
24196      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
24197      *                           a normal View or a ViewGroup with
24198      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
24199      * @hide
24200      */
24201     public void captureTransitioningViews(List<View> transitioningViews) {
24202         if (getVisibility() == View.VISIBLE) {
24203             transitioningViews.add(this);
24204         }
24205     }
24206 
24207     /**
24208      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
24209      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
24210      * @hide
24211      */
24212     public void findNamedViews(Map<String, View> namedElements) {
24213         if (getVisibility() == VISIBLE || mGhostView != null) {
24214             String transitionName = getTransitionName();
24215             if (transitionName != null) {
24216                 namedElements.put(transitionName, this);
24217             }
24218         }
24219     }
24220 
24221     /**
24222      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
24223      * The default implementation does not care the location or event types, but some subclasses
24224      * may use it (such as WebViews).
24225      * @param event The MotionEvent from a mouse
24226      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
24227      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
24228      * @see PointerIcon
24229      */
24230     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
24231         final float x = event.getX(pointerIndex);
24232         final float y = event.getY(pointerIndex);
24233         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
24234             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
24235         }
24236         return mPointerIcon;
24237     }
24238 
24239     /**
24240      * Set the pointer icon for the current view.
24241      * Passing {@code null} will restore the pointer icon to its default value.
24242      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
24243      */
24244     public void setPointerIcon(PointerIcon pointerIcon) {
24245         mPointerIcon = pointerIcon;
24246         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
24247             return;
24248         }
24249         try {
24250             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
24251         } catch (RemoteException e) {
24252         }
24253     }
24254 
24255     /**
24256      * Gets the pointer icon for the current view.
24257      */
24258     public PointerIcon getPointerIcon() {
24259         return mPointerIcon;
24260     }
24261 
24262     /**
24263      * Checks pointer capture status.
24264      *
24265      * @return true if the view has pointer capture.
24266      * @see #requestPointerCapture()
24267      * @see #hasPointerCapture()
24268      */
24269     public boolean hasPointerCapture() {
24270         final ViewRootImpl viewRootImpl = getViewRootImpl();
24271         if (viewRootImpl == null) {
24272             return false;
24273         }
24274         return viewRootImpl.hasPointerCapture();
24275     }
24276 
24277     /**
24278      * Requests pointer capture mode.
24279      * <p>
24280      * When the window has pointer capture, the mouse pointer icon will disappear and will not
24281      * change its position. Further mouse will be dispatched with the source
24282      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
24283      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
24284      * (touchscreens, or stylus) will not be affected.
24285      * <p>
24286      * If the window already has pointer capture, this call does nothing.
24287      * <p>
24288      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
24289      * automatically when the window loses focus.
24290      *
24291      * @see #releasePointerCapture()
24292      * @see #hasPointerCapture()
24293      */
24294     public void requestPointerCapture() {
24295         final ViewRootImpl viewRootImpl = getViewRootImpl();
24296         if (viewRootImpl != null) {
24297             viewRootImpl.requestPointerCapture(true);
24298         }
24299     }
24300 
24301 
24302     /**
24303      * Releases the pointer capture.
24304      * <p>
24305      * If the window does not have pointer capture, this call will do nothing.
24306      * @see #requestPointerCapture()
24307      * @see #hasPointerCapture()
24308      */
24309     public void releasePointerCapture() {
24310         final ViewRootImpl viewRootImpl = getViewRootImpl();
24311         if (viewRootImpl != null) {
24312             viewRootImpl.requestPointerCapture(false);
24313         }
24314     }
24315 
24316     /**
24317      * Called when the window has just acquired or lost pointer capture.
24318      *
24319      * @param hasCapture True if the view now has pointerCapture, false otherwise.
24320      */
24321     @CallSuper
24322     public void onPointerCaptureChange(boolean hasCapture) {
24323     }
24324 
24325     /**
24326      * @see #onPointerCaptureChange
24327      */
24328     public void dispatchPointerCaptureChanged(boolean hasCapture) {
24329         onPointerCaptureChange(hasCapture);
24330     }
24331 
24332     /**
24333      * Implement this method to handle captured pointer events
24334      *
24335      * @param event The captured pointer event.
24336      * @return True if the event was handled, false otherwise.
24337      * @see #requestPointerCapture()
24338      */
24339     public boolean onCapturedPointerEvent(MotionEvent event) {
24340         return false;
24341     }
24342 
24343     /**
24344      * Interface definition for a callback to be invoked when a captured pointer event
24345      * is being dispatched this view. The callback will be invoked before the event is
24346      * given to the view.
24347      */
24348     public interface OnCapturedPointerListener {
24349         /**
24350          * Called when a captured pointer event is dispatched to a view.
24351          * @param view The view this event has been dispatched to.
24352          * @param event The captured event.
24353          * @return True if the listener has consumed the event, false otherwise.
24354          */
24355         boolean onCapturedPointer(View view, MotionEvent event);
24356     }
24357 
24358     /**
24359      * Set a listener to receive callbacks when the pointer capture state of a view changes.
24360      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
24361      */
24362     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
24363         getListenerInfo().mOnCapturedPointerListener = l;
24364     }
24365 
24366     // Properties
24367     //
24368     /**
24369      * A Property wrapper around the <code>alpha</code> functionality handled by the
24370      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
24371      */
24372     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
24373         @Override
24374         public void setValue(View object, float value) {
24375             object.setAlpha(value);
24376         }
24377 
24378         @Override
24379         public Float get(View object) {
24380             return object.getAlpha();
24381         }
24382     };
24383 
24384     /**
24385      * A Property wrapper around the <code>translationX</code> functionality handled by the
24386      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
24387      */
24388     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
24389         @Override
24390         public void setValue(View object, float value) {
24391             object.setTranslationX(value);
24392         }
24393 
24394                 @Override
24395         public Float get(View object) {
24396             return object.getTranslationX();
24397         }
24398     };
24399 
24400     /**
24401      * A Property wrapper around the <code>translationY</code> functionality handled by the
24402      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
24403      */
24404     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
24405         @Override
24406         public void setValue(View object, float value) {
24407             object.setTranslationY(value);
24408         }
24409 
24410         @Override
24411         public Float get(View object) {
24412             return object.getTranslationY();
24413         }
24414     };
24415 
24416     /**
24417      * A Property wrapper around the <code>translationZ</code> functionality handled by the
24418      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
24419      */
24420     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
24421         @Override
24422         public void setValue(View object, float value) {
24423             object.setTranslationZ(value);
24424         }
24425 
24426         @Override
24427         public Float get(View object) {
24428             return object.getTranslationZ();
24429         }
24430     };
24431 
24432     /**
24433      * A Property wrapper around the <code>x</code> functionality handled by the
24434      * {@link View#setX(float)} and {@link View#getX()} methods.
24435      */
24436     public static final Property<View, Float> X = new FloatProperty<View>("x") {
24437         @Override
24438         public void setValue(View object, float value) {
24439             object.setX(value);
24440         }
24441 
24442         @Override
24443         public Float get(View object) {
24444             return object.getX();
24445         }
24446     };
24447 
24448     /**
24449      * A Property wrapper around the <code>y</code> functionality handled by the
24450      * {@link View#setY(float)} and {@link View#getY()} methods.
24451      */
24452     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
24453         @Override
24454         public void setValue(View object, float value) {
24455             object.setY(value);
24456         }
24457 
24458         @Override
24459         public Float get(View object) {
24460             return object.getY();
24461         }
24462     };
24463 
24464     /**
24465      * A Property wrapper around the <code>z</code> functionality handled by the
24466      * {@link View#setZ(float)} and {@link View#getZ()} methods.
24467      */
24468     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
24469         @Override
24470         public void setValue(View object, float value) {
24471             object.setZ(value);
24472         }
24473 
24474         @Override
24475         public Float get(View object) {
24476             return object.getZ();
24477         }
24478     };
24479 
24480     /**
24481      * A Property wrapper around the <code>rotation</code> functionality handled by the
24482      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
24483      */
24484     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
24485         @Override
24486         public void setValue(View object, float value) {
24487             object.setRotation(value);
24488         }
24489 
24490         @Override
24491         public Float get(View object) {
24492             return object.getRotation();
24493         }
24494     };
24495 
24496     /**
24497      * A Property wrapper around the <code>rotationX</code> functionality handled by the
24498      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24499      */
24500     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24501         @Override
24502         public void setValue(View object, float value) {
24503             object.setRotationX(value);
24504         }
24505 
24506         @Override
24507         public Float get(View object) {
24508             return object.getRotationX();
24509         }
24510     };
24511 
24512     /**
24513      * A Property wrapper around the <code>rotationY</code> functionality handled by the
24514      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24515      */
24516     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24517         @Override
24518         public void setValue(View object, float value) {
24519             object.setRotationY(value);
24520         }
24521 
24522         @Override
24523         public Float get(View object) {
24524             return object.getRotationY();
24525         }
24526     };
24527 
24528     /**
24529      * A Property wrapper around the <code>scaleX</code> functionality handled by the
24530      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24531      */
24532     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24533         @Override
24534         public void setValue(View object, float value) {
24535             object.setScaleX(value);
24536         }
24537 
24538         @Override
24539         public Float get(View object) {
24540             return object.getScaleX();
24541         }
24542     };
24543 
24544     /**
24545      * A Property wrapper around the <code>scaleY</code> functionality handled by the
24546      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24547      */
24548     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24549         @Override
24550         public void setValue(View object, float value) {
24551             object.setScaleY(value);
24552         }
24553 
24554         @Override
24555         public Float get(View object) {
24556             return object.getScaleY();
24557         }
24558     };
24559 
24560     /**
24561      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24562      * Each MeasureSpec represents a requirement for either the width or the height.
24563      * A MeasureSpec is comprised of a size and a mode. There are three possible
24564      * modes:
24565      * <dl>
24566      * <dt>UNSPECIFIED</dt>
24567      * <dd>
24568      * The parent has not imposed any constraint on the child. It can be whatever size
24569      * it wants.
24570      * </dd>
24571      *
24572      * <dt>EXACTLY</dt>
24573      * <dd>
24574      * The parent has determined an exact size for the child. The child is going to be
24575      * given those bounds regardless of how big it wants to be.
24576      * </dd>
24577      *
24578      * <dt>AT_MOST</dt>
24579      * <dd>
24580      * The child can be as large as it wants up to the specified size.
24581      * </dd>
24582      * </dl>
24583      *
24584      * MeasureSpecs are implemented as ints to reduce object allocation. This class
24585      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24586      */
24587     public static class MeasureSpec {
24588         private static final int MODE_SHIFT = 30;
24589         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24590 
24591         /** @hide */
24592         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24593         @Retention(RetentionPolicy.SOURCE)
24594         public @interface MeasureSpecMode {}
24595 
24596         /**
24597          * Measure specification mode: The parent has not imposed any constraint
24598          * on the child. It can be whatever size it wants.
24599          */
24600         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24601 
24602         /**
24603          * Measure specification mode: The parent has determined an exact size
24604          * for the child. The child is going to be given those bounds regardless
24605          * of how big it wants to be.
24606          */
24607         public static final int EXACTLY     = 1 << MODE_SHIFT;
24608 
24609         /**
24610          * Measure specification mode: The child can be as large as it wants up
24611          * to the specified size.
24612          */
24613         public static final int AT_MOST     = 2 << MODE_SHIFT;
24614 
24615         /**
24616          * Creates a measure specification based on the supplied size and mode.
24617          *
24618          * The mode must always be one of the following:
24619          * <ul>
24620          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24621          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24622          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24623          * </ul>
24624          *
24625          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24626          * implementation was such that the order of arguments did not matter
24627          * and overflow in either value could impact the resulting MeasureSpec.
24628          * {@link android.widget.RelativeLayout} was affected by this bug.
24629          * Apps targeting API levels greater than 17 will get the fixed, more strict
24630          * behavior.</p>
24631          *
24632          * @param size the size of the measure specification
24633          * @param mode the mode of the measure specification
24634          * @return the measure specification based on size and mode
24635          */
24636         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24637                                           @MeasureSpecMode int mode) {
24638             if (sUseBrokenMakeMeasureSpec) {
24639                 return size + mode;
24640             } else {
24641                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
24642             }
24643         }
24644 
24645         /**
24646          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24647          * will automatically get a size of 0. Older apps expect this.
24648          *
24649          * @hide internal use only for compatibility with system widgets and older apps
24650          */
24651         public static int makeSafeMeasureSpec(int size, int mode) {
24652             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24653                 return 0;
24654             }
24655             return makeMeasureSpec(size, mode);
24656         }
24657 
24658         /**
24659          * Extracts the mode from the supplied measure specification.
24660          *
24661          * @param measureSpec the measure specification to extract the mode from
24662          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24663          *         {@link android.view.View.MeasureSpec#AT_MOST} or
24664          *         {@link android.view.View.MeasureSpec#EXACTLY}
24665          */
24666         @MeasureSpecMode
24667         public static int getMode(int measureSpec) {
24668             //noinspection ResourceType
24669             return (measureSpec & MODE_MASK);
24670         }
24671 
24672         /**
24673          * Extracts the size from the supplied measure specification.
24674          *
24675          * @param measureSpec the measure specification to extract the size from
24676          * @return the size in pixels defined in the supplied measure specification
24677          */
24678         public static int getSize(int measureSpec) {
24679             return (measureSpec & ~MODE_MASK);
24680         }
24681 
24682         static int adjust(int measureSpec, int delta) {
24683             final int mode = getMode(measureSpec);
24684             int size = getSize(measureSpec);
24685             if (mode == UNSPECIFIED) {
24686                 // No need to adjust size for UNSPECIFIED mode.
24687                 return makeMeasureSpec(size, UNSPECIFIED);
24688             }
24689             size += delta;
24690             if (size < 0) {
24691                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24692                         ") spec: " + toString(measureSpec) + " delta: " + delta);
24693                 size = 0;
24694             }
24695             return makeMeasureSpec(size, mode);
24696         }
24697 
24698         /**
24699          * Returns a String representation of the specified measure
24700          * specification.
24701          *
24702          * @param measureSpec the measure specification to convert to a String
24703          * @return a String with the following format: "MeasureSpec: MODE SIZE"
24704          */
24705         public static String toString(int measureSpec) {
24706             int mode = getMode(measureSpec);
24707             int size = getSize(measureSpec);
24708 
24709             StringBuilder sb = new StringBuilder("MeasureSpec: ");
24710 
24711             if (mode == UNSPECIFIED)
24712                 sb.append("UNSPECIFIED ");
24713             else if (mode == EXACTLY)
24714                 sb.append("EXACTLY ");
24715             else if (mode == AT_MOST)
24716                 sb.append("AT_MOST ");
24717             else
24718                 sb.append(mode).append(" ");
24719 
24720             sb.append(size);
24721             return sb.toString();
24722         }
24723     }
24724 
24725     private final class CheckForLongPress implements Runnable {
24726         private int mOriginalWindowAttachCount;
24727         private float mX;
24728         private float mY;
24729         private boolean mOriginalPressedState;
24730 
24731         @Override
24732         public void run() {
24733             if ((mOriginalPressedState == isPressed()) && (mParent != null)
24734                     && mOriginalWindowAttachCount == mWindowAttachCount) {
24735                 if (performLongClick(mX, mY)) {
24736                     mHasPerformedLongPress = true;
24737                 }
24738             }
24739         }
24740 
24741         public void setAnchor(float x, float y) {
24742             mX = x;
24743             mY = y;
24744         }
24745 
24746         public void rememberWindowAttachCount() {
24747             mOriginalWindowAttachCount = mWindowAttachCount;
24748         }
24749 
24750         public void rememberPressedState() {
24751             mOriginalPressedState = isPressed();
24752         }
24753     }
24754 
24755     private final class CheckForTap implements Runnable {
24756         public float x;
24757         public float y;
24758 
24759         @Override
24760         public void run() {
24761             mPrivateFlags &= ~PFLAG_PREPRESSED;
24762             setPressed(true, x, y);
24763             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24764         }
24765     }
24766 
24767     private final class PerformClick implements Runnable {
24768         @Override
24769         public void run() {
24770             performClick();
24771         }
24772     }
24773 
24774     /**
24775      * This method returns a ViewPropertyAnimator object, which can be used to animate
24776      * specific properties on this View.
24777      *
24778      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24779      */
24780     public ViewPropertyAnimator animate() {
24781         if (mAnimator == null) {
24782             mAnimator = new ViewPropertyAnimator(this);
24783         }
24784         return mAnimator;
24785     }
24786 
24787     /**
24788      * Sets the name of the View to be used to identify Views in Transitions.
24789      * Names should be unique in the View hierarchy.
24790      *
24791      * @param transitionName The name of the View to uniquely identify it for Transitions.
24792      */
24793     public final void setTransitionName(String transitionName) {
24794         mTransitionName = transitionName;
24795     }
24796 
24797     /**
24798      * Returns the name of the View to be used to identify Views in Transitions.
24799      * Names should be unique in the View hierarchy.
24800      *
24801      * <p>This returns null if the View has not been given a name.</p>
24802      *
24803      * @return The name used of the View to be used to identify Views in Transitions or null
24804      * if no name has been given.
24805      */
24806     @ViewDebug.ExportedProperty
24807     public String getTransitionName() {
24808         return mTransitionName;
24809     }
24810 
24811     /**
24812      * @hide
24813      */
24814     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24815         // Do nothing.
24816     }
24817 
24818     /**
24819      * Interface definition for a callback to be invoked when a hardware key event is
24820      * dispatched to this view. The callback will be invoked before the key event is
24821      * given to the view. This is only useful for hardware keyboards; a software input
24822      * method has no obligation to trigger this listener.
24823      */
24824     public interface OnKeyListener {
24825         /**
24826          * Called when a hardware key is dispatched to a view. This allows listeners to
24827          * get a chance to respond before the target view.
24828          * <p>Key presses in software keyboards will generally NOT trigger this method,
24829          * although some may elect to do so in some situations. Do not assume a
24830          * software input method has to be key-based; even if it is, it may use key presses
24831          * in a different way than you expect, so there is no way to reliably catch soft
24832          * input key presses.
24833          *
24834          * @param v The view the key has been dispatched to.
24835          * @param keyCode The code for the physical key that was pressed
24836          * @param event The KeyEvent object containing full information about
24837          *        the event.
24838          * @return True if the listener has consumed the event, false otherwise.
24839          */
24840         boolean onKey(View v, int keyCode, KeyEvent event);
24841     }
24842 
24843     /**
24844      * Interface definition for a callback to be invoked when a touch event is
24845      * dispatched to this view. The callback will be invoked before the touch
24846      * event is given to the view.
24847      */
24848     public interface OnTouchListener {
24849         /**
24850          * Called when a touch event is dispatched to a view. This allows listeners to
24851          * get a chance to respond before the target view.
24852          *
24853          * @param v The view the touch event has been dispatched to.
24854          * @param event The MotionEvent object containing full information about
24855          *        the event.
24856          * @return True if the listener has consumed the event, false otherwise.
24857          */
24858         boolean onTouch(View v, MotionEvent event);
24859     }
24860 
24861     /**
24862      * Interface definition for a callback to be invoked when a hover event is
24863      * dispatched to this view. The callback will be invoked before the hover
24864      * event is given to the view.
24865      */
24866     public interface OnHoverListener {
24867         /**
24868          * Called when a hover event is dispatched to a view. This allows listeners to
24869          * get a chance to respond before the target view.
24870          *
24871          * @param v The view the hover event has been dispatched to.
24872          * @param event The MotionEvent object containing full information about
24873          *        the event.
24874          * @return True if the listener has consumed the event, false otherwise.
24875          */
24876         boolean onHover(View v, MotionEvent event);
24877     }
24878 
24879     /**
24880      * Interface definition for a callback to be invoked when a generic motion event is
24881      * dispatched to this view. The callback will be invoked before the generic motion
24882      * event is given to the view.
24883      */
24884     public interface OnGenericMotionListener {
24885         /**
24886          * Called when a generic motion event is dispatched to a view. This allows listeners to
24887          * get a chance to respond before the target view.
24888          *
24889          * @param v The view the generic motion event has been dispatched to.
24890          * @param event The MotionEvent object containing full information about
24891          *        the event.
24892          * @return True if the listener has consumed the event, false otherwise.
24893          */
24894         boolean onGenericMotion(View v, MotionEvent event);
24895     }
24896 
24897     /**
24898      * Interface definition for a callback to be invoked when a view has been clicked and held.
24899      */
24900     public interface OnLongClickListener {
24901         /**
24902          * Called when a view has been clicked and held.
24903          *
24904          * @param v The view that was clicked and held.
24905          *
24906          * @return true if the callback consumed the long click, false otherwise.
24907          */
24908         boolean onLongClick(View v);
24909     }
24910 
24911     /**
24912      * Interface definition for a callback to be invoked when a drag is being dispatched
24913      * to this view.  The callback will be invoked before the hosting view's own
24914      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24915      * onDrag(event) behavior, it should return 'false' from this callback.
24916      *
24917      * <div class="special reference">
24918      * <h3>Developer Guides</h3>
24919      * <p>For a guide to implementing drag and drop features, read the
24920      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24921      * </div>
24922      */
24923     public interface OnDragListener {
24924         /**
24925          * Called when a drag event is dispatched to a view. This allows listeners
24926          * to get a chance to override base View behavior.
24927          *
24928          * @param v The View that received the drag event.
24929          * @param event The {@link android.view.DragEvent} object for the drag event.
24930          * @return {@code true} if the drag event was handled successfully, or {@code false}
24931          * if the drag event was not handled. Note that {@code false} will trigger the View
24932          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24933          */
24934         boolean onDrag(View v, DragEvent event);
24935     }
24936 
24937     /**
24938      * Interface definition for a callback to be invoked when the focus state of
24939      * a view changed.
24940      */
24941     public interface OnFocusChangeListener {
24942         /**
24943          * Called when the focus state of a view has changed.
24944          *
24945          * @param v The view whose state has changed.
24946          * @param hasFocus The new focus state of v.
24947          */
24948         void onFocusChange(View v, boolean hasFocus);
24949     }
24950 
24951     /**
24952      * Interface definition for a callback to be invoked when a view is clicked.
24953      */
24954     public interface OnClickListener {
24955         /**
24956          * Called when a view has been clicked.
24957          *
24958          * @param v The view that was clicked.
24959          */
24960         void onClick(View v);
24961     }
24962 
24963     /**
24964      * Interface definition for a callback to be invoked when a view is context clicked.
24965      */
24966     public interface OnContextClickListener {
24967         /**
24968          * Called when a view is context clicked.
24969          *
24970          * @param v The view that has been context clicked.
24971          * @return true if the callback consumed the context click, false otherwise.
24972          */
24973         boolean onContextClick(View v);
24974     }
24975 
24976     /**
24977      * Interface definition for a callback to be invoked when the context menu
24978      * for this view is being built.
24979      */
24980     public interface OnCreateContextMenuListener {
24981         /**
24982          * Called when the context menu for this view is being built. It is not
24983          * safe to hold onto the menu after this method returns.
24984          *
24985          * @param menu The context menu that is being built
24986          * @param v The view for which the context menu is being built
24987          * @param menuInfo Extra information about the item for which the
24988          *            context menu should be shown. This information will vary
24989          *            depending on the class of v.
24990          */
24991         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24992     }
24993 
24994     /**
24995      * Interface definition for a callback to be invoked when the status bar changes
24996      * visibility.  This reports <strong>global</strong> changes to the system UI
24997      * state, not what the application is requesting.
24998      *
24999      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
25000      */
25001     public interface OnSystemUiVisibilityChangeListener {
25002         /**
25003          * Called when the status bar changes visibility because of a call to
25004          * {@link View#setSystemUiVisibility(int)}.
25005          *
25006          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
25007          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
25008          * This tells you the <strong>global</strong> state of these UI visibility
25009          * flags, not what your app is currently applying.
25010          */
25011         public void onSystemUiVisibilityChange(int visibility);
25012     }
25013 
25014     /**
25015      * Interface definition for a callback to be invoked when this view is attached
25016      * or detached from its window.
25017      */
25018     public interface OnAttachStateChangeListener {
25019         /**
25020          * Called when the view is attached to a window.
25021          * @param v The view that was attached
25022          */
25023         public void onViewAttachedToWindow(View v);
25024         /**
25025          * Called when the view is detached from a window.
25026          * @param v The view that was detached
25027          */
25028         public void onViewDetachedFromWindow(View v);
25029     }
25030 
25031     /**
25032      * Listener for applying window insets on a view in a custom way.
25033      *
25034      * <p>Apps may choose to implement this interface if they want to apply custom policy
25035      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
25036      * is set, its
25037      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
25038      * method will be called instead of the View's own
25039      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
25040      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
25041      * the View's normal behavior as part of its own.</p>
25042      */
25043     public interface OnApplyWindowInsetsListener {
25044         /**
25045          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
25046          * on a View, this listener method will be called instead of the view's own
25047          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
25048          *
25049          * @param v The view applying window insets
25050          * @param insets The insets to apply
25051          * @return The insets supplied, minus any insets that were consumed
25052          */
25053         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
25054     }
25055 
25056     private final class UnsetPressedState implements Runnable {
25057         @Override
25058         public void run() {
25059             setPressed(false);
25060         }
25061     }
25062 
25063     /**
25064      * When a view becomes invisible checks if autofill considers the view invisible too. This
25065      * happens after the regular removal operation to make sure the operation is finished by the
25066      * time this is called.
25067      */
25068     private static class VisibilityChangeForAutofillHandler extends Handler {
25069         private final AutofillManager mAfm;
25070         private final View mView;
25071 
25072         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
25073                 @NonNull View view) {
25074             mAfm = afm;
25075             mView = view;
25076         }
25077 
25078         @Override
25079         public void handleMessage(Message msg) {
25080             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
25081         }
25082     }
25083 
25084     /**
25085      * Base class for derived classes that want to save and restore their own
25086      * state in {@link android.view.View#onSaveInstanceState()}.
25087      */
25088     public static class BaseSavedState extends AbsSavedState {
25089         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
25090         static final int IS_AUTOFILLED = 0b10;
25091         static final int AUTOFILL_ID = 0b100;
25092 
25093         // Flags that describe what data in this state is valid
25094         int mSavedData;
25095         String mStartActivityRequestWhoSaved;
25096         boolean mIsAutofilled;
25097         int mAutofillViewId;
25098 
25099         /**
25100          * Constructor used when reading from a parcel. Reads the state of the superclass.
25101          *
25102          * @param source parcel to read from
25103          */
25104         public BaseSavedState(Parcel source) {
25105             this(source, null);
25106         }
25107 
25108         /**
25109          * Constructor used when reading from a parcel using a given class loader.
25110          * Reads the state of the superclass.
25111          *
25112          * @param source parcel to read from
25113          * @param loader ClassLoader to use for reading
25114          */
25115         public BaseSavedState(Parcel source, ClassLoader loader) {
25116             super(source, loader);
25117             mSavedData = source.readInt();
25118             mStartActivityRequestWhoSaved = source.readString();
25119             mIsAutofilled = source.readBoolean();
25120             mAutofillViewId = source.readInt();
25121         }
25122 
25123         /**
25124          * Constructor called by derived classes when creating their SavedState objects
25125          *
25126          * @param superState The state of the superclass of this view
25127          */
25128         public BaseSavedState(Parcelable superState) {
25129             super(superState);
25130         }
25131 
25132         @Override
25133         public void writeToParcel(Parcel out, int flags) {
25134             super.writeToParcel(out, flags);
25135 
25136             out.writeInt(mSavedData);
25137             out.writeString(mStartActivityRequestWhoSaved);
25138             out.writeBoolean(mIsAutofilled);
25139             out.writeInt(mAutofillViewId);
25140         }
25141 
25142         public static final Parcelable.Creator<BaseSavedState> CREATOR
25143                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
25144             @Override
25145             public BaseSavedState createFromParcel(Parcel in) {
25146                 return new BaseSavedState(in);
25147             }
25148 
25149             @Override
25150             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
25151                 return new BaseSavedState(in, loader);
25152             }
25153 
25154             @Override
25155             public BaseSavedState[] newArray(int size) {
25156                 return new BaseSavedState[size];
25157             }
25158         };
25159     }
25160 
25161     /**
25162      * A set of information given to a view when it is attached to its parent
25163      * window.
25164      */
25165     final static class AttachInfo {
25166         interface Callbacks {
25167             void playSoundEffect(int effectId);
25168             boolean performHapticFeedback(int effectId, boolean always);
25169         }
25170 
25171         /**
25172          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
25173          * to a Handler. This class contains the target (View) to invalidate and
25174          * the coordinates of the dirty rectangle.
25175          *
25176          * For performance purposes, this class also implements a pool of up to
25177          * POOL_LIMIT objects that get reused. This reduces memory allocations
25178          * whenever possible.
25179          */
25180         static class InvalidateInfo {
25181             private static final int POOL_LIMIT = 10;
25182 
25183             private static final SynchronizedPool<InvalidateInfo> sPool =
25184                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
25185 
25186             View target;
25187 
25188             int left;
25189             int top;
25190             int right;
25191             int bottom;
25192 
25193             public static InvalidateInfo obtain() {
25194                 InvalidateInfo instance = sPool.acquire();
25195                 return (instance != null) ? instance : new InvalidateInfo();
25196             }
25197 
25198             public void recycle() {
25199                 target = null;
25200                 sPool.release(this);
25201             }
25202         }
25203 
25204         final IWindowSession mSession;
25205 
25206         final IWindow mWindow;
25207 
25208         final IBinder mWindowToken;
25209 
25210         Display mDisplay;
25211 
25212         final Callbacks mRootCallbacks;
25213 
25214         IWindowId mIWindowId;
25215         WindowId mWindowId;
25216 
25217         /**
25218          * The top view of the hierarchy.
25219          */
25220         View mRootView;
25221 
25222         IBinder mPanelParentWindowToken;
25223 
25224         boolean mHardwareAccelerated;
25225         boolean mHardwareAccelerationRequested;
25226         ThreadedRenderer mThreadedRenderer;
25227         List<RenderNode> mPendingAnimatingRenderNodes;
25228 
25229         /**
25230          * The state of the display to which the window is attached, as reported
25231          * by {@link Display#getState()}.  Note that the display state constants
25232          * declared by {@link Display} do not exactly line up with the screen state
25233          * constants declared by {@link View} (there are more display states than
25234          * screen states).
25235          */
25236         int mDisplayState = Display.STATE_UNKNOWN;
25237 
25238         /**
25239          * Scale factor used by the compatibility mode
25240          */
25241         float mApplicationScale;
25242 
25243         /**
25244          * Indicates whether the application is in compatibility mode
25245          */
25246         boolean mScalingRequired;
25247 
25248         /**
25249          * Left position of this view's window
25250          */
25251         int mWindowLeft;
25252 
25253         /**
25254          * Top position of this view's window
25255          */
25256         int mWindowTop;
25257 
25258         /**
25259          * Indicates whether views need to use 32-bit drawing caches
25260          */
25261         boolean mUse32BitDrawingCache;
25262 
25263         /**
25264          * For windows that are full-screen but using insets to layout inside
25265          * of the screen areas, these are the current insets to appear inside
25266          * the overscan area of the display.
25267          */
25268         final Rect mOverscanInsets = new Rect();
25269 
25270         /**
25271          * For windows that are full-screen but using insets to layout inside
25272          * of the screen decorations, these are the current insets for the
25273          * content of the window.
25274          */
25275         final Rect mContentInsets = new Rect();
25276 
25277         /**
25278          * For windows that are full-screen but using insets to layout inside
25279          * of the screen decorations, these are the current insets for the
25280          * actual visible parts of the window.
25281          */
25282         final Rect mVisibleInsets = new Rect();
25283 
25284         /**
25285          * For windows that are full-screen but using insets to layout inside
25286          * of the screen decorations, these are the current insets for the
25287          * stable system windows.
25288          */
25289         final Rect mStableInsets = new Rect();
25290 
25291         /**
25292          * For windows that include areas that are not covered by real surface these are the outsets
25293          * for real surface.
25294          */
25295         final Rect mOutsets = new Rect();
25296 
25297         /**
25298          * In multi-window we force show the navigation bar. Because we don't want that the surface
25299          * size changes in this mode, we instead have a flag whether the navigation bar size should
25300          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
25301          */
25302         boolean mAlwaysConsumeNavBar;
25303 
25304         /**
25305          * The internal insets given by this window.  This value is
25306          * supplied by the client (through
25307          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
25308          * be given to the window manager when changed to be used in laying
25309          * out windows behind it.
25310          */
25311         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
25312                 = new ViewTreeObserver.InternalInsetsInfo();
25313 
25314         /**
25315          * Set to true when mGivenInternalInsets is non-empty.
25316          */
25317         boolean mHasNonEmptyGivenInternalInsets;
25318 
25319         /**
25320          * All views in the window's hierarchy that serve as scroll containers,
25321          * used to determine if the window can be resized or must be panned
25322          * to adjust for a soft input area.
25323          */
25324         final ArrayList<View> mScrollContainers = new ArrayList<View>();
25325 
25326         final KeyEvent.DispatcherState mKeyDispatchState
25327                 = new KeyEvent.DispatcherState();
25328 
25329         /**
25330          * Indicates whether the view's window currently has the focus.
25331          */
25332         boolean mHasWindowFocus;
25333 
25334         /**
25335          * The current visibility of the window.
25336          */
25337         int mWindowVisibility;
25338 
25339         /**
25340          * Indicates the time at which drawing started to occur.
25341          */
25342         long mDrawingTime;
25343 
25344         /**
25345          * Indicates whether or not ignoring the DIRTY_MASK flags.
25346          */
25347         boolean mIgnoreDirtyState;
25348 
25349         /**
25350          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
25351          * to avoid clearing that flag prematurely.
25352          */
25353         boolean mSetIgnoreDirtyState = false;
25354 
25355         /**
25356          * Indicates whether the view's window is currently in touch mode.
25357          */
25358         boolean mInTouchMode;
25359 
25360         /**
25361          * Indicates whether the view has requested unbuffered input dispatching for the current
25362          * event stream.
25363          */
25364         boolean mUnbufferedDispatchRequested;
25365 
25366         /**
25367          * Indicates that ViewAncestor should trigger a global layout change
25368          * the next time it performs a traversal
25369          */
25370         boolean mRecomputeGlobalAttributes;
25371 
25372         /**
25373          * Always report new attributes at next traversal.
25374          */
25375         boolean mForceReportNewAttributes;
25376 
25377         /**
25378          * Set during a traveral if any views want to keep the screen on.
25379          */
25380         boolean mKeepScreenOn;
25381 
25382         /**
25383          * Set during a traveral if the light center needs to be updated.
25384          */
25385         boolean mNeedsUpdateLightCenter;
25386 
25387         /**
25388          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
25389          */
25390         int mSystemUiVisibility;
25391 
25392         /**
25393          * Hack to force certain system UI visibility flags to be cleared.
25394          */
25395         int mDisabledSystemUiVisibility;
25396 
25397         /**
25398          * Last global system UI visibility reported by the window manager.
25399          */
25400         int mGlobalSystemUiVisibility = -1;
25401 
25402         /**
25403          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
25404          * attached.
25405          */
25406         boolean mHasSystemUiListeners;
25407 
25408         /**
25409          * Set if the window has requested to extend into the overscan region
25410          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
25411          */
25412         boolean mOverscanRequested;
25413 
25414         /**
25415          * Set if the visibility of any views has changed.
25416          */
25417         boolean mViewVisibilityChanged;
25418 
25419         /**
25420          * Set to true if a view has been scrolled.
25421          */
25422         boolean mViewScrollChanged;
25423 
25424         /**
25425          * Set to true if high contrast mode enabled
25426          */
25427         boolean mHighContrastText;
25428 
25429         /**
25430          * Set to true if a pointer event is currently being handled.
25431          */
25432         boolean mHandlingPointerEvent;
25433 
25434         /**
25435          * Global to the view hierarchy used as a temporary for dealing with
25436          * x/y points in the transparent region computations.
25437          */
25438         final int[] mTransparentLocation = new int[2];
25439 
25440         /**
25441          * Global to the view hierarchy used as a temporary for dealing with
25442          * x/y points in the ViewGroup.invalidateChild implementation.
25443          */
25444         final int[] mInvalidateChildLocation = new int[2];
25445 
25446         /**
25447          * Global to the view hierarchy used as a temporary for dealing with
25448          * computing absolute on-screen location.
25449          */
25450         final int[] mTmpLocation = new int[2];
25451 
25452         /**
25453          * Global to the view hierarchy used as a temporary for dealing with
25454          * x/y location when view is transformed.
25455          */
25456         final float[] mTmpTransformLocation = new float[2];
25457 
25458         /**
25459          * The view tree observer used to dispatch global events like
25460          * layout, pre-draw, touch mode change, etc.
25461          */
25462         final ViewTreeObserver mTreeObserver;
25463 
25464         /**
25465          * A Canvas used by the view hierarchy to perform bitmap caching.
25466          */
25467         Canvas mCanvas;
25468 
25469         /**
25470          * The view root impl.
25471          */
25472         final ViewRootImpl mViewRootImpl;
25473 
25474         /**
25475          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
25476          * handler can be used to pump events in the UI events queue.
25477          */
25478         final Handler mHandler;
25479 
25480         /**
25481          * Temporary for use in computing invalidate rectangles while
25482          * calling up the hierarchy.
25483          */
25484         final Rect mTmpInvalRect = new Rect();
25485 
25486         /**
25487          * Temporary for use in computing hit areas with transformed views
25488          */
25489         final RectF mTmpTransformRect = new RectF();
25490 
25491         /**
25492          * Temporary for use in computing hit areas with transformed views
25493          */
25494         final RectF mTmpTransformRect1 = new RectF();
25495 
25496         /**
25497          * Temporary list of rectanges.
25498          */
25499         final List<RectF> mTmpRectList = new ArrayList<>();
25500 
25501         /**
25502          * Temporary for use in transforming invalidation rect
25503          */
25504         final Matrix mTmpMatrix = new Matrix();
25505 
25506         /**
25507          * Temporary for use in transforming invalidation rect
25508          */
25509         final Transformation mTmpTransformation = new Transformation();
25510 
25511         /**
25512          * Temporary for use in querying outlines from OutlineProviders
25513          */
25514         final Outline mTmpOutline = new Outline();
25515 
25516         /**
25517          * Temporary list for use in collecting focusable descendents of a view.
25518          */
25519         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25520 
25521         /**
25522          * The id of the window for accessibility purposes.
25523          */
25524         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25525 
25526         /**
25527          * Flags related to accessibility processing.
25528          *
25529          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25530          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25531          */
25532         int mAccessibilityFetchFlags;
25533 
25534         /**
25535          * The drawable for highlighting accessibility focus.
25536          */
25537         Drawable mAccessibilityFocusDrawable;
25538 
25539         /**
25540          * The drawable for highlighting autofilled views.
25541          *
25542          * @see #isAutofilled()
25543          */
25544         Drawable mAutofilledDrawable;
25545 
25546         /**
25547          * Show where the margins, bounds and layout bounds are for each view.
25548          */
25549         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25550 
25551         /**
25552          * Point used to compute visible regions.
25553          */
25554         final Point mPoint = new Point();
25555 
25556         /**
25557          * Used to track which View originated a requestLayout() call, used when
25558          * requestLayout() is called during layout.
25559          */
25560         View mViewRequestingLayout;
25561 
25562         /**
25563          * Used to track views that need (at least) a partial relayout at their current size
25564          * during the next traversal.
25565          */
25566         List<View> mPartialLayoutViews = new ArrayList<>();
25567 
25568         /**
25569          * Swapped with mPartialLayoutViews during layout to avoid concurrent
25570          * modification. Lazily assigned during ViewRootImpl layout.
25571          */
25572         List<View> mEmptyPartialLayoutViews;
25573 
25574         /**
25575          * Used to track the identity of the current drag operation.
25576          */
25577         IBinder mDragToken;
25578 
25579         /**
25580          * The drag shadow surface for the current drag operation.
25581          */
25582         public Surface mDragSurface;
25583 
25584 
25585         /**
25586          * The view that currently has a tooltip displayed.
25587          */
25588         View mTooltipHost;
25589 
25590         /**
25591          * Creates a new set of attachment information with the specified
25592          * events handler and thread.
25593          *
25594          * @param handler the events handler the view must use
25595          */
25596         AttachInfo(IWindowSession session, IWindow window, Display display,
25597                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25598                 Context context) {
25599             mSession = session;
25600             mWindow = window;
25601             mWindowToken = window.asBinder();
25602             mDisplay = display;
25603             mViewRootImpl = viewRootImpl;
25604             mHandler = handler;
25605             mRootCallbacks = effectPlayer;
25606             mTreeObserver = new ViewTreeObserver(context);
25607         }
25608     }
25609 
25610     /**
25611      * <p>ScrollabilityCache holds various fields used by a View when scrolling
25612      * is supported. This avoids keeping too many unused fields in most
25613      * instances of View.</p>
25614      */
25615     private static class ScrollabilityCache implements Runnable {
25616 
25617         /**
25618          * Scrollbars are not visible
25619          */
25620         public static final int OFF = 0;
25621 
25622         /**
25623          * Scrollbars are visible
25624          */
25625         public static final int ON = 1;
25626 
25627         /**
25628          * Scrollbars are fading away
25629          */
25630         public static final int FADING = 2;
25631 
25632         public boolean fadeScrollBars;
25633 
25634         public int fadingEdgeLength;
25635         public int scrollBarDefaultDelayBeforeFade;
25636         public int scrollBarFadeDuration;
25637 
25638         public int scrollBarSize;
25639         public int scrollBarMinTouchTarget;
25640         public ScrollBarDrawable scrollBar;
25641         public float[] interpolatorValues;
25642         public View host;
25643 
25644         public final Paint paint;
25645         public final Matrix matrix;
25646         public Shader shader;
25647 
25648         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25649 
25650         private static final float[] OPAQUE = { 255 };
25651         private static final float[] TRANSPARENT = { 0.0f };
25652 
25653         /**
25654          * When fading should start. This time moves into the future every time
25655          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25656          */
25657         public long fadeStartTime;
25658 
25659 
25660         /**
25661          * The current state of the scrollbars: ON, OFF, or FADING
25662          */
25663         public int state = OFF;
25664 
25665         private int mLastColor;
25666 
25667         public final Rect mScrollBarBounds = new Rect();
25668         public final Rect mScrollBarTouchBounds = new Rect();
25669 
25670         public static final int NOT_DRAGGING = 0;
25671         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25672         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25673         public int mScrollBarDraggingState = NOT_DRAGGING;
25674 
25675         public float mScrollBarDraggingPos = 0;
25676 
25677         public ScrollabilityCache(ViewConfiguration configuration, View host) {
25678             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25679             scrollBarSize = configuration.getScaledScrollBarSize();
25680             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25681             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25682             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25683 
25684             paint = new Paint();
25685             matrix = new Matrix();
25686             // use use a height of 1, and then wack the matrix each time we
25687             // actually use it.
25688             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25689             paint.setShader(shader);
25690             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25691 
25692             this.host = host;
25693         }
25694 
25695         public void setFadeColor(int color) {
25696             if (color != mLastColor) {
25697                 mLastColor = color;
25698 
25699                 if (color != 0) {
25700                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25701                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25702                     paint.setShader(shader);
25703                     // Restore the default transfer mode (src_over)
25704                     paint.setXfermode(null);
25705                 } else {
25706                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25707                     paint.setShader(shader);
25708                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25709                 }
25710             }
25711         }
25712 
25713         public void run() {
25714             long now = AnimationUtils.currentAnimationTimeMillis();
25715             if (now >= fadeStartTime) {
25716 
25717                 // the animation fades the scrollbars out by changing
25718                 // the opacity (alpha) from fully opaque to fully
25719                 // transparent
25720                 int nextFrame = (int) now;
25721                 int framesCount = 0;
25722 
25723                 Interpolator interpolator = scrollBarInterpolator;
25724 
25725                 // Start opaque
25726                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25727 
25728                 // End transparent
25729                 nextFrame += scrollBarFadeDuration;
25730                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25731 
25732                 state = FADING;
25733 
25734                 // Kick off the fade animation
25735                 host.invalidate(true);
25736             }
25737         }
25738     }
25739 
25740     /**
25741      * Resuable callback for sending
25742      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25743      */
25744     private class SendViewScrolledAccessibilityEvent implements Runnable {
25745         public volatile boolean mIsPending;
25746 
25747         public void run() {
25748             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25749             mIsPending = false;
25750         }
25751     }
25752 
25753     /**
25754      * <p>
25755      * This class represents a delegate that can be registered in a {@link View}
25756      * to enhance accessibility support via composition rather via inheritance.
25757      * It is specifically targeted to widget developers that extend basic View
25758      * classes i.e. classes in package android.view, that would like their
25759      * applications to be backwards compatible.
25760      * </p>
25761      * <div class="special reference">
25762      * <h3>Developer Guides</h3>
25763      * <p>For more information about making applications accessible, read the
25764      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25765      * developer guide.</p>
25766      * </div>
25767      * <p>
25768      * A scenario in which a developer would like to use an accessibility delegate
25769      * is overriding a method introduced in a later API version than the minimal API
25770      * version supported by the application. For example, the method
25771      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25772      * in API version 4 when the accessibility APIs were first introduced. If a
25773      * developer would like his application to run on API version 4 devices (assuming
25774      * all other APIs used by the application are version 4 or lower) and take advantage
25775      * of this method, instead of overriding the method which would break the application's
25776      * backwards compatibility, he can override the corresponding method in this
25777      * delegate and register the delegate in the target View if the API version of
25778      * the system is high enough, i.e. the API version is the same as or higher than the API
25779      * version that introduced
25780      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25781      * </p>
25782      * <p>
25783      * Here is an example implementation:
25784      * </p>
25785      * <code><pre><p>
25786      * if (Build.VERSION.SDK_INT >= 14) {
25787      *     // If the API version is equal of higher than the version in
25788      *     // which onInitializeAccessibilityNodeInfo was introduced we
25789      *     // register a delegate with a customized implementation.
25790      *     View view = findViewById(R.id.view_id);
25791      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25792      *         public void onInitializeAccessibilityNodeInfo(View host,
25793      *                 AccessibilityNodeInfo info) {
25794      *             // Let the default implementation populate the info.
25795      *             super.onInitializeAccessibilityNodeInfo(host, info);
25796      *             // Set some other information.
25797      *             info.setEnabled(host.isEnabled());
25798      *         }
25799      *     });
25800      * }
25801      * </code></pre></p>
25802      * <p>
25803      * This delegate contains methods that correspond to the accessibility methods
25804      * in View. If a delegate has been specified the implementation in View hands
25805      * off handling to the corresponding method in this delegate. The default
25806      * implementation the delegate methods behaves exactly as the corresponding
25807      * method in View for the case of no accessibility delegate been set. Hence,
25808      * to customize the behavior of a View method, clients can override only the
25809      * corresponding delegate method without altering the behavior of the rest
25810      * accessibility related methods of the host view.
25811      * </p>
25812      * <p>
25813      * <strong>Note:</strong> On platform versions prior to
25814      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25815      * views in the {@code android.widget.*} package are called <i>before</i>
25816      * host methods. This prevents certain properties such as class name from
25817      * being modified by overriding
25818      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25819      * as any changes will be overwritten by the host class.
25820      * <p>
25821      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25822      * methods are called <i>after</i> host methods, which all properties to be
25823      * modified without being overwritten by the host class.
25824      */
25825     public static class AccessibilityDelegate {
25826 
25827         /**
25828          * Sends an accessibility event of the given type. If accessibility is not
25829          * enabled this method has no effect.
25830          * <p>
25831          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25832          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25833          * been set.
25834          * </p>
25835          *
25836          * @param host The View hosting the delegate.
25837          * @param eventType The type of the event to send.
25838          *
25839          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25840          */
25841         public void sendAccessibilityEvent(View host, int eventType) {
25842             host.sendAccessibilityEventInternal(eventType);
25843         }
25844 
25845         /**
25846          * Performs the specified accessibility action on the view. For
25847          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25848          * <p>
25849          * The default implementation behaves as
25850          * {@link View#performAccessibilityAction(int, Bundle)
25851          *  View#performAccessibilityAction(int, Bundle)} for the case of
25852          *  no accessibility delegate been set.
25853          * </p>
25854          *
25855          * @param action The action to perform.
25856          * @return Whether the action was performed.
25857          *
25858          * @see View#performAccessibilityAction(int, Bundle)
25859          *      View#performAccessibilityAction(int, Bundle)
25860          */
25861         public boolean performAccessibilityAction(View host, int action, Bundle args) {
25862             return host.performAccessibilityActionInternal(action, args);
25863         }
25864 
25865         /**
25866          * Sends an accessibility event. This method behaves exactly as
25867          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25868          * empty {@link AccessibilityEvent} and does not perform a check whether
25869          * accessibility is enabled.
25870          * <p>
25871          * The default implementation behaves as
25872          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25873          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25874          * the case of no accessibility delegate been set.
25875          * </p>
25876          *
25877          * @param host The View hosting the delegate.
25878          * @param event The event to send.
25879          *
25880          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25881          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25882          */
25883         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25884             host.sendAccessibilityEventUncheckedInternal(event);
25885         }
25886 
25887         /**
25888          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25889          * to its children for adding their text content to the event.
25890          * <p>
25891          * The default implementation behaves as
25892          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25893          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25894          * the case of no accessibility delegate been set.
25895          * </p>
25896          *
25897          * @param host The View hosting the delegate.
25898          * @param event The event.
25899          * @return True if the event population was completed.
25900          *
25901          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25902          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25903          */
25904         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25905             return host.dispatchPopulateAccessibilityEventInternal(event);
25906         }
25907 
25908         /**
25909          * Gives a chance to the host View to populate the accessibility event with its
25910          * text content.
25911          * <p>
25912          * The default implementation behaves as
25913          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25914          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25915          * the case of no accessibility delegate been set.
25916          * </p>
25917          *
25918          * @param host The View hosting the delegate.
25919          * @param event The accessibility event which to populate.
25920          *
25921          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25922          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25923          */
25924         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25925             host.onPopulateAccessibilityEventInternal(event);
25926         }
25927 
25928         /**
25929          * Initializes an {@link AccessibilityEvent} with information about the
25930          * the host View which is the event source.
25931          * <p>
25932          * The default implementation behaves as
25933          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25934          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25935          * the case of no accessibility delegate been set.
25936          * </p>
25937          *
25938          * @param host The View hosting the delegate.
25939          * @param event The event to initialize.
25940          *
25941          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25942          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25943          */
25944         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25945             host.onInitializeAccessibilityEventInternal(event);
25946         }
25947 
25948         /**
25949          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25950          * <p>
25951          * The default implementation behaves as
25952          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25953          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25954          * the case of no accessibility delegate been set.
25955          * </p>
25956          *
25957          * @param host The View hosting the delegate.
25958          * @param info The instance to initialize.
25959          *
25960          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25961          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25962          */
25963         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25964             host.onInitializeAccessibilityNodeInfoInternal(info);
25965         }
25966 
25967         /**
25968          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25969          * additional data.
25970          * <p>
25971          * This method only needs to be implemented if the View offers to provide additional data.
25972          * </p>
25973          * <p>
25974          * The default implementation behaves as
25975          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
25976          * for the case where no accessibility delegate is set.
25977          * </p>
25978          *
25979          * @param host The View hosting the delegate. Never {@code null}.
25980          * @param info The info to which to add the extra data. Never {@code null}.
25981          * @param extraDataKey A key specifying the type of extra data to add to the info. The
25982          *                     extra data should be added to the {@link Bundle} returned by
25983          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25984          *                     {@code null}.
25985          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25986          *                  May be {@code null} if the if the service provided no arguments.
25987          *
25988          * @see AccessibilityNodeInfo#setExtraAvailableData
25989          */
25990         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25991                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25992                 @Nullable Bundle arguments) {
25993             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25994         }
25995 
25996         /**
25997          * Called when a child of the host View has requested sending an
25998          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25999          * to augment the event.
26000          * <p>
26001          * The default implementation behaves as
26002          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
26003          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
26004          * the case of no accessibility delegate been set.
26005          * </p>
26006          *
26007          * @param host The View hosting the delegate.
26008          * @param child The child which requests sending the event.
26009          * @param event The event to be sent.
26010          * @return True if the event should be sent
26011          *
26012          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
26013          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
26014          */
26015         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
26016                 AccessibilityEvent event) {
26017             return host.onRequestSendAccessibilityEventInternal(child, event);
26018         }
26019 
26020         /**
26021          * Gets the provider for managing a virtual view hierarchy rooted at this View
26022          * and reported to {@link android.accessibilityservice.AccessibilityService}s
26023          * that explore the window content.
26024          * <p>
26025          * The default implementation behaves as
26026          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
26027          * the case of no accessibility delegate been set.
26028          * </p>
26029          *
26030          * @return The provider.
26031          *
26032          * @see AccessibilityNodeProvider
26033          */
26034         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
26035             return null;
26036         }
26037 
26038         /**
26039          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
26040          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
26041          * This method is responsible for obtaining an accessibility node info from a
26042          * pool of reusable instances and calling
26043          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
26044          * view to initialize the former.
26045          * <p>
26046          * <strong>Note:</strong> The client is responsible for recycling the obtained
26047          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
26048          * creation.
26049          * </p>
26050          * <p>
26051          * The default implementation behaves as
26052          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
26053          * the case of no accessibility delegate been set.
26054          * </p>
26055          * @return A populated {@link AccessibilityNodeInfo}.
26056          *
26057          * @see AccessibilityNodeInfo
26058          *
26059          * @hide
26060          */
26061         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
26062             return host.createAccessibilityNodeInfoInternal();
26063         }
26064     }
26065 
26066     private static class MatchIdPredicate implements Predicate<View> {
26067         public int mId;
26068 
26069         @Override
26070         public boolean test(View view) {
26071             return (view.mID == mId);
26072         }
26073     }
26074 
26075     private static class MatchLabelForPredicate implements Predicate<View> {
26076         private int mLabeledId;
26077 
26078         @Override
26079         public boolean test(View view) {
26080             return (view.mLabelForId == mLabeledId);
26081         }
26082     }
26083 
26084     /**
26085      * Dump all private flags in readable format, useful for documentation and
26086      * sanity checking.
26087      */
26088     private static void dumpFlags() {
26089         final HashMap<String, String> found = Maps.newHashMap();
26090         try {
26091             for (Field field : View.class.getDeclaredFields()) {
26092                 final int modifiers = field.getModifiers();
26093                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
26094                     if (field.getType().equals(int.class)) {
26095                         final int value = field.getInt(null);
26096                         dumpFlag(found, field.getName(), value);
26097                     } else if (field.getType().equals(int[].class)) {
26098                         final int[] values = (int[]) field.get(null);
26099                         for (int i = 0; i < values.length; i++) {
26100                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
26101                         }
26102                     }
26103                 }
26104             }
26105         } catch (IllegalAccessException e) {
26106             throw new RuntimeException(e);
26107         }
26108 
26109         final ArrayList<String> keys = Lists.newArrayList();
26110         keys.addAll(found.keySet());
26111         Collections.sort(keys);
26112         for (String key : keys) {
26113             Log.d(VIEW_LOG_TAG, found.get(key));
26114         }
26115     }
26116 
26117     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
26118         // Sort flags by prefix, then by bits, always keeping unique keys
26119         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
26120         final int prefix = name.indexOf('_');
26121         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
26122         final String output = bits + " " + name;
26123         found.put(key, output);
26124     }
26125 
26126     /** {@hide} */
26127     public void encode(@NonNull ViewHierarchyEncoder stream) {
26128         stream.beginObject(this);
26129         encodeProperties(stream);
26130         stream.endObject();
26131     }
26132 
26133     /** {@hide} */
26134     @CallSuper
26135     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
26136         Object resolveId = ViewDebug.resolveId(getContext(), mID);
26137         if (resolveId instanceof String) {
26138             stream.addProperty("id", (String) resolveId);
26139         } else {
26140             stream.addProperty("id", mID);
26141         }
26142 
26143         stream.addProperty("misc:transformation.alpha",
26144                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
26145         stream.addProperty("misc:transitionName", getTransitionName());
26146 
26147         // layout
26148         stream.addProperty("layout:left", mLeft);
26149         stream.addProperty("layout:right", mRight);
26150         stream.addProperty("layout:top", mTop);
26151         stream.addProperty("layout:bottom", mBottom);
26152         stream.addProperty("layout:width", getWidth());
26153         stream.addProperty("layout:height", getHeight());
26154         stream.addProperty("layout:layoutDirection", getLayoutDirection());
26155         stream.addProperty("layout:layoutRtl", isLayoutRtl());
26156         stream.addProperty("layout:hasTransientState", hasTransientState());
26157         stream.addProperty("layout:baseline", getBaseline());
26158 
26159         // layout params
26160         ViewGroup.LayoutParams layoutParams = getLayoutParams();
26161         if (layoutParams != null) {
26162             stream.addPropertyKey("layoutParams");
26163             layoutParams.encode(stream);
26164         }
26165 
26166         // scrolling
26167         stream.addProperty("scrolling:scrollX", mScrollX);
26168         stream.addProperty("scrolling:scrollY", mScrollY);
26169 
26170         // padding
26171         stream.addProperty("padding:paddingLeft", mPaddingLeft);
26172         stream.addProperty("padding:paddingRight", mPaddingRight);
26173         stream.addProperty("padding:paddingTop", mPaddingTop);
26174         stream.addProperty("padding:paddingBottom", mPaddingBottom);
26175         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
26176         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
26177         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
26178         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
26179         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
26180 
26181         // measurement
26182         stream.addProperty("measurement:minHeight", mMinHeight);
26183         stream.addProperty("measurement:minWidth", mMinWidth);
26184         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
26185         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
26186 
26187         // drawing
26188         stream.addProperty("drawing:elevation", getElevation());
26189         stream.addProperty("drawing:translationX", getTranslationX());
26190         stream.addProperty("drawing:translationY", getTranslationY());
26191         stream.addProperty("drawing:translationZ", getTranslationZ());
26192         stream.addProperty("drawing:rotation", getRotation());
26193         stream.addProperty("drawing:rotationX", getRotationX());
26194         stream.addProperty("drawing:rotationY", getRotationY());
26195         stream.addProperty("drawing:scaleX", getScaleX());
26196         stream.addProperty("drawing:scaleY", getScaleY());
26197         stream.addProperty("drawing:pivotX", getPivotX());
26198         stream.addProperty("drawing:pivotY", getPivotY());
26199         stream.addProperty("drawing:opaque", isOpaque());
26200         stream.addProperty("drawing:alpha", getAlpha());
26201         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
26202         stream.addProperty("drawing:shadow", hasShadow());
26203         stream.addProperty("drawing:solidColor", getSolidColor());
26204         stream.addProperty("drawing:layerType", mLayerType);
26205         stream.addProperty("drawing:willNotDraw", willNotDraw());
26206         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
26207         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
26208         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
26209         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
26210 
26211         // focus
26212         stream.addProperty("focus:hasFocus", hasFocus());
26213         stream.addProperty("focus:isFocused", isFocused());
26214         stream.addProperty("focus:focusable", getFocusable());
26215         stream.addProperty("focus:isFocusable", isFocusable());
26216         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
26217 
26218         stream.addProperty("misc:clickable", isClickable());
26219         stream.addProperty("misc:pressed", isPressed());
26220         stream.addProperty("misc:selected", isSelected());
26221         stream.addProperty("misc:touchMode", isInTouchMode());
26222         stream.addProperty("misc:hovered", isHovered());
26223         stream.addProperty("misc:activated", isActivated());
26224 
26225         stream.addProperty("misc:visibility", getVisibility());
26226         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
26227         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
26228 
26229         stream.addProperty("misc:enabled", isEnabled());
26230         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
26231         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
26232 
26233         // theme attributes
26234         Resources.Theme theme = getContext().getTheme();
26235         if (theme != null) {
26236             stream.addPropertyKey("theme");
26237             theme.encode(stream);
26238         }
26239 
26240         // view attribute information
26241         int n = mAttributes != null ? mAttributes.length : 0;
26242         stream.addProperty("meta:__attrCount__", n/2);
26243         for (int i = 0; i < n; i += 2) {
26244             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
26245         }
26246 
26247         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
26248 
26249         // text
26250         stream.addProperty("text:textDirection", getTextDirection());
26251         stream.addProperty("text:textAlignment", getTextAlignment());
26252 
26253         // accessibility
26254         CharSequence contentDescription = getContentDescription();
26255         stream.addProperty("accessibility:contentDescription",
26256                 contentDescription == null ? "" : contentDescription.toString());
26257         stream.addProperty("accessibility:labelFor", getLabelFor());
26258         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
26259     }
26260 
26261     /**
26262      * Determine if this view is rendered on a round wearable device and is the main view
26263      * on the screen.
26264      */
26265     boolean shouldDrawRoundScrollbar() {
26266         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
26267             return false;
26268         }
26269 
26270         final View rootView = getRootView();
26271         final WindowInsets insets = getRootWindowInsets();
26272 
26273         int height = getHeight();
26274         int width = getWidth();
26275         int displayHeight = rootView.getHeight();
26276         int displayWidth = rootView.getWidth();
26277 
26278         if (height != displayHeight || width != displayWidth) {
26279             return false;
26280         }
26281 
26282         getLocationInWindow(mAttachInfo.mTmpLocation);
26283         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
26284                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
26285     }
26286 
26287     /**
26288      * Sets the tooltip text which will be displayed in a small popup next to the view.
26289      * <p>
26290      * The tooltip will be displayed:
26291      * <ul>
26292      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
26293      * menu). </li>
26294      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
26295      * </ul>
26296      * <p>
26297      * <strong>Note:</strong> Do not override this method, as it will have no
26298      * effect on the text displayed in the tooltip.
26299      *
26300      * @param tooltipText the tooltip text, or null if no tooltip is required
26301      * @see #getTooltipText()
26302      * @attr ref android.R.styleable#View_tooltipText
26303      */
26304     public void setTooltipText(@Nullable CharSequence tooltipText) {
26305         if (TextUtils.isEmpty(tooltipText)) {
26306             setFlags(0, TOOLTIP);
26307             hideTooltip();
26308             mTooltipInfo = null;
26309         } else {
26310             setFlags(TOOLTIP, TOOLTIP);
26311             if (mTooltipInfo == null) {
26312                 mTooltipInfo = new TooltipInfo();
26313                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
26314                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
26315             }
26316             mTooltipInfo.mTooltipText = tooltipText;
26317         }
26318     }
26319 
26320     /**
26321      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26322      */
26323     public void setTooltip(@Nullable CharSequence tooltipText) {
26324         setTooltipText(tooltipText);
26325     }
26326 
26327     /**
26328      * Returns the view's tooltip text.
26329      *
26330      * <strong>Note:</strong> Do not override this method, as it will have no
26331      * effect on the text displayed in the tooltip. You must call
26332      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
26333      *
26334      * @return the tooltip text
26335      * @see #setTooltipText(CharSequence)
26336      * @attr ref android.R.styleable#View_tooltipText
26337      */
26338     @Nullable
26339     public CharSequence getTooltipText() {
26340         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
26341     }
26342 
26343     /**
26344      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26345      */
26346     @Nullable
26347     public CharSequence getTooltip() {
26348         return getTooltipText();
26349     }
26350 
26351     private boolean showTooltip(int x, int y, boolean fromLongClick) {
26352         if (mAttachInfo == null || mTooltipInfo == null) {
26353             return false;
26354         }
26355         if ((mViewFlags & ENABLED_MASK) != ENABLED) {
26356             return false;
26357         }
26358         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
26359             return false;
26360         }
26361         hideTooltip();
26362         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
26363         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
26364         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
26365         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
26366         mAttachInfo.mTooltipHost = this;
26367         return true;
26368     }
26369 
26370     void hideTooltip() {
26371         if (mTooltipInfo == null) {
26372             return;
26373         }
26374         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26375         if (mTooltipInfo.mTooltipPopup == null) {
26376             return;
26377         }
26378         mTooltipInfo.mTooltipPopup.hide();
26379         mTooltipInfo.mTooltipPopup = null;
26380         mTooltipInfo.mTooltipFromLongClick = false;
26381         if (mAttachInfo != null) {
26382             mAttachInfo.mTooltipHost = null;
26383         }
26384     }
26385 
26386     private boolean showLongClickTooltip(int x, int y) {
26387         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26388         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26389         return showTooltip(x, y, true);
26390     }
26391 
26392     private void showHoverTooltip() {
26393         showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
26394     }
26395 
26396     boolean dispatchTooltipHoverEvent(MotionEvent event) {
26397         if (mTooltipInfo == null) {
26398             return false;
26399         }
26400         switch(event.getAction()) {
26401             case MotionEvent.ACTION_HOVER_MOVE:
26402                 if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
26403                     break;
26404                 }
26405                 if (!mTooltipInfo.mTooltipFromLongClick) {
26406                     if (mTooltipInfo.mTooltipPopup == null) {
26407                         // Schedule showing the tooltip after a timeout.
26408                         mTooltipInfo.mAnchorX = (int) event.getX();
26409                         mTooltipInfo.mAnchorY = (int) event.getY();
26410                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26411                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
26412                                 ViewConfiguration.getHoverTooltipShowTimeout());
26413                     }
26414 
26415                     // Hide hover-triggered tooltip after a period of inactivity.
26416                     // Match the timeout used by NativeInputManager to hide the mouse pointer
26417                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26418                     final int timeout;
26419                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26420                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
26421                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26422                     } else {
26423                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26424                     }
26425                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26426                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26427                 }
26428                 return true;
26429 
26430             case MotionEvent.ACTION_HOVER_EXIT:
26431                 if (!mTooltipInfo.mTooltipFromLongClick) {
26432                     hideTooltip();
26433                 }
26434                 break;
26435         }
26436         return false;
26437     }
26438 
26439     void handleTooltipKey(KeyEvent event) {
26440         switch (event.getAction()) {
26441             case KeyEvent.ACTION_DOWN:
26442                 if (event.getRepeatCount() == 0) {
26443                     hideTooltip();
26444                 }
26445                 break;
26446 
26447             case KeyEvent.ACTION_UP:
26448                 handleTooltipUp();
26449                 break;
26450         }
26451     }
26452 
26453     private void handleTooltipUp() {
26454         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26455             return;
26456         }
26457         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26458         postDelayed(mTooltipInfo.mHideTooltipRunnable,
26459                 ViewConfiguration.getLongPressTooltipHideTimeout());
26460     }
26461 
26462     private int getFocusableAttribute(TypedArray attributes) {
26463         TypedValue val = new TypedValue();
26464         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26465             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26466                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26467             } else {
26468                 return val.data;
26469             }
26470         } else {
26471             return FOCUSABLE_AUTO;
26472         }
26473     }
26474 
26475     /**
26476      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26477      * is not showing.
26478      * @hide
26479      */
26480     @TestApi
26481     public View getTooltipView() {
26482         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26483             return null;
26484         }
26485         return mTooltipInfo.mTooltipPopup.getContentView();
26486     }
26487 }
26488