OSDN Git Service

Merge "Improve consistency in focusAfterDescendants behavior" into oc-dev
[android-x86/frameworks-base.git] / core / java / android / view / View.java
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.Collection;
131 import java.util.Collections;
132 import java.util.HashMap;
133 import java.util.List;
134 import java.util.Locale;
135 import java.util.Map;
136 import java.util.concurrent.CopyOnWriteArrayList;
137 import java.util.concurrent.atomic.AtomicInteger;
138 import java.util.function.Predicate;
139
140 /**
141  * <p>
142  * This class represents the basic building block for user interface components. A View
143  * occupies a rectangular area on the screen and is responsible for drawing and
144  * event handling. View is the base class for <em>widgets</em>, which are
145  * used to create interactive UI components (buttons, text fields, etc.). The
146  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
147  * are invisible containers that hold other Views (or other ViewGroups) and define
148  * their layout properties.
149  * </p>
150  *
151  * <div class="special reference">
152  * <h3>Developer Guides</h3>
153  * <p>For information about using this class to develop your application's user interface,
154  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
155  * </div>
156  *
157  * <a name="Using"></a>
158  * <h3>Using Views</h3>
159  * <p>
160  * All of the views in a window are arranged in a single tree. You can add views
161  * either from code or by specifying a tree of views in one or more XML layout
162  * files. There are many specialized subclasses of views that act as controls or
163  * are capable of displaying text, images, or other content.
164  * </p>
165  * <p>
166  * Once you have created a tree of views, there are typically a few types of
167  * common operations you may wish to perform:
168  * <ul>
169  * <li><strong>Set properties:</strong> for example setting the text of a
170  * {@link android.widget.TextView}. The available properties and the methods
171  * that set them will vary among the different subclasses of views. Note that
172  * properties that are known at build time can be set in the XML layout
173  * files.</li>
174  * <li><strong>Set focus:</strong> The framework will handle moving focus in
175  * response to user input. To force focus to a specific view, call
176  * {@link #requestFocus}.</li>
177  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
178  * that will be notified when something interesting happens to the view. For
179  * example, all views will let you set a listener to be notified when the view
180  * gains or loses focus. You can register such a listener using
181  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
182  * Other view subclasses offer more specialized listeners. For example, a Button
183  * exposes a listener to notify clients when the button is clicked.</li>
184  * <li><strong>Set visibility:</strong> You can hide or show views using
185  * {@link #setVisibility(int)}.</li>
186  * </ul>
187  * </p>
188  * <p><em>
189  * Note: The Android framework is responsible for measuring, laying out and
190  * drawing views. You should not call methods that perform these actions on
191  * views yourself unless you are actually implementing a
192  * {@link android.view.ViewGroup}.
193  * </em></p>
194  *
195  * <a name="Lifecycle"></a>
196  * <h3>Implementing a Custom View</h3>
197  *
198  * <p>
199  * To implement a custom view, you will usually begin by providing overrides for
200  * some of the standard methods that the framework calls on all views. You do
201  * not need to override all of these methods. In fact, you can start by just
202  * overriding {@link #onDraw(android.graphics.Canvas)}.
203  * <table border="2" width="85%" align="center" cellpadding="5">
204  *     <thead>
205  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
206  *     </thead>
207  *
208  *     <tbody>
209  *     <tr>
210  *         <td rowspan="2">Creation</td>
211  *         <td>Constructors</td>
212  *         <td>There is a form of the constructor that are called when the view
213  *         is created from code and a form that is called when the view is
214  *         inflated from a layout file. The second form should parse and apply
215  *         any attributes defined in the layout file.
216  *         </td>
217  *     </tr>
218  *     <tr>
219  *         <td><code>{@link #onFinishInflate()}</code></td>
220  *         <td>Called after a view and all of its children has been inflated
221  *         from XML.</td>
222  *     </tr>
223  *
224  *     <tr>
225  *         <td rowspan="3">Layout</td>
226  *         <td><code>{@link #onMeasure(int, int)}</code></td>
227  *         <td>Called to determine the size requirements for this view and all
228  *         of its children.
229  *         </td>
230  *     </tr>
231  *     <tr>
232  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
233  *         <td>Called when this view should assign a size and position to all
234  *         of its children.
235  *         </td>
236  *     </tr>
237  *     <tr>
238  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
239  *         <td>Called when the size of this view has changed.
240  *         </td>
241  *     </tr>
242  *
243  *     <tr>
244  *         <td>Drawing</td>
245  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
246  *         <td>Called when the view should render its content.
247  *         </td>
248  *     </tr>
249  *
250  *     <tr>
251  *         <td rowspan="4">Event processing</td>
252  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
253  *         <td>Called when a new hardware key event occurs.
254  *         </td>
255  *     </tr>
256  *     <tr>
257  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
258  *         <td>Called when a hardware key up event occurs.
259  *         </td>
260  *     </tr>
261  *     <tr>
262  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
263  *         <td>Called when a trackball motion event occurs.
264  *         </td>
265  *     </tr>
266  *     <tr>
267  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
268  *         <td>Called when a touch screen motion event occurs.
269  *         </td>
270  *     </tr>
271  *
272  *     <tr>
273  *         <td rowspan="2">Focus</td>
274  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
275  *         <td>Called when the view gains or loses focus.
276  *         </td>
277  *     </tr>
278  *
279  *     <tr>
280  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
281  *         <td>Called when the window containing the view gains or loses focus.
282  *         </td>
283  *     </tr>
284  *
285  *     <tr>
286  *         <td rowspan="3">Attaching</td>
287  *         <td><code>{@link #onAttachedToWindow()}</code></td>
288  *         <td>Called when the view is attached to a window.
289  *         </td>
290  *     </tr>
291  *
292  *     <tr>
293  *         <td><code>{@link #onDetachedFromWindow}</code></td>
294  *         <td>Called when the view is detached from its window.
295  *         </td>
296  *     </tr>
297  *
298  *     <tr>
299  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
300  *         <td>Called when the visibility of the window containing the view
301  *         has changed.
302  *         </td>
303  *     </tr>
304  *     </tbody>
305  *
306  * </table>
307  * </p>
308  *
309  * <a name="IDs"></a>
310  * <h3>IDs</h3>
311  * Views may have an integer id associated with them. These ids are typically
312  * assigned in the layout XML files, and are used to find specific views within
313  * the view tree. A common pattern is to:
314  * <ul>
315  * <li>Define a Button in the layout file and assign it a unique ID.
316  * <pre>
317  * &lt;Button
318  *     android:id="@+id/my_button"
319  *     android:layout_width="wrap_content"
320  *     android:layout_height="wrap_content"
321  *     android:text="@string/my_button_text"/&gt;
322  * </pre></li>
323  * <li>From the onCreate method of an Activity, find the Button
324  * <pre class="prettyprint">
325  *      Button myButton = findViewById(R.id.my_button);
326  * </pre></li>
327  * </ul>
328  * <p>
329  * View IDs need not be unique throughout the tree, but it is good practice to
330  * ensure that they are at least unique within the part of the tree you are
331  * searching.
332  * </p>
333  *
334  * <a name="Position"></a>
335  * <h3>Position</h3>
336  * <p>
337  * The geometry of a view is that of a rectangle. A view has a location,
338  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
339  * two dimensions, expressed as a width and a height. The unit for location
340  * and dimensions is the pixel.
341  * </p>
342  *
343  * <p>
344  * It is possible to retrieve the location of a view by invoking the methods
345  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
346  * coordinate of the rectangle representing the view. The latter returns the
347  * top, or Y, coordinate of the rectangle representing the view. These methods
348  * both return the location of the view relative to its parent. For instance,
349  * when getLeft() returns 20, that means the view is located 20 pixels to the
350  * right of the left edge of its direct parent.
351  * </p>
352  *
353  * <p>
354  * In addition, several convenience methods are offered to avoid unnecessary
355  * computations, namely {@link #getRight()} and {@link #getBottom()}.
356  * These methods return the coordinates of the right and bottom edges of the
357  * rectangle representing the view. For instance, calling {@link #getRight()}
358  * is similar to the following computation: <code>getLeft() + getWidth()</code>
359  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
360  * </p>
361  *
362  * <a name="SizePaddingMargins"></a>
363  * <h3>Size, padding and margins</h3>
364  * <p>
365  * The size of a view is expressed with a width and a height. A view actually
366  * possess two pairs of width and height values.
367  * </p>
368  *
369  * <p>
370  * The first pair is known as <em>measured width</em> and
371  * <em>measured height</em>. These dimensions define how big a view wants to be
372  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
373  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
374  * and {@link #getMeasuredHeight()}.
375  * </p>
376  *
377  * <p>
378  * The second pair is simply known as <em>width</em> and <em>height</em>, or
379  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
380  * dimensions define the actual size of the view on screen, at drawing time and
381  * after layout. These values may, but do not have to, be different from the
382  * measured width and height. The width and height can be obtained by calling
383  * {@link #getWidth()} and {@link #getHeight()}.
384  * </p>
385  *
386  * <p>
387  * To measure its dimensions, a view takes into account its padding. The padding
388  * is expressed in pixels for the left, top, right and bottom parts of the view.
389  * Padding can be used to offset the content of the view by a specific amount of
390  * pixels. For instance, a left padding of 2 will push the view's content by
391  * 2 pixels to the right of the left edge. Padding can be set using the
392  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
393  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
394  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
395  * {@link #getPaddingEnd()}.
396  * </p>
397  *
398  * <p>
399  * Even though a view can define a padding, it does not provide any support for
400  * margins. However, view groups provide such a support. Refer to
401  * {@link android.view.ViewGroup} and
402  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
403  * </p>
404  *
405  * <a name="Layout"></a>
406  * <h3>Layout</h3>
407  * <p>
408  * Layout is a two pass process: a measure pass and a layout pass. The measuring
409  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
410  * of the view tree. Each view pushes dimension specifications down the tree
411  * during the recursion. At the end of the measure pass, every view has stored
412  * its measurements. The second pass happens in
413  * {@link #layout(int,int,int,int)} and is also top-down. During
414  * this pass each parent is responsible for positioning all of its children
415  * using the sizes computed in the measure pass.
416  * </p>
417  *
418  * <p>
419  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
420  * {@link #getMeasuredHeight()} values must be set, along with those for all of
421  * that view's descendants. A view's measured width and measured height values
422  * must respect the constraints imposed by the view's parents. This guarantees
423  * that at the end of the measure pass, all parents accept all of their
424  * children's measurements. A parent view may call measure() more than once on
425  * its children. For example, the parent may measure each child once with
426  * unspecified dimensions to find out how big they want to be, then call
427  * measure() on them again with actual numbers if the sum of all the children's
428  * unconstrained sizes is too big or too small.
429  * </p>
430  *
431  * <p>
432  * The measure pass uses two classes to communicate dimensions. The
433  * {@link MeasureSpec} class is used by views to tell their parents how they
434  * want to be measured and positioned. The base LayoutParams class just
435  * describes how big the view wants to be for both width and height. For each
436  * dimension, it can specify one of:
437  * <ul>
438  * <li> an exact number
439  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
440  * (minus padding)
441  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
442  * enclose its content (plus padding).
443  * </ul>
444  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
445  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
446  * an X and Y value.
447  * </p>
448  *
449  * <p>
450  * MeasureSpecs are used to push requirements down the tree from parent to
451  * child. A MeasureSpec can be in one of three modes:
452  * <ul>
453  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
454  * of a child view. For example, a LinearLayout may call measure() on its child
455  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
456  * tall the child view wants to be given a width of 240 pixels.
457  * <li>EXACTLY: This is used by the parent to impose an exact size on the
458  * child. The child must use this size, and guarantee that all of its
459  * descendants will fit within this size.
460  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
461  * child. The child must guarantee that it and all of its descendants will fit
462  * within this size.
463  * </ul>
464  * </p>
465  *
466  * <p>
467  * To initiate a layout, call {@link #requestLayout}. This method is typically
468  * called by a view on itself when it believes that is can no longer fit within
469  * its current bounds.
470  * </p>
471  *
472  * <a name="Drawing"></a>
473  * <h3>Drawing</h3>
474  * <p>
475  * Drawing is handled by walking the tree and recording the drawing commands of
476  * any View that needs to update. After this, the drawing commands of the
477  * entire tree are issued to screen, clipped to the newly damaged area.
478  * </p>
479  *
480  * <p>
481  * The tree is largely recorded and drawn in order, with parents drawn before
482  * (i.e., behind) their children, with siblings drawn in the order they appear
483  * in the tree. If you set a background drawable for a View, then the View will
484  * draw it before calling back to its <code>onDraw()</code> method. The child
485  * drawing order can be overridden with
486  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
487  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
488  * </p>
489  *
490  * <p>
491  * To force a view to draw, call {@link #invalidate()}.
492  * </p>
493  *
494  * <a name="EventHandlingThreading"></a>
495  * <h3>Event Handling and Threading</h3>
496  * <p>
497  * The basic cycle of a view is as follows:
498  * <ol>
499  * <li>An event comes in and is dispatched to the appropriate view. The view
500  * handles the event and notifies any listeners.</li>
501  * <li>If in the course of processing the event, the view's bounds may need
502  * to be changed, the view will call {@link #requestLayout()}.</li>
503  * <li>Similarly, if in the course of processing the event the view's appearance
504  * may need to be changed, the view will call {@link #invalidate()}.</li>
505  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
506  * the framework will take care of measuring, laying out, and drawing the tree
507  * as appropriate.</li>
508  * </ol>
509  * </p>
510  *
511  * <p><em>Note: The entire view tree is single threaded. You must always be on
512  * the UI thread when calling any method on any view.</em>
513  * If you are doing work on other threads and want to update the state of a view
514  * from that thread, you should use a {@link Handler}.
515  * </p>
516  *
517  * <a name="FocusHandling"></a>
518  * <h3>Focus Handling</h3>
519  * <p>
520  * The framework will handle routine focus movement in response to user input.
521  * This includes changing the focus as views are removed or hidden, or as new
522  * views become available. Views indicate their willingness to take focus
523  * through the {@link #isFocusable} method. To change whether a view can take
524  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
525  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
526  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
527  * </p>
528  * <p>
529  * Focus movement is based on an algorithm which finds the nearest neighbor in a
530  * given direction. In rare cases, the default algorithm may not match the
531  * intended behavior of the developer. In these situations, you can provide
532  * explicit overrides by using these XML attributes in the layout file:
533  * <pre>
534  * nextFocusDown
535  * nextFocusLeft
536  * nextFocusRight
537  * nextFocusUp
538  * </pre>
539  * </p>
540  *
541  *
542  * <p>
543  * To get a particular view to take focus, call {@link #requestFocus()}.
544  * </p>
545  *
546  * <a name="TouchMode"></a>
547  * <h3>Touch Mode</h3>
548  * <p>
549  * When a user is navigating a user interface via directional keys such as a D-pad, it is
550  * necessary to give focus to actionable items such as buttons so the user can see
551  * what will take input.  If the device has touch capabilities, however, and the user
552  * begins interacting with the interface by touching it, it is no longer necessary to
553  * always highlight, or give focus to, a particular view.  This motivates a mode
554  * for interaction named 'touch mode'.
555  * </p>
556  * <p>
557  * For a touch capable device, once the user touches the screen, the device
558  * will enter touch mode.  From this point onward, only views for which
559  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
560  * Other views that are touchable, like buttons, will not take focus when touched; they will
561  * only fire the on click listeners.
562  * </p>
563  * <p>
564  * Any time a user hits a directional key, such as a D-pad direction, the view device will
565  * exit touch mode, and find a view to take focus, so that the user may resume interacting
566  * with the user interface without touching the screen again.
567  * </p>
568  * <p>
569  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
570  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
571  * </p>
572  *
573  * <a name="Scrolling"></a>
574  * <h3>Scrolling</h3>
575  * <p>
576  * The framework provides basic support for views that wish to internally
577  * scroll their content. This includes keeping track of the X and Y scroll
578  * offset as well as mechanisms for drawing scrollbars. See
579  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
580  * {@link #awakenScrollBars()} for more details.
581  * </p>
582  *
583  * <a name="Tags"></a>
584  * <h3>Tags</h3>
585  * <p>
586  * Unlike IDs, tags are not used to identify views. Tags are essentially an
587  * extra piece of information that can be associated with a view. They are most
588  * often used as a convenience to store data related to views in the views
589  * themselves rather than by putting them in a separate structure.
590  * </p>
591  * <p>
592  * Tags may be specified with character sequence values in layout XML as either
593  * a single tag using the {@link android.R.styleable#View_tag android:tag}
594  * attribute or multiple tags using the {@code <tag>} child element:
595  * <pre>
596  *     &lt;View ...
597  *           android:tag="@string/mytag_value" /&gt;
598  *     &lt;View ...&gt;
599  *         &lt;tag android:id="@+id/mytag"
600  *              android:value="@string/mytag_value" /&gt;
601  *     &lt;/View>
602  * </pre>
603  * </p>
604  * <p>
605  * Tags may also be specified with arbitrary objects from code using
606  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
607  * </p>
608  *
609  * <a name="Themes"></a>
610  * <h3>Themes</h3>
611  * <p>
612  * By default, Views are created using the theme of the Context object supplied
613  * to their constructor; however, a different theme may be specified by using
614  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
615  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
616  * code.
617  * </p>
618  * <p>
619  * When the {@link android.R.styleable#View_theme android:theme} attribute is
620  * used in XML, the specified theme is applied on top of the inflation
621  * context's theme (see {@link LayoutInflater}) and used for the view itself as
622  * well as any child elements.
623  * </p>
624  * <p>
625  * In the following example, both views will be created using the Material dark
626  * color scheme; however, because an overlay theme is used which only defines a
627  * subset of attributes, the value of
628  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
629  * the inflation context's theme (e.g. the Activity theme) will be preserved.
630  * <pre>
631  *     &lt;LinearLayout
632  *             ...
633  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
634  *         &lt;View ...&gt;
635  *     &lt;/LinearLayout&gt;
636  * </pre>
637  * </p>
638  *
639  * <a name="Properties"></a>
640  * <h3>Properties</h3>
641  * <p>
642  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
643  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
644  * available both in the {@link Property} form as well as in similarly-named setter/getter
645  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
646  * be used to set persistent state associated with these rendering-related properties on the view.
647  * The properties and methods can also be used in conjunction with
648  * {@link android.animation.Animator Animator}-based animations, described more in the
649  * <a href="#Animation">Animation</a> section.
650  * </p>
651  *
652  * <a name="Animation"></a>
653  * <h3>Animation</h3>
654  * <p>
655  * Starting with Android 3.0, the preferred way of animating views is to use the
656  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
657  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
658  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
659  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
660  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
661  * makes animating these View properties particularly easy and efficient.
662  * </p>
663  * <p>
664  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
665  * You can attach an {@link Animation} object to a view using
666  * {@link #setAnimation(Animation)} or
667  * {@link #startAnimation(Animation)}. The animation can alter the scale,
668  * rotation, translation and alpha of a view over time. If the animation is
669  * attached to a view that has children, the animation will affect the entire
670  * subtree rooted by that node. When an animation is started, the framework will
671  * take care of redrawing the appropriate views until the animation completes.
672  * </p>
673  *
674  * <a name="Security"></a>
675  * <h3>Security</h3>
676  * <p>
677  * Sometimes it is essential that an application be able to verify that an action
678  * is being performed with the full knowledge and consent of the user, such as
679  * granting a permission request, making a purchase or clicking on an advertisement.
680  * Unfortunately, a malicious application could try to spoof the user into
681  * performing these actions, unaware, by concealing the intended purpose of the view.
682  * As a remedy, the framework offers a touch filtering mechanism that can be used to
683  * improve the security of views that provide access to sensitive functionality.
684  * </p><p>
685  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
686  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
687  * will discard touches that are received whenever the view's window is obscured by
688  * another visible window.  As a result, the view will not receive touches whenever a
689  * toast, dialog or other window appears above the view's window.
690  * </p><p>
691  * For more fine-grained control over security, consider overriding the
692  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
693  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
694  * </p>
695  *
696  * @attr ref android.R.styleable#View_alpha
697  * @attr ref android.R.styleable#View_background
698  * @attr ref android.R.styleable#View_clickable
699  * @attr ref android.R.styleable#View_contentDescription
700  * @attr ref android.R.styleable#View_drawingCacheQuality
701  * @attr ref android.R.styleable#View_duplicateParentState
702  * @attr ref android.R.styleable#View_id
703  * @attr ref android.R.styleable#View_requiresFadingEdge
704  * @attr ref android.R.styleable#View_fadeScrollbars
705  * @attr ref android.R.styleable#View_fadingEdgeLength
706  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
707  * @attr ref android.R.styleable#View_fitsSystemWindows
708  * @attr ref android.R.styleable#View_isScrollContainer
709  * @attr ref android.R.styleable#View_focusable
710  * @attr ref android.R.styleable#View_focusableInTouchMode
711  * @attr ref android.R.styleable#View_focusedByDefault
712  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
713  * @attr ref android.R.styleable#View_keepScreenOn
714  * @attr ref android.R.styleable#View_keyboardNavigationCluster
715  * @attr ref android.R.styleable#View_layerType
716  * @attr ref android.R.styleable#View_layoutDirection
717  * @attr ref android.R.styleable#View_longClickable
718  * @attr ref android.R.styleable#View_minHeight
719  * @attr ref android.R.styleable#View_minWidth
720  * @attr ref android.R.styleable#View_nextClusterForward
721  * @attr ref android.R.styleable#View_nextFocusDown
722  * @attr ref android.R.styleable#View_nextFocusLeft
723  * @attr ref android.R.styleable#View_nextFocusRight
724  * @attr ref android.R.styleable#View_nextFocusUp
725  * @attr ref android.R.styleable#View_onClick
726  * @attr ref android.R.styleable#View_padding
727  * @attr ref android.R.styleable#View_paddingBottom
728  * @attr ref android.R.styleable#View_paddingLeft
729  * @attr ref android.R.styleable#View_paddingRight
730  * @attr ref android.R.styleable#View_paddingTop
731  * @attr ref android.R.styleable#View_paddingStart
732  * @attr ref android.R.styleable#View_paddingEnd
733  * @attr ref android.R.styleable#View_saveEnabled
734  * @attr ref android.R.styleable#View_rotation
735  * @attr ref android.R.styleable#View_rotationX
736  * @attr ref android.R.styleable#View_rotationY
737  * @attr ref android.R.styleable#View_scaleX
738  * @attr ref android.R.styleable#View_scaleY
739  * @attr ref android.R.styleable#View_scrollX
740  * @attr ref android.R.styleable#View_scrollY
741  * @attr ref android.R.styleable#View_scrollbarSize
742  * @attr ref android.R.styleable#View_scrollbarStyle
743  * @attr ref android.R.styleable#View_scrollbars
744  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
745  * @attr ref android.R.styleable#View_scrollbarFadeDuration
746  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
747  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
748  * @attr ref android.R.styleable#View_scrollbarThumbVertical
749  * @attr ref android.R.styleable#View_scrollbarTrackVertical
750  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
751  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
752  * @attr ref android.R.styleable#View_stateListAnimator
753  * @attr ref android.R.styleable#View_transitionName
754  * @attr ref android.R.styleable#View_soundEffectsEnabled
755  * @attr ref android.R.styleable#View_tag
756  * @attr ref android.R.styleable#View_textAlignment
757  * @attr ref android.R.styleable#View_textDirection
758  * @attr ref android.R.styleable#View_transformPivotX
759  * @attr ref android.R.styleable#View_transformPivotY
760  * @attr ref android.R.styleable#View_translationX
761  * @attr ref android.R.styleable#View_translationY
762  * @attr ref android.R.styleable#View_translationZ
763  * @attr ref android.R.styleable#View_visibility
764  * @attr ref android.R.styleable#View_theme
765  *
766  * @see android.view.ViewGroup
767  */
768 @UiThread
769 public class View implements Drawable.Callback, KeyEvent.Callback,
770         AccessibilityEventSource {
771     private static final boolean DBG = false;
772
773     /** @hide */
774     public static boolean DEBUG_DRAW = false;
775
776     /**
777      * The logging tag used by this class with android.util.Log.
778      */
779     protected static final String VIEW_LOG_TAG = "View";
780
781     /**
782      * When set to true, apps will draw debugging information about their layouts.
783      *
784      * @hide
785      */
786     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
787
788     /**
789      * When set to true, this view will save its attribute data.
790      *
791      * @hide
792      */
793     public static boolean mDebugViewAttributes = false;
794
795     /**
796      * Used to mark a View that has no ID.
797      */
798     public static final int NO_ID = -1;
799
800     /**
801      * Last ID that is given to Views that are no part of activities.
802      *
803      * {@hide}
804      */
805     public static final int LAST_APP_ACCESSIBILITY_ID = Integer.MAX_VALUE / 2;
806
807     /**
808      * Attribute to find the autofilled highlight
809      *
810      * @see #getAutofilledDrawable()
811      */
812     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
813             new int[]{android.R.attr.autofilledHighlight};
814
815     /**
816      * Signals that compatibility booleans have been initialized according to
817      * target SDK versions.
818      */
819     private static boolean sCompatibilityDone = false;
820
821     /**
822      * Use the old (broken) way of building MeasureSpecs.
823      */
824     private static boolean sUseBrokenMakeMeasureSpec = false;
825
826     /**
827      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
828      */
829     static boolean sUseZeroUnspecifiedMeasureSpec = false;
830
831     /**
832      * Ignore any optimizations using the measure cache.
833      */
834     private static boolean sIgnoreMeasureCache = false;
835
836     /**
837      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
838      */
839     private static boolean sAlwaysRemeasureExactly = false;
840
841     /**
842      * Relax constraints around whether setLayoutParams() must be called after
843      * modifying the layout params.
844      */
845     private static boolean sLayoutParamsAlwaysChanged = false;
846
847     /**
848      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
849      * without throwing
850      */
851     static boolean sTextureViewIgnoresDrawableSetters = false;
852
853     /**
854      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
855      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
856      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
857      * check is implemented for backwards compatibility.
858      *
859      * {@hide}
860      */
861     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
862
863     /**
864      * Prior to N, when drag enters into child of a view that has already received an
865      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
866      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
867      * false from its event handler for these events.
868      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
869      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
870      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
871      */
872     static boolean sCascadedDragDrop;
873
874     /**
875      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
876      * to determine things like whether or not to permit item click events. We can't break
877      * apps that do this just because more things (clickable things) are now auto-focusable
878      * and they would get different results, so give old behavior to old apps.
879      */
880     static boolean sHasFocusableExcludeAutoFocusable;
881
882     /**
883      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
884      * made focusable by default. As a result, apps could (incorrectly) change the clickable
885      * setting of views off the UI thread. Now that clickable can effect the focusable state,
886      * changing the clickable attribute off the UI thread will cause an exception (since changing
887      * the focusable state checks). In order to prevent apps from crashing, we will handle this
888      * specific case and just not notify parents on new focusables resulting from marking views
889      * clickable from outside the UI thread.
890      */
891     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
892
893     /** @hide */
894     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
895     @Retention(RetentionPolicy.SOURCE)
896     public @interface Focusable {}
897
898     /**
899      * This view does not want keystrokes.
900      * <p>
901      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
902      * android:focusable}.
903      */
904     public static final int NOT_FOCUSABLE = 0x00000000;
905
906     /**
907      * This view wants keystrokes.
908      * <p>
909      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
910      * android:focusable}.
911      */
912     public static final int FOCUSABLE = 0x00000001;
913
914     /**
915      * This view determines focusability automatically. This is the default.
916      * <p>
917      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
918      * android:focusable}.
919      */
920     public static final int FOCUSABLE_AUTO = 0x00000010;
921
922     /**
923      * Mask for use with setFlags indicating bits used for focus.
924      */
925     private static final int FOCUSABLE_MASK = 0x00000011;
926
927     /**
928      * This view will adjust its padding to fit sytem windows (e.g. status bar)
929      */
930     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
931
932     /** @hide */
933     @IntDef({VISIBLE, INVISIBLE, GONE})
934     @Retention(RetentionPolicy.SOURCE)
935     public @interface Visibility {}
936
937     /**
938      * This view is visible.
939      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
940      * android:visibility}.
941      */
942     public static final int VISIBLE = 0x00000000;
943
944     /**
945      * This view is invisible, but it still takes up space for layout purposes.
946      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
947      * android:visibility}.
948      */
949     public static final int INVISIBLE = 0x00000004;
950
951     /**
952      * This view is invisible, and it doesn't take any space for layout
953      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
954      * android:visibility}.
955      */
956     public static final int GONE = 0x00000008;
957
958     /**
959      * Mask for use with setFlags indicating bits used for visibility.
960      * {@hide}
961      */
962     static final int VISIBILITY_MASK = 0x0000000C;
963
964     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
965
966     /**
967      * Hint indicating that this view can be autofilled with an email address.
968      *
969      * <p>Can be used with either {@link #setAutofillHints(String[])} or
970      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
971      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
972      *
973      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
974      */
975     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
976
977     /**
978      * Hint indicating that this view can be autofilled with a user's real name.
979      *
980      * <p>Can be used with either {@link #setAutofillHints(String[])} or
981      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
982      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
983      *
984      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
985      */
986     public static final String AUTOFILL_HINT_NAME = "name";
987
988     /**
989      * Hint indicating that this view can be autofilled with a username.
990      *
991      * <p>Can be used with either {@link #setAutofillHints(String[])} or
992      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
993      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
994      *
995      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
996      */
997     public static final String AUTOFILL_HINT_USERNAME = "username";
998
999     /**
1000      * Hint indicating that this view can be autofilled with a password.
1001      *
1002      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1003      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1004      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1005      *
1006      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1007      */
1008     public static final String AUTOFILL_HINT_PASSWORD = "password";
1009
1010     /**
1011      * Hint indicating that this view can be autofilled with a phone number.
1012      *
1013      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1014      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1015      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1016      *
1017      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1018      */
1019     public static final String AUTOFILL_HINT_PHONE = "phone";
1020
1021     /**
1022      * Hint indicating that this view can be autofilled with a postal address.
1023      *
1024      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1025      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1026      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1027      *
1028      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1029      */
1030     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1031
1032     /**
1033      * Hint indicating that this view can be autofilled with a postal code.
1034      *
1035      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1036      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1037      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1038      *
1039      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1040      */
1041     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1042
1043     /**
1044      * Hint indicating that this view can be autofilled with a credit card number.
1045      *
1046      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1047      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1048      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1049      *
1050      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1051      */
1052     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1053
1054     /**
1055      * Hint indicating that this view can be autofilled with a credit card security code.
1056      *
1057      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1058      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1059      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1060      *
1061      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1062      */
1063     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1064
1065     /**
1066      * Hint indicating that this view can be autofilled with a credit card expiration date.
1067      *
1068      * <p>It should be used when the credit card expiration date is represented by just one view;
1069      * if it is represented by more than one (for example, one view for the month and another view
1070      * for the year), then each of these views should use the hint specific for the unit
1071      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1072      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1073      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1074      *
1075      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1076      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1077      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1078      *
1079      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1080      */
1081     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1082             "creditCardExpirationDate";
1083
1084     /**
1085      * Hint indicating that this view can be autofilled with a credit card expiration month.
1086      *
1087      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1088      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1089      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1090      *
1091      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1092      */
1093     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1094             "creditCardExpirationMonth";
1095
1096     /**
1097      * Hint indicating that this view can be autofilled with a credit card expiration year.
1098      *
1099      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1100      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1101      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1102      *
1103      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1104      */
1105     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1106             "creditCardExpirationYear";
1107
1108     /**
1109      * Hint indicating that this view can be autofilled with a credit card expiration day.
1110      *
1111      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1112      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1113      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1114      *
1115      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1116      */
1117     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1118
1119     /**
1120      * Hints for the autofill services that describes the content of the view.
1121      */
1122     private @Nullable String[] mAutofillHints;
1123
1124     /**
1125      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1126      */
1127     private AutofillId mAutofillId;
1128
1129     /** @hide */
1130     @IntDef({
1131             AUTOFILL_TYPE_NONE,
1132             AUTOFILL_TYPE_TEXT,
1133             AUTOFILL_TYPE_TOGGLE,
1134             AUTOFILL_TYPE_LIST,
1135             AUTOFILL_TYPE_DATE
1136     })
1137     @Retention(RetentionPolicy.SOURCE)
1138     public @interface AutofillType {}
1139
1140     /**
1141      * Autofill type for views that cannot be autofilled.
1142      */
1143     public static final int AUTOFILL_TYPE_NONE = 0;
1144
1145     /**
1146      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1147      *
1148      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1149      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1150      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1151      */
1152     public static final int AUTOFILL_TYPE_TEXT = 1;
1153
1154     /**
1155      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1156      *
1157      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1158      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1159      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1160      */
1161     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1162
1163     /**
1164      * Autofill type for a selection list field, which is filled by an {@code int}
1165      * representing the element index inside the list (starting at {@code 0}).
1166      *
1167      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1168      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1169      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1170      *
1171      * <p>The available options in the selection list are typically provided by
1172      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1173      */
1174     public static final int AUTOFILL_TYPE_LIST = 3;
1175
1176
1177     /**
1178      * Autofill type for a field that contains a date, which is represented by a long representing
1179      * the number of milliseconds since the standard base time known as "the epoch", namely
1180      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1181      *
1182      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1183      * {@link AutofillValue#forDate(long)}, and the values passed to
1184      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1185      */
1186     public static final int AUTOFILL_TYPE_DATE = 4;
1187
1188     /** @hide */
1189     @IntDef({
1190             IMPORTANT_FOR_AUTOFILL_AUTO,
1191             IMPORTANT_FOR_AUTOFILL_YES,
1192             IMPORTANT_FOR_AUTOFILL_NO,
1193             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1194             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1195     })
1196     @Retention(RetentionPolicy.SOURCE)
1197     public @interface AutofillImportance {}
1198
1199     /**
1200      * Automatically determine whether a view is important for autofill.
1201      */
1202     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1203
1204     /**
1205      * The view is important for autofill, and its children (if any) will be traversed.
1206      */
1207     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1208
1209     /**
1210      * The view is not important for autofill, but its children (if any) will be traversed.
1211      */
1212     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1213
1214     /**
1215      * The view is important for autofill, but its children (if any) will not be traversed.
1216      */
1217     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1218
1219     /**
1220      * The view is not important for autofill, and its children (if any) will not be traversed.
1221      */
1222     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1223
1224     /** @hide */
1225     @IntDef(
1226             flag = true,
1227             value = {AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS})
1228     @Retention(RetentionPolicy.SOURCE)
1229     public @interface AutofillFlags {}
1230
1231     /**
1232      * Flag requesting you to add views that are marked as not important for autofill
1233      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1234      */
1235     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1236
1237     /**
1238      * This view is enabled. Interpretation varies by subclass.
1239      * Use with ENABLED_MASK when calling setFlags.
1240      * {@hide}
1241      */
1242     static final int ENABLED = 0x00000000;
1243
1244     /**
1245      * This view is disabled. Interpretation varies by subclass.
1246      * Use with ENABLED_MASK when calling setFlags.
1247      * {@hide}
1248      */
1249     static final int DISABLED = 0x00000020;
1250
1251    /**
1252     * Mask for use with setFlags indicating bits used for indicating whether
1253     * this view is enabled
1254     * {@hide}
1255     */
1256     static final int ENABLED_MASK = 0x00000020;
1257
1258     /**
1259      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1260      * called and further optimizations will be performed. It is okay to have
1261      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1262      * {@hide}
1263      */
1264     static final int WILL_NOT_DRAW = 0x00000080;
1265
1266     /**
1267      * Mask for use with setFlags indicating bits used for indicating whether
1268      * this view is will draw
1269      * {@hide}
1270      */
1271     static final int DRAW_MASK = 0x00000080;
1272
1273     /**
1274      * <p>This view doesn't show scrollbars.</p>
1275      * {@hide}
1276      */
1277     static final int SCROLLBARS_NONE = 0x00000000;
1278
1279     /**
1280      * <p>This view shows horizontal scrollbars.</p>
1281      * {@hide}
1282      */
1283     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1284
1285     /**
1286      * <p>This view shows vertical scrollbars.</p>
1287      * {@hide}
1288      */
1289     static final int SCROLLBARS_VERTICAL = 0x00000200;
1290
1291     /**
1292      * <p>Mask for use with setFlags indicating bits used for indicating which
1293      * scrollbars are enabled.</p>
1294      * {@hide}
1295      */
1296     static final int SCROLLBARS_MASK = 0x00000300;
1297
1298     /**
1299      * Indicates that the view should filter touches when its window is obscured.
1300      * Refer to the class comments for more information about this security feature.
1301      * {@hide}
1302      */
1303     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1304
1305     /**
1306      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1307      * that they are optional and should be skipped if the window has
1308      * requested system UI flags that ignore those insets for layout.
1309      */
1310     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1311
1312     /**
1313      * <p>This view doesn't show fading edges.</p>
1314      * {@hide}
1315      */
1316     static final int FADING_EDGE_NONE = 0x00000000;
1317
1318     /**
1319      * <p>This view shows horizontal fading edges.</p>
1320      * {@hide}
1321      */
1322     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1323
1324     /**
1325      * <p>This view shows vertical fading edges.</p>
1326      * {@hide}
1327      */
1328     static final int FADING_EDGE_VERTICAL = 0x00002000;
1329
1330     /**
1331      * <p>Mask for use with setFlags indicating bits used for indicating which
1332      * fading edges are enabled.</p>
1333      * {@hide}
1334      */
1335     static final int FADING_EDGE_MASK = 0x00003000;
1336
1337     /**
1338      * <p>Indicates this view can be clicked. When clickable, a View reacts
1339      * to clicks by notifying the OnClickListener.<p>
1340      * {@hide}
1341      */
1342     static final int CLICKABLE = 0x00004000;
1343
1344     /**
1345      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1346      * {@hide}
1347      */
1348     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1349
1350     /**
1351      * <p>Indicates that no icicle should be saved for this view.<p>
1352      * {@hide}
1353      */
1354     static final int SAVE_DISABLED = 0x000010000;
1355
1356     /**
1357      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1358      * property.</p>
1359      * {@hide}
1360      */
1361     static final int SAVE_DISABLED_MASK = 0x000010000;
1362
1363     /**
1364      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1365      * {@hide}
1366      */
1367     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1368
1369     /**
1370      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1371      * {@hide}
1372      */
1373     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1374
1375     /** @hide */
1376     @Retention(RetentionPolicy.SOURCE)
1377     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1378     public @interface DrawingCacheQuality {}
1379
1380     /**
1381      * <p>Enables low quality mode for the drawing cache.</p>
1382      */
1383     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1384
1385     /**
1386      * <p>Enables high quality mode for the drawing cache.</p>
1387      */
1388     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1389
1390     /**
1391      * <p>Enables automatic quality mode for the drawing cache.</p>
1392      */
1393     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1394
1395     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1396             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1397     };
1398
1399     /**
1400      * <p>Mask for use with setFlags indicating bits used for the cache
1401      * quality property.</p>
1402      * {@hide}
1403      */
1404     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1405
1406     /**
1407      * <p>
1408      * Indicates this view can be long clicked. When long clickable, a View
1409      * reacts to long clicks by notifying the OnLongClickListener or showing a
1410      * context menu.
1411      * </p>
1412      * {@hide}
1413      */
1414     static final int LONG_CLICKABLE = 0x00200000;
1415
1416     /**
1417      * <p>Indicates that this view gets its drawable states from its direct parent
1418      * and ignores its original internal states.</p>
1419      *
1420      * @hide
1421      */
1422     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1423
1424     /**
1425      * <p>
1426      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1427      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1428      * OnContextClickListener.
1429      * </p>
1430      * {@hide}
1431      */
1432     static final int CONTEXT_CLICKABLE = 0x00800000;
1433
1434
1435     /** @hide */
1436     @IntDef({
1437         SCROLLBARS_INSIDE_OVERLAY,
1438         SCROLLBARS_INSIDE_INSET,
1439         SCROLLBARS_OUTSIDE_OVERLAY,
1440         SCROLLBARS_OUTSIDE_INSET
1441     })
1442     @Retention(RetentionPolicy.SOURCE)
1443     public @interface ScrollBarStyle {}
1444
1445     /**
1446      * The scrollbar style to display the scrollbars inside the content area,
1447      * without increasing the padding. The scrollbars will be overlaid with
1448      * translucency on the view's content.
1449      */
1450     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1451
1452     /**
1453      * The scrollbar style to display the scrollbars inside the padded area,
1454      * increasing the padding of the view. The scrollbars will not overlap the
1455      * content area of the view.
1456      */
1457     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1458
1459     /**
1460      * The scrollbar style to display the scrollbars at the edge of the view,
1461      * without increasing the padding. The scrollbars will be overlaid with
1462      * translucency.
1463      */
1464     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1465
1466     /**
1467      * The scrollbar style to display the scrollbars at the edge of the view,
1468      * increasing the padding of the view. The scrollbars will only overlap the
1469      * background, if any.
1470      */
1471     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1472
1473     /**
1474      * Mask to check if the scrollbar style is overlay or inset.
1475      * {@hide}
1476      */
1477     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1478
1479     /**
1480      * Mask to check if the scrollbar style is inside or outside.
1481      * {@hide}
1482      */
1483     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1484
1485     /**
1486      * Mask for scrollbar style.
1487      * {@hide}
1488      */
1489     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1490
1491     /**
1492      * View flag indicating that the screen should remain on while the
1493      * window containing this view is visible to the user.  This effectively
1494      * takes care of automatically setting the WindowManager's
1495      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1496      */
1497     public static final int KEEP_SCREEN_ON = 0x04000000;
1498
1499     /**
1500      * View flag indicating whether this view should have sound effects enabled
1501      * for events such as clicking and touching.
1502      */
1503     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1504
1505     /**
1506      * View flag indicating whether this view should have haptic feedback
1507      * enabled for events such as long presses.
1508      */
1509     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1510
1511     /**
1512      * <p>Indicates that the view hierarchy should stop saving state when
1513      * it reaches this view.  If state saving is initiated immediately at
1514      * the view, it will be allowed.
1515      * {@hide}
1516      */
1517     static final int PARENT_SAVE_DISABLED = 0x20000000;
1518
1519     /**
1520      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1521      * {@hide}
1522      */
1523     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1524
1525     private static Paint sDebugPaint;
1526
1527     /**
1528      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1529      * {@hide}
1530      */
1531     static final int TOOLTIP = 0x40000000;
1532
1533     /** @hide */
1534     @IntDef(flag = true,
1535             value = {
1536                 FOCUSABLES_ALL,
1537                 FOCUSABLES_TOUCH_MODE
1538             })
1539     @Retention(RetentionPolicy.SOURCE)
1540     public @interface FocusableMode {}
1541
1542     /**
1543      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1544      * should add all focusable Views regardless if they are focusable in touch mode.
1545      */
1546     public static final int FOCUSABLES_ALL = 0x00000000;
1547
1548     /**
1549      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1550      * should add only Views focusable in touch mode.
1551      */
1552     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1553
1554     /** @hide */
1555     @IntDef({
1556             FOCUS_BACKWARD,
1557             FOCUS_FORWARD,
1558             FOCUS_LEFT,
1559             FOCUS_UP,
1560             FOCUS_RIGHT,
1561             FOCUS_DOWN
1562     })
1563     @Retention(RetentionPolicy.SOURCE)
1564     public @interface FocusDirection {}
1565
1566     /** @hide */
1567     @IntDef({
1568             FOCUS_LEFT,
1569             FOCUS_UP,
1570             FOCUS_RIGHT,
1571             FOCUS_DOWN
1572     })
1573     @Retention(RetentionPolicy.SOURCE)
1574     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1575
1576     /**
1577      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1578      * item.
1579      */
1580     public static final int FOCUS_BACKWARD = 0x00000001;
1581
1582     /**
1583      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1584      * item.
1585      */
1586     public static final int FOCUS_FORWARD = 0x00000002;
1587
1588     /**
1589      * Use with {@link #focusSearch(int)}. Move focus to the left.
1590      */
1591     public static final int FOCUS_LEFT = 0x00000011;
1592
1593     /**
1594      * Use with {@link #focusSearch(int)}. Move focus up.
1595      */
1596     public static final int FOCUS_UP = 0x00000021;
1597
1598     /**
1599      * Use with {@link #focusSearch(int)}. Move focus to the right.
1600      */
1601     public static final int FOCUS_RIGHT = 0x00000042;
1602
1603     /**
1604      * Use with {@link #focusSearch(int)}. Move focus down.
1605      */
1606     public static final int FOCUS_DOWN = 0x00000082;
1607
1608     /**
1609      * Bits of {@link #getMeasuredWidthAndState()} and
1610      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1611      */
1612     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1613
1614     /**
1615      * Bits of {@link #getMeasuredWidthAndState()} and
1616      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1617      */
1618     public static final int MEASURED_STATE_MASK = 0xff000000;
1619
1620     /**
1621      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1622      * for functions that combine both width and height into a single int,
1623      * such as {@link #getMeasuredState()} and the childState argument of
1624      * {@link #resolveSizeAndState(int, int, int)}.
1625      */
1626     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1627
1628     /**
1629      * Bit of {@link #getMeasuredWidthAndState()} and
1630      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1631      * is smaller that the space the view would like to have.
1632      */
1633     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1634
1635     /**
1636      * Base View state sets
1637      */
1638     // Singles
1639     /**
1640      * Indicates the view has no states set. States are used with
1641      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1642      * view depending on its state.
1643      *
1644      * @see android.graphics.drawable.Drawable
1645      * @see #getDrawableState()
1646      */
1647     protected static final int[] EMPTY_STATE_SET;
1648     /**
1649      * Indicates the view is enabled. States are used with
1650      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1651      * view depending on its state.
1652      *
1653      * @see android.graphics.drawable.Drawable
1654      * @see #getDrawableState()
1655      */
1656     protected static final int[] ENABLED_STATE_SET;
1657     /**
1658      * Indicates the view is focused. States are used with
1659      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1660      * view depending on its state.
1661      *
1662      * @see android.graphics.drawable.Drawable
1663      * @see #getDrawableState()
1664      */
1665     protected static final int[] FOCUSED_STATE_SET;
1666     /**
1667      * Indicates the view is selected. States are used with
1668      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1669      * view depending on its state.
1670      *
1671      * @see android.graphics.drawable.Drawable
1672      * @see #getDrawableState()
1673      */
1674     protected static final int[] SELECTED_STATE_SET;
1675     /**
1676      * Indicates the view is pressed. States are used with
1677      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1678      * view depending on its state.
1679      *
1680      * @see android.graphics.drawable.Drawable
1681      * @see #getDrawableState()
1682      */
1683     protected static final int[] PRESSED_STATE_SET;
1684     /**
1685      * Indicates the view's window has focus. States are used with
1686      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1687      * view depending on its state.
1688      *
1689      * @see android.graphics.drawable.Drawable
1690      * @see #getDrawableState()
1691      */
1692     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1693     // Doubles
1694     /**
1695      * Indicates the view is enabled and has the focus.
1696      *
1697      * @see #ENABLED_STATE_SET
1698      * @see #FOCUSED_STATE_SET
1699      */
1700     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1701     /**
1702      * Indicates the view is enabled and selected.
1703      *
1704      * @see #ENABLED_STATE_SET
1705      * @see #SELECTED_STATE_SET
1706      */
1707     protected static final int[] ENABLED_SELECTED_STATE_SET;
1708     /**
1709      * Indicates the view is enabled and that its window has focus.
1710      *
1711      * @see #ENABLED_STATE_SET
1712      * @see #WINDOW_FOCUSED_STATE_SET
1713      */
1714     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1715     /**
1716      * Indicates the view is focused and selected.
1717      *
1718      * @see #FOCUSED_STATE_SET
1719      * @see #SELECTED_STATE_SET
1720      */
1721     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1722     /**
1723      * Indicates the view has the focus and that its window has the focus.
1724      *
1725      * @see #FOCUSED_STATE_SET
1726      * @see #WINDOW_FOCUSED_STATE_SET
1727      */
1728     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1729     /**
1730      * Indicates the view is selected and that its window has the focus.
1731      *
1732      * @see #SELECTED_STATE_SET
1733      * @see #WINDOW_FOCUSED_STATE_SET
1734      */
1735     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1736     // Triples
1737     /**
1738      * Indicates the view is enabled, focused and selected.
1739      *
1740      * @see #ENABLED_STATE_SET
1741      * @see #FOCUSED_STATE_SET
1742      * @see #SELECTED_STATE_SET
1743      */
1744     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1745     /**
1746      * Indicates the view is enabled, focused and its window has the focus.
1747      *
1748      * @see #ENABLED_STATE_SET
1749      * @see #FOCUSED_STATE_SET
1750      * @see #WINDOW_FOCUSED_STATE_SET
1751      */
1752     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1753     /**
1754      * Indicates the view is enabled, selected and its window has the focus.
1755      *
1756      * @see #ENABLED_STATE_SET
1757      * @see #SELECTED_STATE_SET
1758      * @see #WINDOW_FOCUSED_STATE_SET
1759      */
1760     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1761     /**
1762      * Indicates the view is focused, selected and its window has the focus.
1763      *
1764      * @see #FOCUSED_STATE_SET
1765      * @see #SELECTED_STATE_SET
1766      * @see #WINDOW_FOCUSED_STATE_SET
1767      */
1768     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1769     /**
1770      * Indicates the view is enabled, focused, selected and its window
1771      * has the focus.
1772      *
1773      * @see #ENABLED_STATE_SET
1774      * @see #FOCUSED_STATE_SET
1775      * @see #SELECTED_STATE_SET
1776      * @see #WINDOW_FOCUSED_STATE_SET
1777      */
1778     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1779     /**
1780      * Indicates the view is pressed and its window has the focus.
1781      *
1782      * @see #PRESSED_STATE_SET
1783      * @see #WINDOW_FOCUSED_STATE_SET
1784      */
1785     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1786     /**
1787      * Indicates the view is pressed and selected.
1788      *
1789      * @see #PRESSED_STATE_SET
1790      * @see #SELECTED_STATE_SET
1791      */
1792     protected static final int[] PRESSED_SELECTED_STATE_SET;
1793     /**
1794      * Indicates the view is pressed, selected and its window has the focus.
1795      *
1796      * @see #PRESSED_STATE_SET
1797      * @see #SELECTED_STATE_SET
1798      * @see #WINDOW_FOCUSED_STATE_SET
1799      */
1800     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1801     /**
1802      * Indicates the view is pressed and focused.
1803      *
1804      * @see #PRESSED_STATE_SET
1805      * @see #FOCUSED_STATE_SET
1806      */
1807     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1808     /**
1809      * Indicates the view is pressed, focused and its window has the focus.
1810      *
1811      * @see #PRESSED_STATE_SET
1812      * @see #FOCUSED_STATE_SET
1813      * @see #WINDOW_FOCUSED_STATE_SET
1814      */
1815     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1816     /**
1817      * Indicates the view is pressed, focused and selected.
1818      *
1819      * @see #PRESSED_STATE_SET
1820      * @see #SELECTED_STATE_SET
1821      * @see #FOCUSED_STATE_SET
1822      */
1823     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1824     /**
1825      * Indicates the view is pressed, focused, selected and its window has the focus.
1826      *
1827      * @see #PRESSED_STATE_SET
1828      * @see #FOCUSED_STATE_SET
1829      * @see #SELECTED_STATE_SET
1830      * @see #WINDOW_FOCUSED_STATE_SET
1831      */
1832     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1833     /**
1834      * Indicates the view is pressed and enabled.
1835      *
1836      * @see #PRESSED_STATE_SET
1837      * @see #ENABLED_STATE_SET
1838      */
1839     protected static final int[] PRESSED_ENABLED_STATE_SET;
1840     /**
1841      * Indicates the view is pressed, enabled and its window has the focus.
1842      *
1843      * @see #PRESSED_STATE_SET
1844      * @see #ENABLED_STATE_SET
1845      * @see #WINDOW_FOCUSED_STATE_SET
1846      */
1847     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1848     /**
1849      * Indicates the view is pressed, enabled and selected.
1850      *
1851      * @see #PRESSED_STATE_SET
1852      * @see #ENABLED_STATE_SET
1853      * @see #SELECTED_STATE_SET
1854      */
1855     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1856     /**
1857      * Indicates the view is pressed, enabled, selected and its window has the
1858      * focus.
1859      *
1860      * @see #PRESSED_STATE_SET
1861      * @see #ENABLED_STATE_SET
1862      * @see #SELECTED_STATE_SET
1863      * @see #WINDOW_FOCUSED_STATE_SET
1864      */
1865     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1866     /**
1867      * Indicates the view is pressed, enabled and focused.
1868      *
1869      * @see #PRESSED_STATE_SET
1870      * @see #ENABLED_STATE_SET
1871      * @see #FOCUSED_STATE_SET
1872      */
1873     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1874     /**
1875      * Indicates the view is pressed, enabled, focused and its window has the
1876      * focus.
1877      *
1878      * @see #PRESSED_STATE_SET
1879      * @see #ENABLED_STATE_SET
1880      * @see #FOCUSED_STATE_SET
1881      * @see #WINDOW_FOCUSED_STATE_SET
1882      */
1883     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1884     /**
1885      * Indicates the view is pressed, enabled, focused and selected.
1886      *
1887      * @see #PRESSED_STATE_SET
1888      * @see #ENABLED_STATE_SET
1889      * @see #SELECTED_STATE_SET
1890      * @see #FOCUSED_STATE_SET
1891      */
1892     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1893     /**
1894      * Indicates the view is pressed, enabled, focused, selected and its window
1895      * has the focus.
1896      *
1897      * @see #PRESSED_STATE_SET
1898      * @see #ENABLED_STATE_SET
1899      * @see #SELECTED_STATE_SET
1900      * @see #FOCUSED_STATE_SET
1901      * @see #WINDOW_FOCUSED_STATE_SET
1902      */
1903     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1904
1905     static {
1906         EMPTY_STATE_SET = StateSet.get(0);
1907
1908         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1909
1910         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1911         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1912                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1913
1914         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1915         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1916                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1917         FOCUSED_SELECTED_STATE_SET = StateSet.get(
1918                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1919         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1920                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1921                         | StateSet.VIEW_STATE_FOCUSED);
1922
1923         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1924         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1925                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1926         ENABLED_SELECTED_STATE_SET = StateSet.get(
1927                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1928         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1929                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1930                         | StateSet.VIEW_STATE_ENABLED);
1931         ENABLED_FOCUSED_STATE_SET = StateSet.get(
1932                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1933         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1934                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1935                         | StateSet.VIEW_STATE_ENABLED);
1936         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1937                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1938                         | StateSet.VIEW_STATE_ENABLED);
1939         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1940                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1941                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1942
1943         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1944         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1945                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1946         PRESSED_SELECTED_STATE_SET = StateSet.get(
1947                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1948         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1949                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1950                         | StateSet.VIEW_STATE_PRESSED);
1951         PRESSED_FOCUSED_STATE_SET = StateSet.get(
1952                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1953         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1954                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1955                         | StateSet.VIEW_STATE_PRESSED);
1956         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1957                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1958                         | StateSet.VIEW_STATE_PRESSED);
1959         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1960                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1961                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1962         PRESSED_ENABLED_STATE_SET = StateSet.get(
1963                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1964         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1965                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1966                         | StateSet.VIEW_STATE_PRESSED);
1967         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1968                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1969                         | StateSet.VIEW_STATE_PRESSED);
1970         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1971                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1972                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1973         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1974                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1975                         | StateSet.VIEW_STATE_PRESSED);
1976         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1977                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1978                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1979         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1980                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1981                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1982         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1983                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1984                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1985                         | StateSet.VIEW_STATE_PRESSED);
1986     }
1987
1988     /**
1989      * Accessibility event types that are dispatched for text population.
1990      */
1991     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1992             AccessibilityEvent.TYPE_VIEW_CLICKED
1993             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1994             | AccessibilityEvent.TYPE_VIEW_SELECTED
1995             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1996             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1997             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1998             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1999             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2000             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2001             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2002             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2003
2004     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2005
2006     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2007
2008     /**
2009      * Temporary Rect currently for use in setBackground().  This will probably
2010      * be extended in the future to hold our own class with more than just
2011      * a Rect. :)
2012      */
2013     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2014
2015     /**
2016      * Map used to store views' tags.
2017      */
2018     private SparseArray<Object> mKeyedTags;
2019
2020     /**
2021      * The animation currently associated with this view.
2022      * @hide
2023      */
2024     protected Animation mCurrentAnimation = null;
2025
2026     /**
2027      * Width as measured during measure pass.
2028      * {@hide}
2029      */
2030     @ViewDebug.ExportedProperty(category = "measurement")
2031     int mMeasuredWidth;
2032
2033     /**
2034      * Height as measured during measure pass.
2035      * {@hide}
2036      */
2037     @ViewDebug.ExportedProperty(category = "measurement")
2038     int mMeasuredHeight;
2039
2040     /**
2041      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2042      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2043      * its display list. This flag, used only when hw accelerated, allows us to clear the
2044      * flag while retaining this information until it's needed (at getDisplayList() time and
2045      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2046      *
2047      * {@hide}
2048      */
2049     boolean mRecreateDisplayList = false;
2050
2051     /**
2052      * The view's identifier.
2053      * {@hide}
2054      *
2055      * @see #setId(int)
2056      * @see #getId()
2057      */
2058     @IdRes
2059     @ViewDebug.ExportedProperty(resolveId = true)
2060     int mID = NO_ID;
2061
2062     /** The ID of this view for accessibility and autofill purposes.
2063      * <ul>
2064      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2065      *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
2066      *                                                  unique in the process. This might change
2067      *                                                  over activity lifecycle events.
2068      *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
2069      *                                                  unique in the activity. This stays the same
2070      *                                                  over activity lifecycle events.
2071      */
2072     private int mAccessibilityViewId = NO_ID;
2073
2074     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2075
2076     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2077
2078     /**
2079      * The view's tag.
2080      * {@hide}
2081      *
2082      * @see #setTag(Object)
2083      * @see #getTag()
2084      */
2085     protected Object mTag = null;
2086
2087     // for mPrivateFlags:
2088     /** {@hide} */
2089     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2090     /** {@hide} */
2091     static final int PFLAG_FOCUSED                     = 0x00000002;
2092     /** {@hide} */
2093     static final int PFLAG_SELECTED                    = 0x00000004;
2094     /** {@hide} */
2095     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2096     /** {@hide} */
2097     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2098     /** {@hide} */
2099     static final int PFLAG_DRAWN                       = 0x00000020;
2100     /**
2101      * When this flag is set, this view is running an animation on behalf of its
2102      * children and should therefore not cancel invalidate requests, even if they
2103      * lie outside of this view's bounds.
2104      *
2105      * {@hide}
2106      */
2107     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2108     /** {@hide} */
2109     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2110     /** {@hide} */
2111     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2112     /** {@hide} */
2113     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2114     /** {@hide} */
2115     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2116     /** {@hide} */
2117     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2118     /** {@hide} */
2119     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2120
2121     private static final int PFLAG_PRESSED             = 0x00004000;
2122
2123     /** {@hide} */
2124     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2125     /**
2126      * Flag used to indicate that this view should be drawn once more (and only once
2127      * more) after its animation has completed.
2128      * {@hide}
2129      */
2130     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2131
2132     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2133
2134     /**
2135      * Indicates that the View returned true when onSetAlpha() was called and that
2136      * the alpha must be restored.
2137      * {@hide}
2138      */
2139     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2140
2141     /**
2142      * Set by {@link #setScrollContainer(boolean)}.
2143      */
2144     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2145
2146     /**
2147      * Set by {@link #setScrollContainer(boolean)}.
2148      */
2149     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2150
2151     /**
2152      * View flag indicating whether this view was invalidated (fully or partially.)
2153      *
2154      * @hide
2155      */
2156     static final int PFLAG_DIRTY                       = 0x00200000;
2157
2158     /**
2159      * View flag indicating whether this view was invalidated by an opaque
2160      * invalidate request.
2161      *
2162      * @hide
2163      */
2164     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2165
2166     /**
2167      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2168      *
2169      * @hide
2170      */
2171     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2172
2173     /**
2174      * Indicates whether the background is opaque.
2175      *
2176      * @hide
2177      */
2178     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2179
2180     /**
2181      * Indicates whether the scrollbars are opaque.
2182      *
2183      * @hide
2184      */
2185     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2186
2187     /**
2188      * Indicates whether the view is opaque.
2189      *
2190      * @hide
2191      */
2192     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2193
2194     /**
2195      * Indicates a prepressed state;
2196      * the short time between ACTION_DOWN and recognizing
2197      * a 'real' press. Prepressed is used to recognize quick taps
2198      * even when they are shorter than ViewConfiguration.getTapTimeout().
2199      *
2200      * @hide
2201      */
2202     private static final int PFLAG_PREPRESSED          = 0x02000000;
2203
2204     /**
2205      * Indicates whether the view is temporarily detached.
2206      *
2207      * @hide
2208      */
2209     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2210
2211     /**
2212      * Indicates that we should awaken scroll bars once attached
2213      *
2214      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2215      * during window attachment and it is no longer needed. Feel free to repurpose it.
2216      *
2217      * @hide
2218      */
2219     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2220
2221     /**
2222      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2223      * @hide
2224      */
2225     private static final int PFLAG_HOVERED             = 0x10000000;
2226
2227     /**
2228      * no longer needed, should be reused
2229      */
2230     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2231
2232     /** {@hide} */
2233     static final int PFLAG_ACTIVATED                   = 0x40000000;
2234
2235     /**
2236      * Indicates that this view was specifically invalidated, not just dirtied because some
2237      * child view was invalidated. The flag is used to determine when we need to recreate
2238      * a view's display list (as opposed to just returning a reference to its existing
2239      * display list).
2240      *
2241      * @hide
2242      */
2243     static final int PFLAG_INVALIDATED                 = 0x80000000;
2244
2245     /**
2246      * Masks for mPrivateFlags2, as generated by dumpFlags():
2247      *
2248      * |-------|-------|-------|-------|
2249      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2250      *                                1  PFLAG2_DRAG_HOVERED
2251      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2252      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2253      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2254      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2255      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2256      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2257      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2258      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2259      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2260      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2261      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2262      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2263      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2264      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2265      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2266      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2267      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2268      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2269      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2270      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2271      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2272      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2273      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2274      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2275      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2276      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2277      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2278      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2279      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2280      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2281      *    1                              PFLAG2_PADDING_RESOLVED
2282      *   1                               PFLAG2_DRAWABLE_RESOLVED
2283      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2284      * |-------|-------|-------|-------|
2285      */
2286
2287     /**
2288      * Indicates that this view has reported that it can accept the current drag's content.
2289      * Cleared when the drag operation concludes.
2290      * @hide
2291      */
2292     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2293
2294     /**
2295      * Indicates that this view is currently directly under the drag location in a
2296      * drag-and-drop operation involving content that it can accept.  Cleared when
2297      * the drag exits the view, or when the drag operation concludes.
2298      * @hide
2299      */
2300     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2301
2302     /** @hide */
2303     @IntDef({
2304         LAYOUT_DIRECTION_LTR,
2305         LAYOUT_DIRECTION_RTL,
2306         LAYOUT_DIRECTION_INHERIT,
2307         LAYOUT_DIRECTION_LOCALE
2308     })
2309     @Retention(RetentionPolicy.SOURCE)
2310     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2311     public @interface LayoutDir {}
2312
2313     /** @hide */
2314     @IntDef({
2315         LAYOUT_DIRECTION_LTR,
2316         LAYOUT_DIRECTION_RTL
2317     })
2318     @Retention(RetentionPolicy.SOURCE)
2319     public @interface ResolvedLayoutDir {}
2320
2321     /**
2322      * A flag to indicate that the layout direction of this view has not been defined yet.
2323      * @hide
2324      */
2325     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2326
2327     /**
2328      * Horizontal layout direction of this view is from Left to Right.
2329      * Use with {@link #setLayoutDirection}.
2330      */
2331     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2332
2333     /**
2334      * Horizontal layout direction of this view is from Right to Left.
2335      * Use with {@link #setLayoutDirection}.
2336      */
2337     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2338
2339     /**
2340      * Horizontal layout direction of this view is inherited from its parent.
2341      * Use with {@link #setLayoutDirection}.
2342      */
2343     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2344
2345     /**
2346      * Horizontal layout direction of this view is from deduced from the default language
2347      * script for the locale. Use with {@link #setLayoutDirection}.
2348      */
2349     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2350
2351     /**
2352      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2353      * @hide
2354      */
2355     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2356
2357     /**
2358      * Mask for use with private flags indicating bits used for horizontal layout direction.
2359      * @hide
2360      */
2361     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2362
2363     /**
2364      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2365      * right-to-left direction.
2366      * @hide
2367      */
2368     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2369
2370     /**
2371      * Indicates whether the view horizontal layout direction has been resolved.
2372      * @hide
2373      */
2374     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2375
2376     /**
2377      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2378      * @hide
2379      */
2380     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2381             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2382
2383     /*
2384      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2385      * flag value.
2386      * @hide
2387      */
2388     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2389             LAYOUT_DIRECTION_LTR,
2390             LAYOUT_DIRECTION_RTL,
2391             LAYOUT_DIRECTION_INHERIT,
2392             LAYOUT_DIRECTION_LOCALE
2393     };
2394
2395     /**
2396      * Default horizontal layout direction.
2397      */
2398     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2399
2400     /**
2401      * Default horizontal layout direction.
2402      * @hide
2403      */
2404     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2405
2406     /**
2407      * Text direction is inherited through {@link ViewGroup}
2408      */
2409     public static final int TEXT_DIRECTION_INHERIT = 0;
2410
2411     /**
2412      * Text direction is using "first strong algorithm". The first strong directional character
2413      * determines the paragraph direction. If there is no strong directional character, the
2414      * paragraph direction is the view's resolved layout direction.
2415      */
2416     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2417
2418     /**
2419      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2420      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2421      * If there are neither, the paragraph direction is the view's resolved layout direction.
2422      */
2423     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2424
2425     /**
2426      * Text direction is forced to LTR.
2427      */
2428     public static final int TEXT_DIRECTION_LTR = 3;
2429
2430     /**
2431      * Text direction is forced to RTL.
2432      */
2433     public static final int TEXT_DIRECTION_RTL = 4;
2434
2435     /**
2436      * Text direction is coming from the system Locale.
2437      */
2438     public static final int TEXT_DIRECTION_LOCALE = 5;
2439
2440     /**
2441      * Text direction is using "first strong algorithm". The first strong directional character
2442      * determines the paragraph direction. If there is no strong directional character, the
2443      * paragraph direction is LTR.
2444      */
2445     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2446
2447     /**
2448      * Text direction is using "first strong algorithm". The first strong directional character
2449      * determines the paragraph direction. If there is no strong directional character, the
2450      * paragraph direction is RTL.
2451      */
2452     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2453
2454     /**
2455      * Default text direction is inherited
2456      */
2457     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2458
2459     /**
2460      * Default resolved text direction
2461      * @hide
2462      */
2463     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2464
2465     /**
2466      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2467      * @hide
2468      */
2469     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2470
2471     /**
2472      * Mask for use with private flags indicating bits used for text direction.
2473      * @hide
2474      */
2475     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2476             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2477
2478     /**
2479      * Array of text direction flags for mapping attribute "textDirection" to correct
2480      * flag value.
2481      * @hide
2482      */
2483     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2484             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2485             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2486             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2487             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2488             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2489             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2490             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2491             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2492     };
2493
2494     /**
2495      * Indicates whether the view text direction has been resolved.
2496      * @hide
2497      */
2498     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2499             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2500
2501     /**
2502      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2503      * @hide
2504      */
2505     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2506
2507     /**
2508      * Mask for use with private flags indicating bits used for resolved text direction.
2509      * @hide
2510      */
2511     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2512             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2513
2514     /**
2515      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2516      * @hide
2517      */
2518     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2519             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2520
2521     /** @hide */
2522     @IntDef({
2523         TEXT_ALIGNMENT_INHERIT,
2524         TEXT_ALIGNMENT_GRAVITY,
2525         TEXT_ALIGNMENT_CENTER,
2526         TEXT_ALIGNMENT_TEXT_START,
2527         TEXT_ALIGNMENT_TEXT_END,
2528         TEXT_ALIGNMENT_VIEW_START,
2529         TEXT_ALIGNMENT_VIEW_END
2530     })
2531     @Retention(RetentionPolicy.SOURCE)
2532     public @interface TextAlignment {}
2533
2534     /**
2535      * Default text alignment. The text alignment of this View is inherited from its parent.
2536      * Use with {@link #setTextAlignment(int)}
2537      */
2538     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2539
2540     /**
2541      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2542      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2543      *
2544      * Use with {@link #setTextAlignment(int)}
2545      */
2546     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2547
2548     /**
2549      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2550      *
2551      * Use with {@link #setTextAlignment(int)}
2552      */
2553     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2554
2555     /**
2556      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2557      *
2558      * Use with {@link #setTextAlignment(int)}
2559      */
2560     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2561
2562     /**
2563      * Center the paragraph, e.g. ALIGN_CENTER.
2564      *
2565      * Use with {@link #setTextAlignment(int)}
2566      */
2567     public static final int TEXT_ALIGNMENT_CENTER = 4;
2568
2569     /**
2570      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2571      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2572      *
2573      * Use with {@link #setTextAlignment(int)}
2574      */
2575     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2576
2577     /**
2578      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2579      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2580      *
2581      * Use with {@link #setTextAlignment(int)}
2582      */
2583     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2584
2585     /**
2586      * Default text alignment is inherited
2587      */
2588     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2589
2590     /**
2591      * Default resolved text alignment
2592      * @hide
2593      */
2594     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2595
2596     /**
2597       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2598       * @hide
2599       */
2600     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2601
2602     /**
2603       * Mask for use with private flags indicating bits used for text alignment.
2604       * @hide
2605       */
2606     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2607
2608     /**
2609      * Array of text direction flags for mapping attribute "textAlignment" to correct
2610      * flag value.
2611      * @hide
2612      */
2613     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2614             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2615             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2616             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2617             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2618             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2619             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2620             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2621     };
2622
2623     /**
2624      * Indicates whether the view text alignment has been resolved.
2625      * @hide
2626      */
2627     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2628
2629     /**
2630      * Bit shift to get the resolved text alignment.
2631      * @hide
2632      */
2633     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2634
2635     /**
2636      * Mask for use with private flags indicating bits used for text alignment.
2637      * @hide
2638      */
2639     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2640             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2641
2642     /**
2643      * Indicates whether if the view text alignment has been resolved to gravity
2644      */
2645     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2646             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2647
2648     // Accessiblity constants for mPrivateFlags2
2649
2650     /**
2651      * Shift for the bits in {@link #mPrivateFlags2} related to the
2652      * "importantForAccessibility" attribute.
2653      */
2654     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2655
2656     /**
2657      * Automatically determine whether a view is important for accessibility.
2658      */
2659     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2660
2661     /**
2662      * The view is important for accessibility.
2663      */
2664     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2665
2666     /**
2667      * The view is not important for accessibility.
2668      */
2669     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2670
2671     /**
2672      * The view is not important for accessibility, nor are any of its
2673      * descendant views.
2674      */
2675     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2676
2677     /**
2678      * The default whether the view is important for accessibility.
2679      */
2680     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2681
2682     /**
2683      * Mask for obtaining the bits which specify how to determine
2684      * whether a view is important for accessibility.
2685      */
2686     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2687         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2688         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2689         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2690
2691     /**
2692      * Shift for the bits in {@link #mPrivateFlags2} related to the
2693      * "accessibilityLiveRegion" attribute.
2694      */
2695     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2696
2697     /**
2698      * Live region mode specifying that accessibility services should not
2699      * automatically announce changes to this view. This is the default live
2700      * region mode for most views.
2701      * <p>
2702      * Use with {@link #setAccessibilityLiveRegion(int)}.
2703      */
2704     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2705
2706     /**
2707      * Live region mode specifying that accessibility services should announce
2708      * changes to this view.
2709      * <p>
2710      * Use with {@link #setAccessibilityLiveRegion(int)}.
2711      */
2712     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2713
2714     /**
2715      * Live region mode specifying that accessibility services should interrupt
2716      * ongoing speech to immediately announce changes to this view.
2717      * <p>
2718      * Use with {@link #setAccessibilityLiveRegion(int)}.
2719      */
2720     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2721
2722     /**
2723      * The default whether the view is important for accessibility.
2724      */
2725     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2726
2727     /**
2728      * Mask for obtaining the bits which specify a view's accessibility live
2729      * region mode.
2730      */
2731     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2732             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2733             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2734
2735     /**
2736      * Flag indicating whether a view has accessibility focus.
2737      */
2738     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2739
2740     /**
2741      * Flag whether the accessibility state of the subtree rooted at this view changed.
2742      */
2743     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2744
2745     /**
2746      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2747      * is used to check whether later changes to the view's transform should invalidate the
2748      * view to force the quickReject test to run again.
2749      */
2750     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2751
2752     /**
2753      * Flag indicating that start/end padding has been resolved into left/right padding
2754      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2755      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2756      * during measurement. In some special cases this is required such as when an adapter-based
2757      * view measures prospective children without attaching them to a window.
2758      */
2759     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2760
2761     /**
2762      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2763      */
2764     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2765
2766     /**
2767      * Indicates that the view is tracking some sort of transient state
2768      * that the app should not need to be aware of, but that the framework
2769      * should take special care to preserve.
2770      */
2771     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2772
2773     /**
2774      * Group of bits indicating that RTL properties resolution is done.
2775      */
2776     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2777             PFLAG2_TEXT_DIRECTION_RESOLVED |
2778             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2779             PFLAG2_PADDING_RESOLVED |
2780             PFLAG2_DRAWABLE_RESOLVED;
2781
2782     // There are a couple of flags left in mPrivateFlags2
2783
2784     /* End of masks for mPrivateFlags2 */
2785
2786     /**
2787      * Masks for mPrivateFlags3, as generated by dumpFlags():
2788      *
2789      * |-------|-------|-------|-------|
2790      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2791      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2792      *                               1   PFLAG3_IS_LAID_OUT
2793      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2794      *                             1     PFLAG3_CALLED_SUPER
2795      *                            1      PFLAG3_APPLYING_INSETS
2796      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2797      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2798      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2799      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2800      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2801      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2802      *                     1             PFLAG3_SCROLL_INDICATOR_START
2803      *                    1              PFLAG3_SCROLL_INDICATOR_END
2804      *                   1               PFLAG3_ASSIST_BLOCKED
2805      *                  1                PFLAG3_CLUSTER
2806      *                 1                 PFLAG3_IS_AUTOFILLED
2807      *                1                  PFLAG3_FINGER_DOWN
2808      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2809      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2810      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2811      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2812      *        1                          PFLAG3_TEMPORARY_DETACH
2813      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2814      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
2815      * |-------|-------|-------|-------|
2816      */
2817
2818     /**
2819      * Flag indicating that view has a transform animation set on it. This is used to track whether
2820      * an animation is cleared between successive frames, in order to tell the associated
2821      * DisplayList to clear its animation matrix.
2822      */
2823     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2824
2825     /**
2826      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2827      * animation is cleared between successive frames, in order to tell the associated
2828      * DisplayList to restore its alpha value.
2829      */
2830     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2831
2832     /**
2833      * Flag indicating that the view has been through at least one layout since it
2834      * was last attached to a window.
2835      */
2836     static final int PFLAG3_IS_LAID_OUT = 0x4;
2837
2838     /**
2839      * Flag indicating that a call to measure() was skipped and should be done
2840      * instead when layout() is invoked.
2841      */
2842     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2843
2844     /**
2845      * Flag indicating that an overridden method correctly called down to
2846      * the superclass implementation as required by the API spec.
2847      */
2848     static final int PFLAG3_CALLED_SUPER = 0x10;
2849
2850     /**
2851      * Flag indicating that we're in the process of applying window insets.
2852      */
2853     static final int PFLAG3_APPLYING_INSETS = 0x20;
2854
2855     /**
2856      * Flag indicating that we're in the process of fitting system windows using the old method.
2857      */
2858     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2859
2860     /**
2861      * Flag indicating that nested scrolling is enabled for this view.
2862      * The view will optionally cooperate with views up its parent chain to allow for
2863      * integrated nested scrolling along the same axis.
2864      */
2865     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2866
2867     /**
2868      * Flag indicating that the bottom scroll indicator should be displayed
2869      * when this view can scroll up.
2870      */
2871     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2872
2873     /**
2874      * Flag indicating that the bottom scroll indicator should be displayed
2875      * when this view can scroll down.
2876      */
2877     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2878
2879     /**
2880      * Flag indicating that the left scroll indicator should be displayed
2881      * when this view can scroll left.
2882      */
2883     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2884
2885     /**
2886      * Flag indicating that the right scroll indicator should be displayed
2887      * when this view can scroll right.
2888      */
2889     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2890
2891     /**
2892      * Flag indicating that the start scroll indicator should be displayed
2893      * when this view can scroll in the start direction.
2894      */
2895     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2896
2897     /**
2898      * Flag indicating that the end scroll indicator should be displayed
2899      * when this view can scroll in the end direction.
2900      */
2901     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2902
2903     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2904
2905     static final int SCROLL_INDICATORS_NONE = 0x0000;
2906
2907     /**
2908      * Mask for use with setFlags indicating bits used for indicating which
2909      * scroll indicators are enabled.
2910      */
2911     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2912             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2913             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2914             | PFLAG3_SCROLL_INDICATOR_END;
2915
2916     /**
2917      * Left-shift required to translate between public scroll indicator flags
2918      * and internal PFLAGS3 flags. When used as a right-shift, translates
2919      * PFLAGS3 flags to public flags.
2920      */
2921     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2922
2923     /** @hide */
2924     @Retention(RetentionPolicy.SOURCE)
2925     @IntDef(flag = true,
2926             value = {
2927                     SCROLL_INDICATOR_TOP,
2928                     SCROLL_INDICATOR_BOTTOM,
2929                     SCROLL_INDICATOR_LEFT,
2930                     SCROLL_INDICATOR_RIGHT,
2931                     SCROLL_INDICATOR_START,
2932                     SCROLL_INDICATOR_END,
2933             })
2934     public @interface ScrollIndicators {}
2935
2936     /**
2937      * Scroll indicator direction for the top edge of the view.
2938      *
2939      * @see #setScrollIndicators(int)
2940      * @see #setScrollIndicators(int, int)
2941      * @see #getScrollIndicators()
2942      */
2943     public static final int SCROLL_INDICATOR_TOP =
2944             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2945
2946     /**
2947      * Scroll indicator direction for the bottom edge of the view.
2948      *
2949      * @see #setScrollIndicators(int)
2950      * @see #setScrollIndicators(int, int)
2951      * @see #getScrollIndicators()
2952      */
2953     public static final int SCROLL_INDICATOR_BOTTOM =
2954             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2955
2956     /**
2957      * Scroll indicator direction for the left edge of the view.
2958      *
2959      * @see #setScrollIndicators(int)
2960      * @see #setScrollIndicators(int, int)
2961      * @see #getScrollIndicators()
2962      */
2963     public static final int SCROLL_INDICATOR_LEFT =
2964             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2965
2966     /**
2967      * Scroll indicator direction for the right edge of the view.
2968      *
2969      * @see #setScrollIndicators(int)
2970      * @see #setScrollIndicators(int, int)
2971      * @see #getScrollIndicators()
2972      */
2973     public static final int SCROLL_INDICATOR_RIGHT =
2974             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2975
2976     /**
2977      * Scroll indicator direction for the starting edge of the view.
2978      * <p>
2979      * Resolved according to the view's layout direction, see
2980      * {@link #getLayoutDirection()} for more information.
2981      *
2982      * @see #setScrollIndicators(int)
2983      * @see #setScrollIndicators(int, int)
2984      * @see #getScrollIndicators()
2985      */
2986     public static final int SCROLL_INDICATOR_START =
2987             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2988
2989     /**
2990      * Scroll indicator direction for the ending edge of the view.
2991      * <p>
2992      * Resolved according to the view's layout direction, see
2993      * {@link #getLayoutDirection()} for more information.
2994      *
2995      * @see #setScrollIndicators(int)
2996      * @see #setScrollIndicators(int, int)
2997      * @see #getScrollIndicators()
2998      */
2999     public static final int SCROLL_INDICATOR_END =
3000             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3001
3002     /**
3003      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3004      * into this view.<p>
3005      */
3006     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3007
3008     /**
3009      * Flag indicating that the view is a root of a keyboard navigation cluster.
3010      *
3011      * @see #isKeyboardNavigationCluster()
3012      * @see #setKeyboardNavigationCluster(boolean)
3013      */
3014     private static final int PFLAG3_CLUSTER = 0x8000;
3015
3016     /**
3017      * Flag indicating that the view is autofilled
3018      *
3019      * @see #isAutofilled()
3020      * @see #setAutofilled(boolean)
3021      */
3022     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3023
3024     /**
3025      * Indicates that the user is currently touching the screen.
3026      * Currently used for the tooltip positioning only.
3027      */
3028     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3029
3030     /**
3031      * Flag indicating that this view is the default-focus view.
3032      *
3033      * @see #isFocusedByDefault()
3034      * @see #setFocusedByDefault(boolean)
3035      */
3036     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3037
3038     /**
3039      * Shift for the bits in {@link #mPrivateFlags3} related to the
3040      * "importantForAutofill" attribute.
3041      */
3042     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3043
3044     /**
3045      * Mask for obtaining the bits which specify how to determine
3046      * whether a view is important for autofill.
3047      */
3048     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3049             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3050             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3051             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3052             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3053
3054     /**
3055      * Whether this view has rendered elements that overlap (see {@link
3056      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3057      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3058      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3059      * determined by whatever {@link #hasOverlappingRendering()} returns.
3060      */
3061     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3062
3063     /**
3064      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3065      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3066      */
3067     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3068
3069     /**
3070      * Flag indicating that the view is temporarily detached from the parent view.
3071      *
3072      * @see #onStartTemporaryDetach()
3073      * @see #onFinishTemporaryDetach()
3074      */
3075     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3076
3077     /**
3078      * Flag indicating that the view does not wish to be revealed within its parent
3079      * hierarchy when it gains focus. Expressed in the negative since the historical
3080      * default behavior is to reveal on focus; this flag suppresses that behavior.
3081      *
3082      * @see #setRevealOnFocusHint(boolean)
3083      * @see #getRevealOnFocusHint()
3084      */
3085     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3086
3087     /**
3088      * Flag indicating that when layout is completed we should notify
3089      * that the view was entered for autofill purposes. To minimize
3090      * showing autofill for views not visible to the user we evaluate
3091      * user visibility which cannot be done until the view is laid out.
3092      */
3093     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3094
3095     /* End of masks for mPrivateFlags3 */
3096
3097     /**
3098      * Always allow a user to over-scroll this view, provided it is a
3099      * view that can scroll.
3100      *
3101      * @see #getOverScrollMode()
3102      * @see #setOverScrollMode(int)
3103      */
3104     public static final int OVER_SCROLL_ALWAYS = 0;
3105
3106     /**
3107      * Allow a user to over-scroll this view only if the content is large
3108      * enough to meaningfully scroll, provided it is a view that can scroll.
3109      *
3110      * @see #getOverScrollMode()
3111      * @see #setOverScrollMode(int)
3112      */
3113     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3114
3115     /**
3116      * Never allow a user to over-scroll this view.
3117      *
3118      * @see #getOverScrollMode()
3119      * @see #setOverScrollMode(int)
3120      */
3121     public static final int OVER_SCROLL_NEVER = 2;
3122
3123     /**
3124      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3125      * requested the system UI (status bar) to be visible (the default).
3126      *
3127      * @see #setSystemUiVisibility(int)
3128      */
3129     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3130
3131     /**
3132      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3133      * system UI to enter an unobtrusive "low profile" mode.
3134      *
3135      * <p>This is for use in games, book readers, video players, or any other
3136      * "immersive" application where the usual system chrome is deemed too distracting.
3137      *
3138      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3139      *
3140      * @see #setSystemUiVisibility(int)
3141      */
3142     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3143
3144     /**
3145      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3146      * system navigation be temporarily hidden.
3147      *
3148      * <p>This is an even less obtrusive state than that called for by
3149      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3150      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3151      * those to disappear. This is useful (in conjunction with the
3152      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3153      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3154      * window flags) for displaying content using every last pixel on the display.
3155      *
3156      * <p>There is a limitation: because navigation controls are so important, the least user
3157      * interaction will cause them to reappear immediately.  When this happens, both
3158      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3159      * so that both elements reappear at the same time.
3160      *
3161      * @see #setSystemUiVisibility(int)
3162      */
3163     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3164
3165     /**
3166      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3167      * into the normal fullscreen mode so that its content can take over the screen
3168      * while still allowing the user to interact with the application.
3169      *
3170      * <p>This has the same visual effect as
3171      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3172      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3173      * meaning that non-critical screen decorations (such as the status bar) will be
3174      * hidden while the user is in the View's window, focusing the experience on
3175      * that content.  Unlike the window flag, if you are using ActionBar in
3176      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3177      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3178      * hide the action bar.
3179      *
3180      * <p>This approach to going fullscreen is best used over the window flag when
3181      * it is a transient state -- that is, the application does this at certain
3182      * points in its user interaction where it wants to allow the user to focus
3183      * on content, but not as a continuous state.  For situations where the application
3184      * would like to simply stay full screen the entire time (such as a game that
3185      * wants to take over the screen), the
3186      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3187      * is usually a better approach.  The state set here will be removed by the system
3188      * in various situations (such as the user moving to another application) like
3189      * the other system UI states.
3190      *
3191      * <p>When using this flag, the application should provide some easy facility
3192      * for the user to go out of it.  A common example would be in an e-book
3193      * reader, where tapping on the screen brings back whatever screen and UI
3194      * decorations that had been hidden while the user was immersed in reading
3195      * the book.
3196      *
3197      * @see #setSystemUiVisibility(int)
3198      */
3199     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3200
3201     /**
3202      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3203      * flags, we would like a stable view of the content insets given to
3204      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3205      * will always represent the worst case that the application can expect
3206      * as a continuous state.  In the stock Android UI this is the space for
3207      * the system bar, nav bar, and status bar, but not more transient elements
3208      * such as an input method.
3209      *
3210      * The stable layout your UI sees is based on the system UI modes you can
3211      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3212      * then you will get a stable layout for changes of the
3213      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3214      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3215      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3216      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3217      * with a stable layout.  (Note that you should avoid using
3218      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3219      *
3220      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3221      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3222      * then a hidden status bar will be considered a "stable" state for purposes
3223      * here.  This allows your UI to continually hide the status bar, while still
3224      * using the system UI flags to hide the action bar while still retaining
3225      * a stable layout.  Note that changing the window fullscreen flag will never
3226      * provide a stable layout for a clean transition.
3227      *
3228      * <p>If you are using ActionBar in
3229      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3230      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3231      * insets it adds to those given to the application.
3232      */
3233     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3234
3235     /**
3236      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3237      * to be laid out as if it has requested
3238      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3239      * allows it to avoid artifacts when switching in and out of that mode, at
3240      * the expense that some of its user interface may be covered by screen
3241      * decorations when they are shown.  You can perform layout of your inner
3242      * UI elements to account for the navigation system UI through the
3243      * {@link #fitSystemWindows(Rect)} method.
3244      */
3245     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3246
3247     /**
3248      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3249      * to be laid out as if it has requested
3250      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3251      * allows it to avoid artifacts when switching in and out of that mode, at
3252      * the expense that some of its user interface may be covered by screen
3253      * decorations when they are shown.  You can perform layout of your inner
3254      * UI elements to account for non-fullscreen system UI through the
3255      * {@link #fitSystemWindows(Rect)} method.
3256      */
3257     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3258
3259     /**
3260      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3261      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3262      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3263      * user interaction.
3264      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3265      * has an effect when used in combination with that flag.</p>
3266      */
3267     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3268
3269     /**
3270      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3271      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3272      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3273      * experience while also hiding the system bars.  If this flag is not set,
3274      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3275      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3276      * if the user swipes from the top of the screen.
3277      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3278      * system gestures, such as swiping from the top of the screen.  These transient system bars
3279      * will overlay app’s content, may have some degree of transparency, and will automatically
3280      * hide after a short timeout.
3281      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3282      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3283      * with one or both of those flags.</p>
3284      */
3285     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3286
3287     /**
3288      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3289      * is compatible with light status bar backgrounds.
3290      *
3291      * <p>For this to take effect, the window must request
3292      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3293      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3294      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3295      *         FLAG_TRANSLUCENT_STATUS}.
3296      *
3297      * @see android.R.attr#windowLightStatusBar
3298      */
3299     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3300
3301     /**
3302      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3303      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3304      */
3305     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3306
3307     /**
3308      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3309      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3310      */
3311     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3312
3313     /**
3314      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3315      * that is compatible with light navigation bar backgrounds.
3316      *
3317      * <p>For this to take effect, the window must request
3318      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3319      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3320      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3321      *         FLAG_TRANSLUCENT_NAVIGATION}.
3322      */
3323     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3324
3325     /**
3326      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3327      */
3328     @Deprecated
3329     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3330
3331     /**
3332      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3333      */
3334     @Deprecated
3335     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3336
3337     /**
3338      * @hide
3339      *
3340      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3341      * out of the public fields to keep the undefined bits out of the developer's way.
3342      *
3343      * Flag to make the status bar not expandable.  Unless you also
3344      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3345      */
3346     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3347
3348     /**
3349      * @hide
3350      *
3351      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3352      * out of the public fields to keep the undefined bits out of the developer's way.
3353      *
3354      * Flag to hide notification icons and scrolling ticker text.
3355      */
3356     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3357
3358     /**
3359      * @hide
3360      *
3361      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3362      * out of the public fields to keep the undefined bits out of the developer's way.
3363      *
3364      * Flag to disable incoming notification alerts.  This will not block
3365      * icons, but it will block sound, vibrating and other visual or aural notifications.
3366      */
3367     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3368
3369     /**
3370      * @hide
3371      *
3372      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3373      * out of the public fields to keep the undefined bits out of the developer's way.
3374      *
3375      * Flag to hide only the scrolling ticker.  Note that
3376      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3377      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3378      */
3379     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3380
3381     /**
3382      * @hide
3383      *
3384      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3385      * out of the public fields to keep the undefined bits out of the developer's way.
3386      *
3387      * Flag to hide the center system info area.
3388      */
3389     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3390
3391     /**
3392      * @hide
3393      *
3394      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3395      * out of the public fields to keep the undefined bits out of the developer's way.
3396      *
3397      * Flag to hide only the home button.  Don't use this
3398      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3399      */
3400     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3401
3402     /**
3403      * @hide
3404      *
3405      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3406      * out of the public fields to keep the undefined bits out of the developer's way.
3407      *
3408      * Flag to hide only the back button. Don't use this
3409      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3410      */
3411     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3412
3413     /**
3414      * @hide
3415      *
3416      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3417      * out of the public fields to keep the undefined bits out of the developer's way.
3418      *
3419      * Flag to hide only the clock.  You might use this if your activity has
3420      * its own clock making the status bar's clock redundant.
3421      */
3422     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3423
3424     /**
3425      * @hide
3426      *
3427      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3428      * out of the public fields to keep the undefined bits out of the developer's way.
3429      *
3430      * Flag to hide only the recent apps button. Don't use this
3431      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3432      */
3433     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3434
3435     /**
3436      * @hide
3437      *
3438      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3439      * out of the public fields to keep the undefined bits out of the developer's way.
3440      *
3441      * Flag to disable the global search gesture. Don't use this
3442      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3443      */
3444     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3445
3446     /**
3447      * @hide
3448      *
3449      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3450      * out of the public fields to keep the undefined bits out of the developer's way.
3451      *
3452      * Flag to specify that the status bar is displayed in transient mode.
3453      */
3454     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
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 specify that the navigation bar is displayed in transient mode.
3463      */
3464     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
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 specify that the hidden status bar would like to be shown.
3473      */
3474     public static final int STATUS_BAR_UNHIDE = 0x10000000;
3475
3476     /**
3477      * @hide
3478      *
3479      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3480      * out of the public fields to keep the undefined bits out of the developer's way.
3481      *
3482      * Flag to specify that the hidden navigation bar would like to be shown.
3483      */
3484     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3485
3486     /**
3487      * @hide
3488      *
3489      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3490      * out of the public fields to keep the undefined bits out of the developer's way.
3491      *
3492      * Flag to specify that the status bar is displayed in translucent mode.
3493      */
3494     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3495
3496     /**
3497      * @hide
3498      *
3499      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3500      * out of the public fields to keep the undefined bits out of the developer's way.
3501      *
3502      * Flag to specify that the navigation bar is displayed in translucent mode.
3503      */
3504     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3505
3506     /**
3507      * @hide
3508      *
3509      * Makes navigation bar transparent (but not the status bar).
3510      */
3511     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3512
3513     /**
3514      * @hide
3515      *
3516      * Makes status bar transparent (but not the navigation bar).
3517      */
3518     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3519
3520     /**
3521      * @hide
3522      *
3523      * Makes both status bar and navigation bar transparent.
3524      */
3525     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3526             | STATUS_BAR_TRANSPARENT;
3527
3528     /**
3529      * @hide
3530      */
3531     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3532
3533     /**
3534      * These are the system UI flags that can be cleared by events outside
3535      * of an application.  Currently this is just the ability to tap on the
3536      * screen while hiding the navigation bar to have it return.
3537      * @hide
3538      */
3539     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3540             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3541             | SYSTEM_UI_FLAG_FULLSCREEN;
3542
3543     /**
3544      * Flags that can impact the layout in relation to system UI.
3545      */
3546     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3547             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3548             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3549
3550     /** @hide */
3551     @IntDef(flag = true,
3552             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3553     @Retention(RetentionPolicy.SOURCE)
3554     public @interface FindViewFlags {}
3555
3556     /**
3557      * Find views that render the specified text.
3558      *
3559      * @see #findViewsWithText(ArrayList, CharSequence, int)
3560      */
3561     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3562
3563     /**
3564      * Find find views that contain the specified content description.
3565      *
3566      * @see #findViewsWithText(ArrayList, CharSequence, int)
3567      */
3568     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3569
3570     /**
3571      * Find views that contain {@link AccessibilityNodeProvider}. Such
3572      * a View is a root of virtual view hierarchy and may contain the searched
3573      * text. If this flag is set Views with providers are automatically
3574      * added and it is a responsibility of the client to call the APIs of
3575      * the provider to determine whether the virtual tree rooted at this View
3576      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3577      * representing the virtual views with this text.
3578      *
3579      * @see #findViewsWithText(ArrayList, CharSequence, int)
3580      *
3581      * @hide
3582      */
3583     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3584
3585     /**
3586      * The undefined cursor position.
3587      *
3588      * @hide
3589      */
3590     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3591
3592     /**
3593      * Indicates that the screen has changed state and is now off.
3594      *
3595      * @see #onScreenStateChanged(int)
3596      */
3597     public static final int SCREEN_STATE_OFF = 0x0;
3598
3599     /**
3600      * Indicates that the screen has changed state and is now on.
3601      *
3602      * @see #onScreenStateChanged(int)
3603      */
3604     public static final int SCREEN_STATE_ON = 0x1;
3605
3606     /**
3607      * Indicates no axis of view scrolling.
3608      */
3609     public static final int SCROLL_AXIS_NONE = 0;
3610
3611     /**
3612      * Indicates scrolling along the horizontal axis.
3613      */
3614     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3615
3616     /**
3617      * Indicates scrolling along the vertical axis.
3618      */
3619     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3620
3621     /**
3622      * Controls the over-scroll mode for this view.
3623      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3624      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3625      * and {@link #OVER_SCROLL_NEVER}.
3626      */
3627     private int mOverScrollMode;
3628
3629     /**
3630      * The parent this view is attached to.
3631      * {@hide}
3632      *
3633      * @see #getParent()
3634      */
3635     protected ViewParent mParent;
3636
3637     /**
3638      * {@hide}
3639      */
3640     AttachInfo mAttachInfo;
3641
3642     /**
3643      * {@hide}
3644      */
3645     @ViewDebug.ExportedProperty(flagMapping = {
3646         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3647                 name = "FORCE_LAYOUT"),
3648         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3649                 name = "LAYOUT_REQUIRED"),
3650         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3651             name = "DRAWING_CACHE_INVALID", outputIf = false),
3652         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3653         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3654         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3655         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3656     }, formatToHexString = true)
3657
3658     /* @hide */
3659     public int mPrivateFlags;
3660     int mPrivateFlags2;
3661     int mPrivateFlags3;
3662
3663     /**
3664      * This view's request for the visibility of the status bar.
3665      * @hide
3666      */
3667     @ViewDebug.ExportedProperty(flagMapping = {
3668         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3669                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3670                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3671         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3672                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3673                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3674         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3675                                 equals = SYSTEM_UI_FLAG_VISIBLE,
3676                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3677     }, formatToHexString = true)
3678     int mSystemUiVisibility;
3679
3680     /**
3681      * Reference count for transient state.
3682      * @see #setHasTransientState(boolean)
3683      */
3684     int mTransientStateCount = 0;
3685
3686     /**
3687      * Count of how many windows this view has been attached to.
3688      */
3689     int mWindowAttachCount;
3690
3691     /**
3692      * The layout parameters associated with this view and used by the parent
3693      * {@link android.view.ViewGroup} to determine how this view should be
3694      * laid out.
3695      * {@hide}
3696      */
3697     protected ViewGroup.LayoutParams mLayoutParams;
3698
3699     /**
3700      * The view flags hold various views states.
3701      * {@hide}
3702      */
3703     @ViewDebug.ExportedProperty(formatToHexString = true)
3704     int mViewFlags;
3705
3706     static class TransformationInfo {
3707         /**
3708          * The transform matrix for the View. This transform is calculated internally
3709          * based on the translation, rotation, and scale properties.
3710          *
3711          * Do *not* use this variable directly; instead call getMatrix(), which will
3712          * load the value from the View's RenderNode.
3713          */
3714         private final Matrix mMatrix = new Matrix();
3715
3716         /**
3717          * The inverse transform matrix for the View. This transform is calculated
3718          * internally based on the translation, rotation, and scale properties.
3719          *
3720          * Do *not* use this variable directly; instead call getInverseMatrix(),
3721          * which will load the value from the View's RenderNode.
3722          */
3723         private Matrix mInverseMatrix;
3724
3725         /**
3726          * The opacity of the View. This is a value from 0 to 1, where 0 means
3727          * completely transparent and 1 means completely opaque.
3728          */
3729         @ViewDebug.ExportedProperty
3730         float mAlpha = 1f;
3731
3732         /**
3733          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3734          * property only used by transitions, which is composited with the other alpha
3735          * values to calculate the final visual alpha value.
3736          */
3737         float mTransitionAlpha = 1f;
3738     }
3739
3740     /** @hide */
3741     public TransformationInfo mTransformationInfo;
3742
3743     /**
3744      * Current clip bounds. to which all drawing of this view are constrained.
3745      */
3746     Rect mClipBounds = null;
3747
3748     private boolean mLastIsOpaque;
3749
3750     /**
3751      * The distance in pixels from the left edge of this view's parent
3752      * to the left edge of this view.
3753      * {@hide}
3754      */
3755     @ViewDebug.ExportedProperty(category = "layout")
3756     protected int mLeft;
3757     /**
3758      * The distance in pixels from the left edge of this view's parent
3759      * to the right edge of this view.
3760      * {@hide}
3761      */
3762     @ViewDebug.ExportedProperty(category = "layout")
3763     protected int mRight;
3764     /**
3765      * The distance in pixels from the top edge of this view's parent
3766      * to the top edge of this view.
3767      * {@hide}
3768      */
3769     @ViewDebug.ExportedProperty(category = "layout")
3770     protected int mTop;
3771     /**
3772      * The distance in pixels from the top edge of this view's parent
3773      * to the bottom edge of this view.
3774      * {@hide}
3775      */
3776     @ViewDebug.ExportedProperty(category = "layout")
3777     protected int mBottom;
3778
3779     /**
3780      * The offset, in pixels, by which the content of this view is scrolled
3781      * horizontally.
3782      * {@hide}
3783      */
3784     @ViewDebug.ExportedProperty(category = "scrolling")
3785     protected int mScrollX;
3786     /**
3787      * The offset, in pixels, by which the content of this view is scrolled
3788      * vertically.
3789      * {@hide}
3790      */
3791     @ViewDebug.ExportedProperty(category = "scrolling")
3792     protected int mScrollY;
3793
3794     /**
3795      * The left padding in pixels, that is the distance in pixels between the
3796      * left edge of this view and the left edge of its content.
3797      * {@hide}
3798      */
3799     @ViewDebug.ExportedProperty(category = "padding")
3800     protected int mPaddingLeft = 0;
3801     /**
3802      * The right padding in pixels, that is the distance in pixels between the
3803      * right edge of this view and the right edge of its content.
3804      * {@hide}
3805      */
3806     @ViewDebug.ExportedProperty(category = "padding")
3807     protected int mPaddingRight = 0;
3808     /**
3809      * The top padding in pixels, that is the distance in pixels between the
3810      * top edge of this view and the top edge of its content.
3811      * {@hide}
3812      */
3813     @ViewDebug.ExportedProperty(category = "padding")
3814     protected int mPaddingTop;
3815     /**
3816      * The bottom padding in pixels, that is the distance in pixels between the
3817      * bottom edge of this view and the bottom edge of its content.
3818      * {@hide}
3819      */
3820     @ViewDebug.ExportedProperty(category = "padding")
3821     protected int mPaddingBottom;
3822
3823     /**
3824      * The layout insets in pixels, that is the distance in pixels between the
3825      * visible edges of this view its bounds.
3826      */
3827     private Insets mLayoutInsets;
3828
3829     /**
3830      * Briefly describes the view and is primarily used for accessibility support.
3831      */
3832     private CharSequence mContentDescription;
3833
3834     /**
3835      * Specifies the id of a view for which this view serves as a label for
3836      * accessibility purposes.
3837      */
3838     private int mLabelForId = View.NO_ID;
3839
3840     /**
3841      * Predicate for matching labeled view id with its label for
3842      * accessibility purposes.
3843      */
3844     private MatchLabelForPredicate mMatchLabelForPredicate;
3845
3846     /**
3847      * Specifies a view before which this one is visited in accessibility traversal.
3848      */
3849     private int mAccessibilityTraversalBeforeId = NO_ID;
3850
3851     /**
3852      * Specifies a view after which this one is visited in accessibility traversal.
3853      */
3854     private int mAccessibilityTraversalAfterId = NO_ID;
3855
3856     /**
3857      * Predicate for matching a view by its id.
3858      */
3859     private MatchIdPredicate mMatchIdPredicate;
3860
3861     /**
3862      * Cache the paddingRight set by the user to append to the scrollbar's size.
3863      *
3864      * @hide
3865      */
3866     @ViewDebug.ExportedProperty(category = "padding")
3867     protected int mUserPaddingRight;
3868
3869     /**
3870      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3871      *
3872      * @hide
3873      */
3874     @ViewDebug.ExportedProperty(category = "padding")
3875     protected int mUserPaddingBottom;
3876
3877     /**
3878      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3879      *
3880      * @hide
3881      */
3882     @ViewDebug.ExportedProperty(category = "padding")
3883     protected int mUserPaddingLeft;
3884
3885     /**
3886      * Cache the paddingStart set by the user to append to the scrollbar's size.
3887      *
3888      */
3889     @ViewDebug.ExportedProperty(category = "padding")
3890     int mUserPaddingStart;
3891
3892     /**
3893      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3894      *
3895      */
3896     @ViewDebug.ExportedProperty(category = "padding")
3897     int mUserPaddingEnd;
3898
3899     /**
3900      * Cache initial left padding.
3901      *
3902      * @hide
3903      */
3904     int mUserPaddingLeftInitial;
3905
3906     /**
3907      * Cache initial right padding.
3908      *
3909      * @hide
3910      */
3911     int mUserPaddingRightInitial;
3912
3913     /**
3914      * Default undefined padding
3915      */
3916     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3917
3918     /**
3919      * Cache if a left padding has been defined
3920      */
3921     private boolean mLeftPaddingDefined = false;
3922
3923     /**
3924      * Cache if a right padding has been defined
3925      */
3926     private boolean mRightPaddingDefined = false;
3927
3928     /**
3929      * @hide
3930      */
3931     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3932     /**
3933      * @hide
3934      */
3935     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3936
3937     private LongSparseLongArray mMeasureCache;
3938
3939     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3940     private Drawable mBackground;
3941     private TintInfo mBackgroundTint;
3942
3943     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3944     private ForegroundInfo mForegroundInfo;
3945
3946     private Drawable mScrollIndicatorDrawable;
3947
3948     /**
3949      * RenderNode used for backgrounds.
3950      * <p>
3951      * When non-null and valid, this is expected to contain an up-to-date copy
3952      * of the background drawable. It is cleared on temporary detach, and reset
3953      * on cleanup.
3954      */
3955     private RenderNode mBackgroundRenderNode;
3956
3957     private int mBackgroundResource;
3958     private boolean mBackgroundSizeChanged;
3959
3960     /** The default focus highlight.
3961      * @see #mDefaultFocusHighlightEnabled
3962      * @see Drawable#hasFocusStateSpecified()
3963      */
3964     private Drawable mDefaultFocusHighlight;
3965     private Drawable mDefaultFocusHighlightCache;
3966     private boolean mDefaultFocusHighlightSizeChanged;
3967     /**
3968      * True if the default focus highlight is needed on the target device.
3969      */
3970     private static boolean sUseDefaultFocusHighlight;
3971
3972     private String mTransitionName;
3973
3974     static class TintInfo {
3975         ColorStateList mTintList;
3976         PorterDuff.Mode mTintMode;
3977         boolean mHasTintMode;
3978         boolean mHasTintList;
3979     }
3980
3981     private static class ForegroundInfo {
3982         private Drawable mDrawable;
3983         private TintInfo mTintInfo;
3984         private int mGravity = Gravity.FILL;
3985         private boolean mInsidePadding = true;
3986         private boolean mBoundsChanged = true;
3987         private final Rect mSelfBounds = new Rect();
3988         private final Rect mOverlayBounds = new Rect();
3989     }
3990
3991     static class ListenerInfo {
3992         /**
3993          * Listener used to dispatch focus change events.
3994          * This field should be made private, so it is hidden from the SDK.
3995          * {@hide}
3996          */
3997         protected OnFocusChangeListener mOnFocusChangeListener;
3998
3999         /**
4000          * Listeners for layout change events.
4001          */
4002         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4003
4004         protected OnScrollChangeListener mOnScrollChangeListener;
4005
4006         /**
4007          * Listeners for attach events.
4008          */
4009         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4010
4011         /**
4012          * Listener used to dispatch click events.
4013          * This field should be made private, so it is hidden from the SDK.
4014          * {@hide}
4015          */
4016         public OnClickListener mOnClickListener;
4017
4018         /**
4019          * Listener used to dispatch long click events.
4020          * This field should be made private, so it is hidden from the SDK.
4021          * {@hide}
4022          */
4023         protected OnLongClickListener mOnLongClickListener;
4024
4025         /**
4026          * Listener used to dispatch context click events. This field should be made private, so it
4027          * is hidden from the SDK.
4028          * {@hide}
4029          */
4030         protected OnContextClickListener mOnContextClickListener;
4031
4032         /**
4033          * Listener used to build the context menu.
4034          * This field should be made private, so it is hidden from the SDK.
4035          * {@hide}
4036          */
4037         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4038
4039         private OnKeyListener mOnKeyListener;
4040
4041         private OnTouchListener mOnTouchListener;
4042
4043         private OnHoverListener mOnHoverListener;
4044
4045         private OnGenericMotionListener mOnGenericMotionListener;
4046
4047         private OnDragListener mOnDragListener;
4048
4049         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4050
4051         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4052
4053         OnCapturedPointerListener mOnCapturedPointerListener;
4054     }
4055
4056     ListenerInfo mListenerInfo;
4057
4058     private static class TooltipInfo {
4059         /**
4060          * Text to be displayed in a tooltip popup.
4061          */
4062         @Nullable
4063         CharSequence mTooltipText;
4064
4065         /**
4066          * View-relative position of the tooltip anchor point.
4067          */
4068         int mAnchorX;
4069         int mAnchorY;
4070
4071         /**
4072          * The tooltip popup.
4073          */
4074         @Nullable
4075         TooltipPopup mTooltipPopup;
4076
4077         /**
4078          * Set to true if the tooltip was shown as a result of a long click.
4079          */
4080         boolean mTooltipFromLongClick;
4081
4082         /**
4083          * Keep these Runnables so that they can be used to reschedule.
4084          */
4085         Runnable mShowTooltipRunnable;
4086         Runnable mHideTooltipRunnable;
4087     }
4088
4089     TooltipInfo mTooltipInfo;
4090
4091     // Temporary values used to hold (x,y) coordinates when delegating from the
4092     // two-arg performLongClick() method to the legacy no-arg version.
4093     private float mLongClickX = Float.NaN;
4094     private float mLongClickY = Float.NaN;
4095
4096     /**
4097      * The application environment this view lives in.
4098      * This field should be made private, so it is hidden from the SDK.
4099      * {@hide}
4100      */
4101     @ViewDebug.ExportedProperty(deepExport = true)
4102     protected Context mContext;
4103
4104     private final Resources mResources;
4105
4106     private ScrollabilityCache mScrollCache;
4107
4108     private int[] mDrawableState = null;
4109
4110     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4111
4112     /**
4113      * Animator that automatically runs based on state changes.
4114      */
4115     private StateListAnimator mStateListAnimator;
4116
4117     /**
4118      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4119      * the user may specify which view to go to next.
4120      */
4121     private int mNextFocusLeftId = View.NO_ID;
4122
4123     /**
4124      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4125      * the user may specify which view to go to next.
4126      */
4127     private int mNextFocusRightId = View.NO_ID;
4128
4129     /**
4130      * When this view has focus and the next focus is {@link #FOCUS_UP},
4131      * the user may specify which view to go to next.
4132      */
4133     private int mNextFocusUpId = View.NO_ID;
4134
4135     /**
4136      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4137      * the user may specify which view to go to next.
4138      */
4139     private int mNextFocusDownId = View.NO_ID;
4140
4141     /**
4142      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4143      * the user may specify which view to go to next.
4144      */
4145     int mNextFocusForwardId = View.NO_ID;
4146
4147     /**
4148      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4149      *
4150      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4151      */
4152     int mNextClusterForwardId = View.NO_ID;
4153
4154     /**
4155      * Whether this View should use a default focus highlight when it gets focused but doesn't
4156      * have {@link android.R.attr#state_focused} defined in its background.
4157      */
4158     boolean mDefaultFocusHighlightEnabled = true;
4159
4160     private CheckForLongPress mPendingCheckForLongPress;
4161     private CheckForTap mPendingCheckForTap = null;
4162     private PerformClick mPerformClick;
4163     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4164
4165     private UnsetPressedState mUnsetPressedState;
4166
4167     /**
4168      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4169      * up event while a long press is invoked as soon as the long press duration is reached, so
4170      * a long press could be performed before the tap is checked, in which case the tap's action
4171      * should not be invoked.
4172      */
4173     private boolean mHasPerformedLongPress;
4174
4175     /**
4176      * Whether a context click button is currently pressed down. This is true when the stylus is
4177      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4178      * pressed. This is false once the button is released or if the stylus has been lifted.
4179      */
4180     private boolean mInContextButtonPress;
4181
4182     /**
4183      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4184      * true after a stylus button press has occured, when the next up event should not be recognized
4185      * as a tap.
4186      */
4187     private boolean mIgnoreNextUpEvent;
4188
4189     /**
4190      * The minimum height of the view. We'll try our best to have the height
4191      * of this view to at least this amount.
4192      */
4193     @ViewDebug.ExportedProperty(category = "measurement")
4194     private int mMinHeight;
4195
4196     /**
4197      * The minimum width of the view. We'll try our best to have the width
4198      * of this view to at least this amount.
4199      */
4200     @ViewDebug.ExportedProperty(category = "measurement")
4201     private int mMinWidth;
4202
4203     /**
4204      * The delegate to handle touch events that are physically in this view
4205      * but should be handled by another view.
4206      */
4207     private TouchDelegate mTouchDelegate = null;
4208
4209     /**
4210      * Solid color to use as a background when creating the drawing cache. Enables
4211      * the cache to use 16 bit bitmaps instead of 32 bit.
4212      */
4213     private int mDrawingCacheBackgroundColor = 0;
4214
4215     /**
4216      * Special tree observer used when mAttachInfo is null.
4217      */
4218     private ViewTreeObserver mFloatingTreeObserver;
4219
4220     /**
4221      * Cache the touch slop from the context that created the view.
4222      */
4223     private int mTouchSlop;
4224
4225     /**
4226      * Object that handles automatic animation of view properties.
4227      */
4228     private ViewPropertyAnimator mAnimator = null;
4229
4230     /**
4231      * List of registered FrameMetricsObservers.
4232      */
4233     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4234
4235     /**
4236      * Flag indicating that a drag can cross window boundaries.  When
4237      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4238      * with this flag set, all visible applications with targetSdkVersion >=
4239      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4240      * in the drag operation and receive the dragged content.
4241      *
4242      * <p>If this is the only flag set, then the drag recipient will only have access to text data
4243      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4244      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4245      */
4246     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4247
4248     /**
4249      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4250      * request read access to the content URI(s) contained in the {@link ClipData} object.
4251      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4252      */
4253     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4254
4255     /**
4256      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4257      * request write access to the content URI(s) contained in the {@link ClipData} object.
4258      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4259      */
4260     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4261
4262     /**
4263      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4264      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4265      * reboots until explicitly revoked with
4266      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4267      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4268      */
4269     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4270             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4271
4272     /**
4273      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4274      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4275      * match against the original granted URI.
4276      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4277      */
4278     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4279             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4280
4281     /**
4282      * Flag indicating that the drag shadow will be opaque.  When
4283      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4284      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4285      */
4286     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4287
4288     /**
4289      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4290      */
4291     private float mVerticalScrollFactor;
4292
4293     /**
4294      * Position of the vertical scroll bar.
4295      */
4296     private int mVerticalScrollbarPosition;
4297
4298     /**
4299      * Position the scroll bar at the default position as determined by the system.
4300      */
4301     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4302
4303     /**
4304      * Position the scroll bar along the left edge.
4305      */
4306     public static final int SCROLLBAR_POSITION_LEFT = 1;
4307
4308     /**
4309      * Position the scroll bar along the right edge.
4310      */
4311     public static final int SCROLLBAR_POSITION_RIGHT = 2;
4312
4313     /**
4314      * Indicates that the view does not have a layer.
4315      *
4316      * @see #getLayerType()
4317      * @see #setLayerType(int, android.graphics.Paint)
4318      * @see #LAYER_TYPE_SOFTWARE
4319      * @see #LAYER_TYPE_HARDWARE
4320      */
4321     public static final int LAYER_TYPE_NONE = 0;
4322
4323     /**
4324      * <p>Indicates that the view has a software layer. A software layer is backed
4325      * by a bitmap and causes the view to be rendered using Android's software
4326      * rendering pipeline, even if hardware acceleration is enabled.</p>
4327      *
4328      * <p>Software layers have various usages:</p>
4329      * <p>When the application is not using hardware acceleration, a software layer
4330      * is useful to apply a specific color filter and/or blending mode and/or
4331      * translucency to a view and all its children.</p>
4332      * <p>When the application is using hardware acceleration, a software layer
4333      * is useful to render drawing primitives not supported by the hardware
4334      * accelerated pipeline. It can also be used to cache a complex view tree
4335      * into a texture and reduce the complexity of drawing operations. For instance,
4336      * when animating a complex view tree with a translation, a software layer can
4337      * be used to render the view tree only once.</p>
4338      * <p>Software layers should be avoided when the affected view tree updates
4339      * often. Every update will require to re-render the software layer, which can
4340      * potentially be slow (particularly when hardware acceleration is turned on
4341      * since the layer will have to be uploaded into a hardware texture after every
4342      * update.)</p>
4343      *
4344      * @see #getLayerType()
4345      * @see #setLayerType(int, android.graphics.Paint)
4346      * @see #LAYER_TYPE_NONE
4347      * @see #LAYER_TYPE_HARDWARE
4348      */
4349     public static final int LAYER_TYPE_SOFTWARE = 1;
4350
4351     /**
4352      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4353      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4354      * OpenGL hardware) and causes the view to be rendered using Android's hardware
4355      * rendering pipeline, but only if hardware acceleration is turned on for the
4356      * view hierarchy. When hardware acceleration is turned off, hardware layers
4357      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4358      *
4359      * <p>A hardware layer is useful to apply a specific color filter and/or
4360      * blending mode and/or translucency to a view and all its children.</p>
4361      * <p>A hardware layer can be used to cache a complex view tree into a
4362      * texture and reduce the complexity of drawing operations. For instance,
4363      * when animating a complex view tree with a translation, a hardware layer can
4364      * be used to render the view tree only once.</p>
4365      * <p>A hardware layer can also be used to increase the rendering quality when
4366      * rotation transformations are applied on a view. It can also be used to
4367      * prevent potential clipping issues when applying 3D transforms on a view.</p>
4368      *
4369      * @see #getLayerType()
4370      * @see #setLayerType(int, android.graphics.Paint)
4371      * @see #LAYER_TYPE_NONE
4372      * @see #LAYER_TYPE_SOFTWARE
4373      */
4374     public static final int LAYER_TYPE_HARDWARE = 2;
4375
4376     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4377             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4378             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4379             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4380     })
4381     int mLayerType = LAYER_TYPE_NONE;
4382     Paint mLayerPaint;
4383
4384     /**
4385      * Set to true when drawing cache is enabled and cannot be created.
4386      *
4387      * @hide
4388      */
4389     public boolean mCachingFailed;
4390     private Bitmap mDrawingCache;
4391     private Bitmap mUnscaledDrawingCache;
4392
4393     /**
4394      * RenderNode holding View properties, potentially holding a DisplayList of View content.
4395      * <p>
4396      * When non-null and valid, this is expected to contain an up-to-date copy
4397      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4398      * cleanup.
4399      */
4400     final RenderNode mRenderNode;
4401
4402     /**
4403      * Set to true when the view is sending hover accessibility events because it
4404      * is the innermost hovered view.
4405      */
4406     private boolean mSendingHoverAccessibilityEvents;
4407
4408     /**
4409      * Delegate for injecting accessibility functionality.
4410      */
4411     AccessibilityDelegate mAccessibilityDelegate;
4412
4413     /**
4414      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4415      * and add/remove objects to/from the overlay directly through the Overlay methods.
4416      */
4417     ViewOverlay mOverlay;
4418
4419     /**
4420      * The currently active parent view for receiving delegated nested scrolling events.
4421      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4422      * by {@link #stopNestedScroll()} at the same point where we clear
4423      * requestDisallowInterceptTouchEvent.
4424      */
4425     private ViewParent mNestedScrollingParent;
4426
4427     /**
4428      * Consistency verifier for debugging purposes.
4429      * @hide
4430      */
4431     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4432             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4433                     new InputEventConsistencyVerifier(this, 0) : null;
4434
4435     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4436
4437     private int[] mTempNestedScrollConsumed;
4438
4439     /**
4440      * An overlay is going to draw this View instead of being drawn as part of this
4441      * View's parent. mGhostView is the View in the Overlay that must be invalidated
4442      * when this view is invalidated.
4443      */
4444     GhostView mGhostView;
4445
4446     /**
4447      * Holds pairs of adjacent attribute data: attribute name followed by its value.
4448      * @hide
4449      */
4450     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4451     public String[] mAttributes;
4452
4453     /**
4454      * Maps a Resource id to its name.
4455      */
4456     private static SparseArray<String> mAttributeMap;
4457
4458     /**
4459      * Queue of pending runnables. Used to postpone calls to post() until this
4460      * view is attached and has a handler.
4461      */
4462     private HandlerActionQueue mRunQueue;
4463
4464     /**
4465      * The pointer icon when the mouse hovers on this view. The default is null.
4466      */
4467     private PointerIcon mPointerIcon;
4468
4469     /**
4470      * @hide
4471      */
4472     String mStartActivityRequestWho;
4473
4474     @Nullable
4475     private RoundScrollbarRenderer mRoundScrollbarRenderer;
4476
4477     /** Used to delay visibility updates sent to the autofill manager */
4478     private Handler mVisibilityChangeForAutofillHandler;
4479
4480     /**
4481      * Simple constructor to use when creating a view from code.
4482      *
4483      * @param context The Context the view is running in, through which it can
4484      *        access the current theme, resources, etc.
4485      */
4486     public View(Context context) {
4487         mContext = context;
4488         mResources = context != null ? context.getResources() : null;
4489         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4490         // Set some flags defaults
4491         mPrivateFlags2 =
4492                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4493                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4494                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4495                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4496                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4497                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4498         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4499         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4500         mUserPaddingStart = UNDEFINED_PADDING;
4501         mUserPaddingEnd = UNDEFINED_PADDING;
4502         mRenderNode = RenderNode.create(getClass().getName(), this);
4503
4504         if (!sCompatibilityDone && context != null) {
4505             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4506
4507             // Older apps may need this compatibility hack for measurement.
4508             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4509
4510             // Older apps expect onMeasure() to always be called on a layout pass, regardless
4511             // of whether a layout was requested on that View.
4512             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4513
4514             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4515             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
4516
4517             // In M and newer, our widgets can pass a "hint" value in the size
4518             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4519             // know what the expected parent size is going to be, so e.g. list items can size
4520             // themselves at 1/3 the size of their container. It breaks older apps though,
4521             // specifically apps that use some popular open source libraries.
4522             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4523
4524             // Old versions of the platform would give different results from
4525             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4526             // modes, so we always need to run an additional EXACTLY pass.
4527             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4528
4529             // Prior to N, layout params could change without requiring a
4530             // subsequent call to setLayoutParams() and they would usually
4531             // work. Partial layout breaks this assumption.
4532             sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4533
4534             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4535             // On N+, we throw, but that breaks compatibility with apps that use these methods.
4536             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4537
4538             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4539             // in apps so we target check it to avoid breaking existing apps.
4540             sPreserveMarginParamsInLayoutParamConversion =
4541                     targetSdkVersion >= Build.VERSION_CODES.N;
4542
4543             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4544
4545             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4546
4547             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4548
4549             sUseDefaultFocusHighlight = context.getResources().getBoolean(
4550                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
4551
4552             sCompatibilityDone = true;
4553         }
4554     }
4555
4556     /**
4557      * Constructor that is called when inflating a view from XML. This is called
4558      * when a view is being constructed from an XML file, supplying attributes
4559      * that were specified in the XML file. This version uses a default style of
4560      * 0, so the only attribute values applied are those in the Context's Theme
4561      * and the given AttributeSet.
4562      *
4563      * <p>
4564      * The method onFinishInflate() will be called after all children have been
4565      * added.
4566      *
4567      * @param context The Context the view is running in, through which it can
4568      *        access the current theme, resources, etc.
4569      * @param attrs The attributes of the XML tag that is inflating the view.
4570      * @see #View(Context, AttributeSet, int)
4571      */
4572     public View(Context context, @Nullable AttributeSet attrs) {
4573         this(context, attrs, 0);
4574     }
4575
4576     /**
4577      * Perform inflation from XML and apply a class-specific base style from a
4578      * theme attribute. This constructor of View allows subclasses to use their
4579      * own base style when they are inflating. For example, a Button class's
4580      * constructor would call this version of the super class constructor and
4581      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4582      * allows the theme's button style to modify all of the base view attributes
4583      * (in particular its background) as well as the Button class's attributes.
4584      *
4585      * @param context The Context the view is running in, through which it can
4586      *        access the current theme, resources, etc.
4587      * @param attrs The attributes of the XML tag that is inflating the view.
4588      * @param defStyleAttr An attribute in the current theme that contains a
4589      *        reference to a style resource that supplies default values for
4590      *        the view. Can be 0 to not look for defaults.
4591      * @see #View(Context, AttributeSet)
4592      */
4593     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4594         this(context, attrs, defStyleAttr, 0);
4595     }
4596
4597     /**
4598      * Perform inflation from XML and apply a class-specific base style from a
4599      * theme attribute or style resource. This constructor of View allows
4600      * subclasses to use their own base style when they are inflating.
4601      * <p>
4602      * When determining the final value of a particular attribute, there are
4603      * four inputs that come into play:
4604      * <ol>
4605      * <li>Any attribute values in the given AttributeSet.
4606      * <li>The style resource specified in the AttributeSet (named "style").
4607      * <li>The default style specified by <var>defStyleAttr</var>.
4608      * <li>The default style specified by <var>defStyleRes</var>.
4609      * <li>The base values in this theme.
4610      * </ol>
4611      * <p>
4612      * Each of these inputs is considered in-order, with the first listed taking
4613      * precedence over the following ones. In other words, if in the
4614      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4615      * , then the button's text will <em>always</em> be black, regardless of
4616      * what is specified in any of the styles.
4617      *
4618      * @param context The Context the view is running in, through which it can
4619      *        access the current theme, resources, etc.
4620      * @param attrs The attributes of the XML tag that is inflating the view.
4621      * @param defStyleAttr An attribute in the current theme that contains a
4622      *        reference to a style resource that supplies default values for
4623      *        the view. Can be 0 to not look for defaults.
4624      * @param defStyleRes A resource identifier of a style resource that
4625      *        supplies default values for the view, used only if
4626      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4627      *        to not look for defaults.
4628      * @see #View(Context, AttributeSet, int)
4629      */
4630     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4631         this(context);
4632
4633         final TypedArray a = context.obtainStyledAttributes(
4634                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4635
4636         if (mDebugViewAttributes) {
4637             saveAttributeData(attrs, a);
4638         }
4639
4640         Drawable background = null;
4641
4642         int leftPadding = -1;
4643         int topPadding = -1;
4644         int rightPadding = -1;
4645         int bottomPadding = -1;
4646         int startPadding = UNDEFINED_PADDING;
4647         int endPadding = UNDEFINED_PADDING;
4648
4649         int padding = -1;
4650         int paddingHorizontal = -1;
4651         int paddingVertical = -1;
4652
4653         int viewFlagValues = 0;
4654         int viewFlagMasks = 0;
4655
4656         boolean setScrollContainer = false;
4657
4658         int x = 0;
4659         int y = 0;
4660
4661         float tx = 0;
4662         float ty = 0;
4663         float tz = 0;
4664         float elevation = 0;
4665         float rotation = 0;
4666         float rotationX = 0;
4667         float rotationY = 0;
4668         float sx = 1f;
4669         float sy = 1f;
4670         boolean transformSet = false;
4671
4672         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4673         int overScrollMode = mOverScrollMode;
4674         boolean initializeScrollbars = false;
4675         boolean initializeScrollIndicators = false;
4676
4677         boolean startPaddingDefined = false;
4678         boolean endPaddingDefined = false;
4679         boolean leftPaddingDefined = false;
4680         boolean rightPaddingDefined = false;
4681
4682         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4683
4684         // Set default values.
4685         viewFlagValues |= FOCUSABLE_AUTO;
4686         viewFlagMasks |= FOCUSABLE_AUTO;
4687
4688         final int N = a.getIndexCount();
4689         for (int i = 0; i < N; i++) {
4690             int attr = a.getIndex(i);
4691             switch (attr) {
4692                 case com.android.internal.R.styleable.View_background:
4693                     background = a.getDrawable(attr);
4694                     break;
4695                 case com.android.internal.R.styleable.View_padding:
4696                     padding = a.getDimensionPixelSize(attr, -1);
4697                     mUserPaddingLeftInitial = padding;
4698                     mUserPaddingRightInitial = padding;
4699                     leftPaddingDefined = true;
4700                     rightPaddingDefined = true;
4701                     break;
4702                 case com.android.internal.R.styleable.View_paddingHorizontal:
4703                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4704                     mUserPaddingLeftInitial = paddingHorizontal;
4705                     mUserPaddingRightInitial = paddingHorizontal;
4706                     leftPaddingDefined = true;
4707                     rightPaddingDefined = true;
4708                     break;
4709                 case com.android.internal.R.styleable.View_paddingVertical:
4710                     paddingVertical = a.getDimensionPixelSize(attr, -1);
4711                     break;
4712                  case com.android.internal.R.styleable.View_paddingLeft:
4713                     leftPadding = a.getDimensionPixelSize(attr, -1);
4714                     mUserPaddingLeftInitial = leftPadding;
4715                     leftPaddingDefined = true;
4716                     break;
4717                 case com.android.internal.R.styleable.View_paddingTop:
4718                     topPadding = a.getDimensionPixelSize(attr, -1);
4719                     break;
4720                 case com.android.internal.R.styleable.View_paddingRight:
4721                     rightPadding = a.getDimensionPixelSize(attr, -1);
4722                     mUserPaddingRightInitial = rightPadding;
4723                     rightPaddingDefined = true;
4724                     break;
4725                 case com.android.internal.R.styleable.View_paddingBottom:
4726                     bottomPadding = a.getDimensionPixelSize(attr, -1);
4727                     break;
4728                 case com.android.internal.R.styleable.View_paddingStart:
4729                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4730                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4731                     break;
4732                 case com.android.internal.R.styleable.View_paddingEnd:
4733                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4734                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4735                     break;
4736                 case com.android.internal.R.styleable.View_scrollX:
4737                     x = a.getDimensionPixelOffset(attr, 0);
4738                     break;
4739                 case com.android.internal.R.styleable.View_scrollY:
4740                     y = a.getDimensionPixelOffset(attr, 0);
4741                     break;
4742                 case com.android.internal.R.styleable.View_alpha:
4743                     setAlpha(a.getFloat(attr, 1f));
4744                     break;
4745                 case com.android.internal.R.styleable.View_transformPivotX:
4746                     setPivotX(a.getDimension(attr, 0));
4747                     break;
4748                 case com.android.internal.R.styleable.View_transformPivotY:
4749                     setPivotY(a.getDimension(attr, 0));
4750                     break;
4751                 case com.android.internal.R.styleable.View_translationX:
4752                     tx = a.getDimension(attr, 0);
4753                     transformSet = true;
4754                     break;
4755                 case com.android.internal.R.styleable.View_translationY:
4756                     ty = a.getDimension(attr, 0);
4757                     transformSet = true;
4758                     break;
4759                 case com.android.internal.R.styleable.View_translationZ:
4760                     tz = a.getDimension(attr, 0);
4761                     transformSet = true;
4762                     break;
4763                 case com.android.internal.R.styleable.View_elevation:
4764                     elevation = a.getDimension(attr, 0);
4765                     transformSet = true;
4766                     break;
4767                 case com.android.internal.R.styleable.View_rotation:
4768                     rotation = a.getFloat(attr, 0);
4769                     transformSet = true;
4770                     break;
4771                 case com.android.internal.R.styleable.View_rotationX:
4772                     rotationX = a.getFloat(attr, 0);
4773                     transformSet = true;
4774                     break;
4775                 case com.android.internal.R.styleable.View_rotationY:
4776                     rotationY = a.getFloat(attr, 0);
4777                     transformSet = true;
4778                     break;
4779                 case com.android.internal.R.styleable.View_scaleX:
4780                     sx = a.getFloat(attr, 1f);
4781                     transformSet = true;
4782                     break;
4783                 case com.android.internal.R.styleable.View_scaleY:
4784                     sy = a.getFloat(attr, 1f);
4785                     transformSet = true;
4786                     break;
4787                 case com.android.internal.R.styleable.View_id:
4788                     mID = a.getResourceId(attr, NO_ID);
4789                     break;
4790                 case com.android.internal.R.styleable.View_tag:
4791                     mTag = a.getText(attr);
4792                     break;
4793                 case com.android.internal.R.styleable.View_fitsSystemWindows:
4794                     if (a.getBoolean(attr, false)) {
4795                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
4796                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4797                     }
4798                     break;
4799                 case com.android.internal.R.styleable.View_focusable:
4800                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4801                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4802                         viewFlagMasks |= FOCUSABLE_MASK;
4803                     }
4804                     break;
4805                 case com.android.internal.R.styleable.View_focusableInTouchMode:
4806                     if (a.getBoolean(attr, false)) {
4807                         // unset auto focus since focusableInTouchMode implies explicit focusable
4808                         viewFlagValues &= ~FOCUSABLE_AUTO;
4809                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4810                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4811                     }
4812                     break;
4813                 case com.android.internal.R.styleable.View_clickable:
4814                     if (a.getBoolean(attr, false)) {
4815                         viewFlagValues |= CLICKABLE;
4816                         viewFlagMasks |= CLICKABLE;
4817                     }
4818                     break;
4819                 case com.android.internal.R.styleable.View_longClickable:
4820                     if (a.getBoolean(attr, false)) {
4821                         viewFlagValues |= LONG_CLICKABLE;
4822                         viewFlagMasks |= LONG_CLICKABLE;
4823                     }
4824                     break;
4825                 case com.android.internal.R.styleable.View_contextClickable:
4826                     if (a.getBoolean(attr, false)) {
4827                         viewFlagValues |= CONTEXT_CLICKABLE;
4828                         viewFlagMasks |= CONTEXT_CLICKABLE;
4829                     }
4830                     break;
4831                 case com.android.internal.R.styleable.View_saveEnabled:
4832                     if (!a.getBoolean(attr, true)) {
4833                         viewFlagValues |= SAVE_DISABLED;
4834                         viewFlagMasks |= SAVE_DISABLED_MASK;
4835                     }
4836                     break;
4837                 case com.android.internal.R.styleable.View_duplicateParentState:
4838                     if (a.getBoolean(attr, false)) {
4839                         viewFlagValues |= DUPLICATE_PARENT_STATE;
4840                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
4841                     }
4842                     break;
4843                 case com.android.internal.R.styleable.View_visibility:
4844                     final int visibility = a.getInt(attr, 0);
4845                     if (visibility != 0) {
4846                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
4847                         viewFlagMasks |= VISIBILITY_MASK;
4848                     }
4849                     break;
4850                 case com.android.internal.R.styleable.View_layoutDirection:
4851                     // Clear any layout direction flags (included resolved bits) already set
4852                     mPrivateFlags2 &=
4853                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4854                     // Set the layout direction flags depending on the value of the attribute
4855                     final int layoutDirection = a.getInt(attr, -1);
4856                     final int value = (layoutDirection != -1) ?
4857                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4858                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4859                     break;
4860                 case com.android.internal.R.styleable.View_drawingCacheQuality:
4861                     final int cacheQuality = a.getInt(attr, 0);
4862                     if (cacheQuality != 0) {
4863                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4864                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4865                     }
4866                     break;
4867                 case com.android.internal.R.styleable.View_contentDescription:
4868                     setContentDescription(a.getString(attr));
4869                     break;
4870                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4871                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4872                     break;
4873                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4874                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4875                     break;
4876                 case com.android.internal.R.styleable.View_labelFor:
4877                     setLabelFor(a.getResourceId(attr, NO_ID));
4878                     break;
4879                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4880                     if (!a.getBoolean(attr, true)) {
4881                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4882                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4883                     }
4884                     break;
4885                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4886                     if (!a.getBoolean(attr, true)) {
4887                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4888                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4889                     }
4890                     break;
4891                 case R.styleable.View_scrollbars:
4892                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4893                     if (scrollbars != SCROLLBARS_NONE) {
4894                         viewFlagValues |= scrollbars;
4895                         viewFlagMasks |= SCROLLBARS_MASK;
4896                         initializeScrollbars = true;
4897                     }
4898                     break;
4899                 //noinspection deprecation
4900                 case R.styleable.View_fadingEdge:
4901                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4902                         // Ignore the attribute starting with ICS
4903                         break;
4904                     }
4905                     // With builds < ICS, fall through and apply fading edges
4906                 case R.styleable.View_requiresFadingEdge:
4907                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4908                     if (fadingEdge != FADING_EDGE_NONE) {
4909                         viewFlagValues |= fadingEdge;
4910                         viewFlagMasks |= FADING_EDGE_MASK;
4911                         initializeFadingEdgeInternal(a);
4912                     }
4913                     break;
4914                 case R.styleable.View_scrollbarStyle:
4915                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4916                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4917                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4918                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4919                     }
4920                     break;
4921                 case R.styleable.View_isScrollContainer:
4922                     setScrollContainer = true;
4923                     if (a.getBoolean(attr, false)) {
4924                         setScrollContainer(true);
4925                     }
4926                     break;
4927                 case com.android.internal.R.styleable.View_keepScreenOn:
4928                     if (a.getBoolean(attr, false)) {
4929                         viewFlagValues |= KEEP_SCREEN_ON;
4930                         viewFlagMasks |= KEEP_SCREEN_ON;
4931                     }
4932                     break;
4933                 case R.styleable.View_filterTouchesWhenObscured:
4934                     if (a.getBoolean(attr, false)) {
4935                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4936                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4937                     }
4938                     break;
4939                 case R.styleable.View_nextFocusLeft:
4940                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4941                     break;
4942                 case R.styleable.View_nextFocusRight:
4943                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4944                     break;
4945                 case R.styleable.View_nextFocusUp:
4946                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4947                     break;
4948                 case R.styleable.View_nextFocusDown:
4949                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4950                     break;
4951                 case R.styleable.View_nextFocusForward:
4952                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4953                     break;
4954                 case R.styleable.View_nextClusterForward:
4955                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4956                     break;
4957                 case R.styleable.View_minWidth:
4958                     mMinWidth = a.getDimensionPixelSize(attr, 0);
4959                     break;
4960                 case R.styleable.View_minHeight:
4961                     mMinHeight = a.getDimensionPixelSize(attr, 0);
4962                     break;
4963                 case R.styleable.View_onClick:
4964                     if (context.isRestricted()) {
4965                         throw new IllegalStateException("The android:onClick attribute cannot "
4966                                 + "be used within a restricted context");
4967                     }
4968
4969                     final String handlerName = a.getString(attr);
4970                     if (handlerName != null) {
4971                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4972                     }
4973                     break;
4974                 case R.styleable.View_overScrollMode:
4975                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4976                     break;
4977                 case R.styleable.View_verticalScrollbarPosition:
4978                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4979                     break;
4980                 case R.styleable.View_layerType:
4981                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4982                     break;
4983                 case R.styleable.View_textDirection:
4984                     // Clear any text direction flag already set
4985                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4986                     // Set the text direction flags depending on the value of the attribute
4987                     final int textDirection = a.getInt(attr, -1);
4988                     if (textDirection != -1) {
4989                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4990                     }
4991                     break;
4992                 case R.styleable.View_textAlignment:
4993                     // Clear any text alignment flag already set
4994                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4995                     // Set the text alignment flag depending on the value of the attribute
4996                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4997                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4998                     break;
4999                 case R.styleable.View_importantForAccessibility:
5000                     setImportantForAccessibility(a.getInt(attr,
5001                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5002                     break;
5003                 case R.styleable.View_accessibilityLiveRegion:
5004                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5005                     break;
5006                 case R.styleable.View_transitionName:
5007                     setTransitionName(a.getString(attr));
5008                     break;
5009                 case R.styleable.View_nestedScrollingEnabled:
5010                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5011                     break;
5012                 case R.styleable.View_stateListAnimator:
5013                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5014                             a.getResourceId(attr, 0)));
5015                     break;
5016                 case R.styleable.View_backgroundTint:
5017                     // This will get applied later during setBackground().
5018                     if (mBackgroundTint == null) {
5019                         mBackgroundTint = new TintInfo();
5020                     }
5021                     mBackgroundTint.mTintList = a.getColorStateList(
5022                             R.styleable.View_backgroundTint);
5023                     mBackgroundTint.mHasTintList = true;
5024                     break;
5025                 case R.styleable.View_backgroundTintMode:
5026                     // This will get applied later during setBackground().
5027                     if (mBackgroundTint == null) {
5028                         mBackgroundTint = new TintInfo();
5029                     }
5030                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
5031                             R.styleable.View_backgroundTintMode, -1), null);
5032                     mBackgroundTint.mHasTintMode = true;
5033                     break;
5034                 case R.styleable.View_outlineProvider:
5035                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5036                             PROVIDER_BACKGROUND));
5037                     break;
5038                 case R.styleable.View_foreground:
5039                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5040                         setForeground(a.getDrawable(attr));
5041                     }
5042                     break;
5043                 case R.styleable.View_foregroundGravity:
5044                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5045                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5046                     }
5047                     break;
5048                 case R.styleable.View_foregroundTintMode:
5049                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5050                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5051                     }
5052                     break;
5053                 case R.styleable.View_foregroundTint:
5054                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5055                         setForegroundTintList(a.getColorStateList(attr));
5056                     }
5057                     break;
5058                 case R.styleable.View_foregroundInsidePadding:
5059                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5060                         if (mForegroundInfo == null) {
5061                             mForegroundInfo = new ForegroundInfo();
5062                         }
5063                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5064                                 mForegroundInfo.mInsidePadding);
5065                     }
5066                     break;
5067                 case R.styleable.View_scrollIndicators:
5068                     final int scrollIndicators =
5069                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5070                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5071                     if (scrollIndicators != 0) {
5072                         mPrivateFlags3 |= scrollIndicators;
5073                         initializeScrollIndicators = true;
5074                     }
5075                     break;
5076                 case R.styleable.View_pointerIcon:
5077                     final int resourceId = a.getResourceId(attr, 0);
5078                     if (resourceId != 0) {
5079                         setPointerIcon(PointerIcon.load(
5080                                 context.getResources(), resourceId));
5081                     } else {
5082                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5083                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5084                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5085                         }
5086                     }
5087                     break;
5088                 case R.styleable.View_forceHasOverlappingRendering:
5089                     if (a.peekValue(attr) != null) {
5090                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5091                     }
5092                     break;
5093                 case R.styleable.View_tooltipText:
5094                     setTooltipText(a.getText(attr));
5095                     break;
5096                 case R.styleable.View_keyboardNavigationCluster:
5097                     if (a.peekValue(attr) != null) {
5098                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5099                     }
5100                     break;
5101                 case R.styleable.View_focusedByDefault:
5102                     if (a.peekValue(attr) != null) {
5103                         setFocusedByDefault(a.getBoolean(attr, true));
5104                     }
5105                     break;
5106                 case R.styleable.View_autofillHints:
5107                     if (a.peekValue(attr) != null) {
5108                         CharSequence[] rawHints = null;
5109                         String rawString = null;
5110
5111                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5112                             int resId = a.getResourceId(attr, 0);
5113
5114                             try {
5115                                 rawHints = a.getTextArray(attr);
5116                             } catch (Resources.NotFoundException e) {
5117                                 rawString = getResources().getString(resId);
5118                             }
5119                         } else {
5120                             rawString = a.getString(attr);
5121                         }
5122
5123                         if (rawHints == null) {
5124                             if (rawString == null) {
5125                                 throw new IllegalArgumentException(
5126                                         "Could not resolve autofillHints");
5127                             } else {
5128                                 rawHints = rawString.split(",");
5129                             }
5130                         }
5131
5132                         String[] hints = new String[rawHints.length];
5133
5134                         int numHints = rawHints.length;
5135                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5136                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5137                         }
5138                         setAutofillHints(hints);
5139                     }
5140                     break;
5141                 case R.styleable.View_importantForAutofill:
5142                     if (a.peekValue(attr) != null) {
5143                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5144                     }
5145                     break;
5146                 case R.styleable.View_defaultFocusHighlightEnabled:
5147                     if (a.peekValue(attr) != null) {
5148                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5149                     }
5150                     break;
5151             }
5152         }
5153
5154         setOverScrollMode(overScrollMode);
5155
5156         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5157         // the resolved layout direction). Those cached values will be used later during padding
5158         // resolution.
5159         mUserPaddingStart = startPadding;
5160         mUserPaddingEnd = endPadding;
5161
5162         if (background != null) {
5163             setBackground(background);
5164         }
5165
5166         // setBackground above will record that padding is currently provided by the background.
5167         // If we have padding specified via xml, record that here instead and use it.
5168         mLeftPaddingDefined = leftPaddingDefined;
5169         mRightPaddingDefined = rightPaddingDefined;
5170
5171         if (padding >= 0) {
5172             leftPadding = padding;
5173             topPadding = padding;
5174             rightPadding = padding;
5175             bottomPadding = padding;
5176             mUserPaddingLeftInitial = padding;
5177             mUserPaddingRightInitial = padding;
5178         } else {
5179             if (paddingHorizontal >= 0) {
5180                 leftPadding = paddingHorizontal;
5181                 rightPadding = paddingHorizontal;
5182                 mUserPaddingLeftInitial = paddingHorizontal;
5183                 mUserPaddingRightInitial = paddingHorizontal;
5184             }
5185             if (paddingVertical >= 0) {
5186                 topPadding = paddingVertical;
5187                 bottomPadding = paddingVertical;
5188             }
5189         }
5190
5191         if (isRtlCompatibilityMode()) {
5192             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5193             // left / right padding are used if defined (meaning here nothing to do). If they are not
5194             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5195             // start / end and resolve them as left / right (layout direction is not taken into account).
5196             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5197             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5198             // defined.
5199             if (!mLeftPaddingDefined && startPaddingDefined) {
5200                 leftPadding = startPadding;
5201             }
5202             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5203             if (!mRightPaddingDefined && endPaddingDefined) {
5204                 rightPadding = endPadding;
5205             }
5206             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5207         } else {
5208             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5209             // values defined. Otherwise, left /right values are used.
5210             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5211             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5212             // defined.
5213             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5214
5215             if (mLeftPaddingDefined && !hasRelativePadding) {
5216                 mUserPaddingLeftInitial = leftPadding;
5217             }
5218             if (mRightPaddingDefined && !hasRelativePadding) {
5219                 mUserPaddingRightInitial = rightPadding;
5220             }
5221         }
5222
5223         internalSetPadding(
5224                 mUserPaddingLeftInitial,
5225                 topPadding >= 0 ? topPadding : mPaddingTop,
5226                 mUserPaddingRightInitial,
5227                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5228
5229         if (viewFlagMasks != 0) {
5230             setFlags(viewFlagValues, viewFlagMasks);
5231         }
5232
5233         if (initializeScrollbars) {
5234             initializeScrollbarsInternal(a);
5235         }
5236
5237         if (initializeScrollIndicators) {
5238             initializeScrollIndicatorsInternal();
5239         }
5240
5241         a.recycle();
5242
5243         // Needs to be called after mViewFlags is set
5244         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5245             recomputePadding();
5246         }
5247
5248         if (x != 0 || y != 0) {
5249             scrollTo(x, y);
5250         }
5251
5252         if (transformSet) {
5253             setTranslationX(tx);
5254             setTranslationY(ty);
5255             setTranslationZ(tz);
5256             setElevation(elevation);
5257             setRotation(rotation);
5258             setRotationX(rotationX);
5259             setRotationY(rotationY);
5260             setScaleX(sx);
5261             setScaleY(sy);
5262         }
5263
5264         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5265             setScrollContainer(true);
5266         }
5267
5268         computeOpaqueFlags();
5269     }
5270
5271     /**
5272      * An implementation of OnClickListener that attempts to lazily load a
5273      * named click handling method from a parent or ancestor context.
5274      */
5275     private static class DeclaredOnClickListener implements OnClickListener {
5276         private final View mHostView;
5277         private final String mMethodName;
5278
5279         private Method mResolvedMethod;
5280         private Context mResolvedContext;
5281
5282         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5283             mHostView = hostView;
5284             mMethodName = methodName;
5285         }
5286
5287         @Override
5288         public void onClick(@NonNull View v) {
5289             if (mResolvedMethod == null) {
5290                 resolveMethod(mHostView.getContext(), mMethodName);
5291             }
5292
5293             try {
5294                 mResolvedMethod.invoke(mResolvedContext, v);
5295             } catch (IllegalAccessException e) {
5296                 throw new IllegalStateException(
5297                         "Could not execute non-public method for android:onClick", e);
5298             } catch (InvocationTargetException e) {
5299                 throw new IllegalStateException(
5300                         "Could not execute method for android:onClick", e);
5301             }
5302         }
5303
5304         @NonNull
5305         private void resolveMethod(@Nullable Context context, @NonNull String name) {
5306             while (context != null) {
5307                 try {
5308                     if (!context.isRestricted()) {
5309                         final Method method = context.getClass().getMethod(mMethodName, View.class);
5310                         if (method != null) {
5311                             mResolvedMethod = method;
5312                             mResolvedContext = context;
5313                             return;
5314                         }
5315                     }
5316                 } catch (NoSuchMethodException e) {
5317                     // Failed to find method, keep searching up the hierarchy.
5318                 }
5319
5320                 if (context instanceof ContextWrapper) {
5321                     context = ((ContextWrapper) context).getBaseContext();
5322                 } else {
5323                     // Can't search up the hierarchy, null out and fail.
5324                     context = null;
5325                 }
5326             }
5327
5328             final int id = mHostView.getId();
5329             final String idText = id == NO_ID ? "" : " with id '"
5330                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5331             throw new IllegalStateException("Could not find method " + mMethodName
5332                     + "(View) in a parent or ancestor Context for android:onClick "
5333                     + "attribute defined on view " + mHostView.getClass() + idText);
5334         }
5335     }
5336
5337     /**
5338      * Non-public constructor for use in testing
5339      */
5340     View() {
5341         mResources = null;
5342         mRenderNode = RenderNode.create(getClass().getName(), this);
5343     }
5344
5345     final boolean debugDraw() {
5346         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5347     }
5348
5349     private static SparseArray<String> getAttributeMap() {
5350         if (mAttributeMap == null) {
5351             mAttributeMap = new SparseArray<>();
5352         }
5353         return mAttributeMap;
5354     }
5355
5356     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5357         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5358         final int indexCount = t.getIndexCount();
5359         final String[] attributes = new String[(attrsCount + indexCount) * 2];
5360
5361         int i = 0;
5362
5363         // Store raw XML attributes.
5364         for (int j = 0; j < attrsCount; ++j) {
5365             attributes[i] = attrs.getAttributeName(j);
5366             attributes[i + 1] = attrs.getAttributeValue(j);
5367             i += 2;
5368         }
5369
5370         // Store resolved styleable attributes.
5371         final Resources res = t.getResources();
5372         final SparseArray<String> attributeMap = getAttributeMap();
5373         for (int j = 0; j < indexCount; ++j) {
5374             final int index = t.getIndex(j);
5375             if (!t.hasValueOrEmpty(index)) {
5376                 // Value is undefined. Skip it.
5377                 continue;
5378             }
5379
5380             final int resourceId = t.getResourceId(index, 0);
5381             if (resourceId == 0) {
5382                 // Value is not a reference. Skip it.
5383                 continue;
5384             }
5385
5386             String resourceName = attributeMap.get(resourceId);
5387             if (resourceName == null) {
5388                 try {
5389                     resourceName = res.getResourceName(resourceId);
5390                 } catch (Resources.NotFoundException e) {
5391                     resourceName = "0x" + Integer.toHexString(resourceId);
5392                 }
5393                 attributeMap.put(resourceId, resourceName);
5394             }
5395
5396             attributes[i] = resourceName;
5397             attributes[i + 1] = t.getString(index);
5398             i += 2;
5399         }
5400
5401         // Trim to fit contents.
5402         final String[] trimmed = new String[i];
5403         System.arraycopy(attributes, 0, trimmed, 0, i);
5404         mAttributes = trimmed;
5405     }
5406
5407     public String toString() {
5408         StringBuilder out = new StringBuilder(128);
5409         out.append(getClass().getName());
5410         out.append('{');
5411         out.append(Integer.toHexString(System.identityHashCode(this)));
5412         out.append(' ');
5413         switch (mViewFlags&VISIBILITY_MASK) {
5414             case VISIBLE: out.append('V'); break;
5415             case INVISIBLE: out.append('I'); break;
5416             case GONE: out.append('G'); break;
5417             default: out.append('.'); break;
5418         }
5419         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5420         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5421         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5422         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5423         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5424         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5425         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5426         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5427         out.append(' ');
5428         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5429         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5430         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5431         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5432             out.append('p');
5433         } else {
5434             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5435         }
5436         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5437         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5438         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5439         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5440         out.append(' ');
5441         out.append(mLeft);
5442         out.append(',');
5443         out.append(mTop);
5444         out.append('-');
5445         out.append(mRight);
5446         out.append(',');
5447         out.append(mBottom);
5448         final int id = getId();
5449         if (id != NO_ID) {
5450             out.append(" #");
5451             out.append(Integer.toHexString(id));
5452             final Resources r = mResources;
5453             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5454                 try {
5455                     String pkgname;
5456                     switch (id&0xff000000) {
5457                         case 0x7f000000:
5458                             pkgname="app";
5459                             break;
5460                         case 0x01000000:
5461                             pkgname="android";
5462                             break;
5463                         default:
5464                             pkgname = r.getResourcePackageName(id);
5465                             break;
5466                     }
5467                     String typename = r.getResourceTypeName(id);
5468                     String entryname = r.getResourceEntryName(id);
5469                     out.append(" ");
5470                     out.append(pkgname);
5471                     out.append(":");
5472                     out.append(typename);
5473                     out.append("/");
5474                     out.append(entryname);
5475                 } catch (Resources.NotFoundException e) {
5476                 }
5477             }
5478         }
5479         out.append("}");
5480         return out.toString();
5481     }
5482
5483     /**
5484      * <p>
5485      * Initializes the fading edges from a given set of styled attributes. This
5486      * method should be called by subclasses that need fading edges and when an
5487      * instance of these subclasses is created programmatically rather than
5488      * being inflated from XML. This method is automatically called when the XML
5489      * is inflated.
5490      * </p>
5491      *
5492      * @param a the styled attributes set to initialize the fading edges from
5493      *
5494      * @removed
5495      */
5496     protected void initializeFadingEdge(TypedArray a) {
5497         // This method probably shouldn't have been included in the SDK to begin with.
5498         // It relies on 'a' having been initialized using an attribute filter array that is
5499         // not publicly available to the SDK. The old method has been renamed
5500         // to initializeFadingEdgeInternal and hidden for framework use only;
5501         // this one initializes using defaults to make it safe to call for apps.
5502
5503         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5504
5505         initializeFadingEdgeInternal(arr);
5506
5507         arr.recycle();
5508     }
5509
5510     /**
5511      * <p>
5512      * Initializes the fading edges from a given set of styled attributes. This
5513      * method should be called by subclasses that need fading edges and when an
5514      * instance of these subclasses is created programmatically rather than
5515      * being inflated from XML. This method is automatically called when the XML
5516      * is inflated.
5517      * </p>
5518      *
5519      * @param a the styled attributes set to initialize the fading edges from
5520      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5521      */
5522     protected void initializeFadingEdgeInternal(TypedArray a) {
5523         initScrollCache();
5524
5525         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5526                 R.styleable.View_fadingEdgeLength,
5527                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5528     }
5529
5530     /**
5531      * Returns the size of the vertical faded edges used to indicate that more
5532      * content in this view is visible.
5533      *
5534      * @return The size in pixels of the vertical faded edge or 0 if vertical
5535      *         faded edges are not enabled for this view.
5536      * @attr ref android.R.styleable#View_fadingEdgeLength
5537      */
5538     public int getVerticalFadingEdgeLength() {
5539         if (isVerticalFadingEdgeEnabled()) {
5540             ScrollabilityCache cache = mScrollCache;
5541             if (cache != null) {
5542                 return cache.fadingEdgeLength;
5543             }
5544         }
5545         return 0;
5546     }
5547
5548     /**
5549      * Set the size of the faded edge used to indicate that more content in this
5550      * view is available.  Will not change whether the fading edge is enabled; use
5551      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5552      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5553      * for the vertical or horizontal fading edges.
5554      *
5555      * @param length The size in pixels of the faded edge used to indicate that more
5556      *        content in this view is visible.
5557      */
5558     public void setFadingEdgeLength(int length) {
5559         initScrollCache();
5560         mScrollCache.fadingEdgeLength = length;
5561     }
5562
5563     /**
5564      * Returns the size of the horizontal faded edges used to indicate that more
5565      * content in this view is visible.
5566      *
5567      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5568      *         faded edges are not enabled for this view.
5569      * @attr ref android.R.styleable#View_fadingEdgeLength
5570      */
5571     public int getHorizontalFadingEdgeLength() {
5572         if (isHorizontalFadingEdgeEnabled()) {
5573             ScrollabilityCache cache = mScrollCache;
5574             if (cache != null) {
5575                 return cache.fadingEdgeLength;
5576             }
5577         }
5578         return 0;
5579     }
5580
5581     /**
5582      * Returns the width of the vertical scrollbar.
5583      *
5584      * @return The width in pixels of the vertical scrollbar or 0 if there
5585      *         is no vertical scrollbar.
5586      */
5587     public int getVerticalScrollbarWidth() {
5588         ScrollabilityCache cache = mScrollCache;
5589         if (cache != null) {
5590             ScrollBarDrawable scrollBar = cache.scrollBar;
5591             if (scrollBar != null) {
5592                 int size = scrollBar.getSize(true);
5593                 if (size <= 0) {
5594                     size = cache.scrollBarSize;
5595                 }
5596                 return size;
5597             }
5598             return 0;
5599         }
5600         return 0;
5601     }
5602
5603     /**
5604      * Returns the height of the horizontal scrollbar.
5605      *
5606      * @return The height in pixels of the horizontal scrollbar or 0 if
5607      *         there is no horizontal scrollbar.
5608      */
5609     protected int getHorizontalScrollbarHeight() {
5610         ScrollabilityCache cache = mScrollCache;
5611         if (cache != null) {
5612             ScrollBarDrawable scrollBar = cache.scrollBar;
5613             if (scrollBar != null) {
5614                 int size = scrollBar.getSize(false);
5615                 if (size <= 0) {
5616                     size = cache.scrollBarSize;
5617                 }
5618                 return size;
5619             }
5620             return 0;
5621         }
5622         return 0;
5623     }
5624
5625     /**
5626      * <p>
5627      * Initializes the scrollbars from a given set of styled attributes. This
5628      * method should be called by subclasses that need scrollbars and when an
5629      * instance of these subclasses is created programmatically rather than
5630      * being inflated from XML. This method is automatically called when the XML
5631      * is inflated.
5632      * </p>
5633      *
5634      * @param a the styled attributes set to initialize the scrollbars from
5635      *
5636      * @removed
5637      */
5638     protected void initializeScrollbars(TypedArray a) {
5639         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5640         // using the View filter array which is not available to the SDK. As such, internal
5641         // framework usage now uses initializeScrollbarsInternal and we grab a default
5642         // TypedArray with the right filter instead here.
5643         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5644
5645         initializeScrollbarsInternal(arr);
5646
5647         // We ignored the method parameter. Recycle the one we actually did use.
5648         arr.recycle();
5649     }
5650
5651     /**
5652      * <p>
5653      * Initializes the scrollbars from a given set of styled attributes. This
5654      * method should be called by subclasses that need scrollbars and when an
5655      * instance of these subclasses is created programmatically rather than
5656      * being inflated from XML. This method is automatically called when the XML
5657      * is inflated.
5658      * </p>
5659      *
5660      * @param a the styled attributes set to initialize the scrollbars from
5661      * @hide
5662      */
5663     protected void initializeScrollbarsInternal(TypedArray a) {
5664         initScrollCache();
5665
5666         final ScrollabilityCache scrollabilityCache = mScrollCache;
5667
5668         if (scrollabilityCache.scrollBar == null) {
5669             scrollabilityCache.scrollBar = new ScrollBarDrawable();
5670             scrollabilityCache.scrollBar.setState(getDrawableState());
5671             scrollabilityCache.scrollBar.setCallback(this);
5672         }
5673
5674         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5675
5676         if (!fadeScrollbars) {
5677             scrollabilityCache.state = ScrollabilityCache.ON;
5678         }
5679         scrollabilityCache.fadeScrollBars = fadeScrollbars;
5680
5681
5682         scrollabilityCache.scrollBarFadeDuration = a.getInt(
5683                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5684                         .getScrollBarFadeDuration());
5685         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5686                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
5687                 ViewConfiguration.getScrollDefaultDelay());
5688
5689
5690         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5691                 com.android.internal.R.styleable.View_scrollbarSize,
5692                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
5693
5694         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5695         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5696
5697         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5698         if (thumb != null) {
5699             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5700         }
5701
5702         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5703                 false);
5704         if (alwaysDraw) {
5705             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5706         }
5707
5708         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5709         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5710
5711         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5712         if (thumb != null) {
5713             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5714         }
5715
5716         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5717                 false);
5718         if (alwaysDraw) {
5719             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5720         }
5721
5722         // Apply layout direction to the new Drawables if needed
5723         final int layoutDirection = getLayoutDirection();
5724         if (track != null) {
5725             track.setLayoutDirection(layoutDirection);
5726         }
5727         if (thumb != null) {
5728             thumb.setLayoutDirection(layoutDirection);
5729         }
5730
5731         // Re-apply user/background padding so that scrollbar(s) get added
5732         resolvePadding();
5733     }
5734
5735     private void initializeScrollIndicatorsInternal() {
5736         // Some day maybe we'll break this into top/left/start/etc. and let the
5737         // client control it. Until then, you can have any scroll indicator you
5738         // want as long as it's a 1dp foreground-colored rectangle.
5739         if (mScrollIndicatorDrawable == null) {
5740             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5741         }
5742     }
5743
5744     /**
5745      * <p>
5746      * Initalizes the scrollability cache if necessary.
5747      * </p>
5748      */
5749     private void initScrollCache() {
5750         if (mScrollCache == null) {
5751             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5752         }
5753     }
5754
5755     private ScrollabilityCache getScrollCache() {
5756         initScrollCache();
5757         return mScrollCache;
5758     }
5759
5760     /**
5761      * Set the position of the vertical scroll bar. Should be one of
5762      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5763      * {@link #SCROLLBAR_POSITION_RIGHT}.
5764      *
5765      * @param position Where the vertical scroll bar should be positioned.
5766      */
5767     public void setVerticalScrollbarPosition(int position) {
5768         if (mVerticalScrollbarPosition != position) {
5769             mVerticalScrollbarPosition = position;
5770             computeOpaqueFlags();
5771             resolvePadding();
5772         }
5773     }
5774
5775     /**
5776      * @return The position where the vertical scroll bar will show, if applicable.
5777      * @see #setVerticalScrollbarPosition(int)
5778      */
5779     public int getVerticalScrollbarPosition() {
5780         return mVerticalScrollbarPosition;
5781     }
5782
5783     boolean isOnScrollbar(float x, float y) {
5784         if (mScrollCache == null) {
5785             return false;
5786         }
5787         x += getScrollX();
5788         y += getScrollY();
5789         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5790             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5791             getVerticalScrollBarBounds(null, touchBounds);
5792             if (touchBounds.contains((int) x, (int) y)) {
5793                 return true;
5794             }
5795         }
5796         if (isHorizontalScrollBarEnabled()) {
5797             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5798             getHorizontalScrollBarBounds(null, touchBounds);
5799             if (touchBounds.contains((int) x, (int) y)) {
5800                 return true;
5801             }
5802         }
5803         return false;
5804     }
5805
5806     boolean isOnScrollbarThumb(float x, float y) {
5807         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5808     }
5809
5810     private boolean isOnVerticalScrollbarThumb(float x, float y) {
5811         if (mScrollCache == null) {
5812             return false;
5813         }
5814         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5815             x += getScrollX();
5816             y += getScrollY();
5817             final Rect bounds = mScrollCache.mScrollBarBounds;
5818             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5819             getVerticalScrollBarBounds(bounds, touchBounds);
5820             final int range = computeVerticalScrollRange();
5821             final int offset = computeVerticalScrollOffset();
5822             final int extent = computeVerticalScrollExtent();
5823             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5824                     extent, range);
5825             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5826                     extent, range, offset);
5827             final int thumbTop = bounds.top + thumbOffset;
5828             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5829             if (x >= touchBounds.left && x <= touchBounds.right
5830                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5831                 return true;
5832             }
5833         }
5834         return false;
5835     }
5836
5837     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5838         if (mScrollCache == null) {
5839             return false;
5840         }
5841         if (isHorizontalScrollBarEnabled()) {
5842             x += getScrollX();
5843             y += getScrollY();
5844             final Rect bounds = mScrollCache.mScrollBarBounds;
5845             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5846             getHorizontalScrollBarBounds(bounds, touchBounds);
5847             final int range = computeHorizontalScrollRange();
5848             final int offset = computeHorizontalScrollOffset();
5849             final int extent = computeHorizontalScrollExtent();
5850             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5851                     extent, range);
5852             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5853                     extent, range, offset);
5854             final int thumbLeft = bounds.left + thumbOffset;
5855             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5856             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5857                     && y >= touchBounds.top && y <= touchBounds.bottom) {
5858                 return true;
5859             }
5860         }
5861         return false;
5862     }
5863
5864     boolean isDraggingScrollBar() {
5865         return mScrollCache != null
5866                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5867     }
5868
5869     /**
5870      * Sets the state of all scroll indicators.
5871      * <p>
5872      * See {@link #setScrollIndicators(int, int)} for usage information.
5873      *
5874      * @param indicators a bitmask of indicators that should be enabled, or
5875      *                   {@code 0} to disable all indicators
5876      * @see #setScrollIndicators(int, int)
5877      * @see #getScrollIndicators()
5878      * @attr ref android.R.styleable#View_scrollIndicators
5879      */
5880     public void setScrollIndicators(@ScrollIndicators int indicators) {
5881         setScrollIndicators(indicators,
5882                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5883     }
5884
5885     /**
5886      * Sets the state of the scroll indicators specified by the mask. To change
5887      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5888      * <p>
5889      * When a scroll indicator is enabled, it will be displayed if the view
5890      * can scroll in the direction of the indicator.
5891      * <p>
5892      * Multiple indicator types may be enabled or disabled by passing the
5893      * logical OR of the desired types. If multiple types are specified, they
5894      * will all be set to the same enabled state.
5895      * <p>
5896      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5897      *
5898      * @param indicators the indicator direction, or the logical OR of multiple
5899      *             indicator directions. One or more of:
5900      *             <ul>
5901      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5902      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5903      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5904      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5905      *               <li>{@link #SCROLL_INDICATOR_START}</li>
5906      *               <li>{@link #SCROLL_INDICATOR_END}</li>
5907      *             </ul>
5908      * @see #setScrollIndicators(int)
5909      * @see #getScrollIndicators()
5910      * @attr ref android.R.styleable#View_scrollIndicators
5911      */
5912     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5913         // Shift and sanitize mask.
5914         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5915         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5916
5917         // Shift and mask indicators.
5918         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5919         indicators &= mask;
5920
5921         // Merge with non-masked flags.
5922         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5923
5924         if (mPrivateFlags3 != updatedFlags) {
5925             mPrivateFlags3 = updatedFlags;
5926
5927             if (indicators != 0) {
5928                 initializeScrollIndicatorsInternal();
5929             }
5930             invalidate();
5931         }
5932     }
5933
5934     /**
5935      * Returns a bitmask representing the enabled scroll indicators.
5936      * <p>
5937      * For example, if the top and left scroll indicators are enabled and all
5938      * other indicators are disabled, the return value will be
5939      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5940      * <p>
5941      * To check whether the bottom scroll indicator is enabled, use the value
5942      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5943      *
5944      * @return a bitmask representing the enabled scroll indicators
5945      */
5946     @ScrollIndicators
5947     public int getScrollIndicators() {
5948         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5949                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5950     }
5951
5952     ListenerInfo getListenerInfo() {
5953         if (mListenerInfo != null) {
5954             return mListenerInfo;
5955         }
5956         mListenerInfo = new ListenerInfo();
5957         return mListenerInfo;
5958     }
5959
5960     /**
5961      * Register a callback to be invoked when the scroll X or Y positions of
5962      * this view change.
5963      * <p>
5964      * <b>Note:</b> Some views handle scrolling independently from View and may
5965      * have their own separate listeners for scroll-type events. For example,
5966      * {@link android.widget.ListView ListView} allows clients to register an
5967      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5968      * to listen for changes in list scroll position.
5969      *
5970      * @param l The listener to notify when the scroll X or Y position changes.
5971      * @see android.view.View#getScrollX()
5972      * @see android.view.View#getScrollY()
5973      */
5974     public void setOnScrollChangeListener(OnScrollChangeListener l) {
5975         getListenerInfo().mOnScrollChangeListener = l;
5976     }
5977
5978     /**
5979      * Register a callback to be invoked when focus of this view changed.
5980      *
5981      * @param l The callback that will run.
5982      */
5983     public void setOnFocusChangeListener(OnFocusChangeListener l) {
5984         getListenerInfo().mOnFocusChangeListener = l;
5985     }
5986
5987     /**
5988      * Add a listener that will be called when the bounds of the view change due to
5989      * layout processing.
5990      *
5991      * @param listener The listener that will be called when layout bounds change.
5992      */
5993     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5994         ListenerInfo li = getListenerInfo();
5995         if (li.mOnLayoutChangeListeners == null) {
5996             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5997         }
5998         if (!li.mOnLayoutChangeListeners.contains(listener)) {
5999             li.mOnLayoutChangeListeners.add(listener);
6000         }
6001     }
6002
6003     /**
6004      * Remove a listener for layout changes.
6005      *
6006      * @param listener The listener for layout bounds change.
6007      */
6008     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6009         ListenerInfo li = mListenerInfo;
6010         if (li == null || li.mOnLayoutChangeListeners == null) {
6011             return;
6012         }
6013         li.mOnLayoutChangeListeners.remove(listener);
6014     }
6015
6016     /**
6017      * Add a listener for attach state changes.
6018      *
6019      * This listener will be called whenever this view is attached or detached
6020      * from a window. Remove the listener using
6021      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6022      *
6023      * @param listener Listener to attach
6024      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6025      */
6026     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6027         ListenerInfo li = getListenerInfo();
6028         if (li.mOnAttachStateChangeListeners == null) {
6029             li.mOnAttachStateChangeListeners
6030                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6031         }
6032         li.mOnAttachStateChangeListeners.add(listener);
6033     }
6034
6035     /**
6036      * Remove a listener for attach state changes. The listener will receive no further
6037      * notification of window attach/detach events.
6038      *
6039      * @param listener Listener to remove
6040      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6041      */
6042     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6043         ListenerInfo li = mListenerInfo;
6044         if (li == null || li.mOnAttachStateChangeListeners == null) {
6045             return;
6046         }
6047         li.mOnAttachStateChangeListeners.remove(listener);
6048     }
6049
6050     /**
6051      * Returns the focus-change callback registered for this view.
6052      *
6053      * @return The callback, or null if one is not registered.
6054      */
6055     public OnFocusChangeListener getOnFocusChangeListener() {
6056         ListenerInfo li = mListenerInfo;
6057         return li != null ? li.mOnFocusChangeListener : null;
6058     }
6059
6060     /**
6061      * Register a callback to be invoked when this view is clicked. If this view is not
6062      * clickable, it becomes clickable.
6063      *
6064      * @param l The callback that will run
6065      *
6066      * @see #setClickable(boolean)
6067      */
6068     public void setOnClickListener(@Nullable OnClickListener l) {
6069         if (!isClickable()) {
6070             setClickable(true);
6071         }
6072         getListenerInfo().mOnClickListener = l;
6073     }
6074
6075     /**
6076      * Return whether this view has an attached OnClickListener.  Returns
6077      * true if there is a listener, false if there is none.
6078      */
6079     public boolean hasOnClickListeners() {
6080         ListenerInfo li = mListenerInfo;
6081         return (li != null && li.mOnClickListener != null);
6082     }
6083
6084     /**
6085      * Register a callback to be invoked when this view is clicked and held. If this view is not
6086      * long clickable, it becomes long clickable.
6087      *
6088      * @param l The callback that will run
6089      *
6090      * @see #setLongClickable(boolean)
6091      */
6092     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6093         if (!isLongClickable()) {
6094             setLongClickable(true);
6095         }
6096         getListenerInfo().mOnLongClickListener = l;
6097     }
6098
6099     /**
6100      * Register a callback to be invoked when this view is context clicked. If the view is not
6101      * context clickable, it becomes context clickable.
6102      *
6103      * @param l The callback that will run
6104      * @see #setContextClickable(boolean)
6105      */
6106     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6107         if (!isContextClickable()) {
6108             setContextClickable(true);
6109         }
6110         getListenerInfo().mOnContextClickListener = l;
6111     }
6112
6113     /**
6114      * Register a callback to be invoked when the context menu for this view is
6115      * being built. If this view is not long clickable, it becomes long clickable.
6116      *
6117      * @param l The callback that will run
6118      *
6119      */
6120     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6121         if (!isLongClickable()) {
6122             setLongClickable(true);
6123         }
6124         getListenerInfo().mOnCreateContextMenuListener = l;
6125     }
6126
6127     /**
6128      * Set an observer to collect stats for each frame rendered for this view.
6129      *
6130      * @hide
6131      */
6132     public void addFrameMetricsListener(Window window,
6133             Window.OnFrameMetricsAvailableListener listener,
6134             Handler handler) {
6135         if (mAttachInfo != null) {
6136             if (mAttachInfo.mThreadedRenderer != null) {
6137                 if (mFrameMetricsObservers == null) {
6138                     mFrameMetricsObservers = new ArrayList<>();
6139                 }
6140
6141                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6142                         handler.getLooper(), listener);
6143                 mFrameMetricsObservers.add(fmo);
6144                 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6145             } else {
6146                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6147             }
6148         } else {
6149             if (mFrameMetricsObservers == null) {
6150                 mFrameMetricsObservers = new ArrayList<>();
6151             }
6152
6153             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6154                     handler.getLooper(), listener);
6155             mFrameMetricsObservers.add(fmo);
6156         }
6157     }
6158
6159     /**
6160      * Remove observer configured to collect frame stats for this view.
6161      *
6162      * @hide
6163      */
6164     public void removeFrameMetricsListener(
6165             Window.OnFrameMetricsAvailableListener listener) {
6166         ThreadedRenderer renderer = getThreadedRenderer();
6167         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6168         if (fmo == null) {
6169             throw new IllegalArgumentException(
6170                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
6171         }
6172
6173         if (mFrameMetricsObservers != null) {
6174             mFrameMetricsObservers.remove(fmo);
6175             if (renderer != null) {
6176                 renderer.removeFrameMetricsObserver(fmo);
6177             }
6178         }
6179     }
6180
6181     private void registerPendingFrameMetricsObservers() {
6182         if (mFrameMetricsObservers != null) {
6183             ThreadedRenderer renderer = getThreadedRenderer();
6184             if (renderer != null) {
6185                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6186                     renderer.addFrameMetricsObserver(fmo);
6187                 }
6188             } else {
6189                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6190             }
6191         }
6192     }
6193
6194     private FrameMetricsObserver findFrameMetricsObserver(
6195             Window.OnFrameMetricsAvailableListener listener) {
6196         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6197             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6198             if (observer.mListener == listener) {
6199                 return observer;
6200             }
6201         }
6202
6203         return null;
6204     }
6205
6206     /**
6207      * Call this view's OnClickListener, if it is defined.  Performs all normal
6208      * actions associated with clicking: reporting accessibility event, playing
6209      * a sound, etc.
6210      *
6211      * @return True there was an assigned OnClickListener that was called, false
6212      *         otherwise is returned.
6213      */
6214     public boolean performClick() {
6215         final boolean result;
6216         final ListenerInfo li = mListenerInfo;
6217         if (li != null && li.mOnClickListener != null) {
6218             playSoundEffect(SoundEffectConstants.CLICK);
6219             li.mOnClickListener.onClick(this);
6220             result = true;
6221         } else {
6222             result = false;
6223         }
6224
6225         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6226
6227         notifyEnterOrExitForAutoFillIfNeeded(true);
6228
6229         return result;
6230     }
6231
6232     /**
6233      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6234      * this only calls the listener, and does not do any associated clicking
6235      * actions like reporting an accessibility event.
6236      *
6237      * @return True there was an assigned OnClickListener that was called, false
6238      *         otherwise is returned.
6239      */
6240     public boolean callOnClick() {
6241         ListenerInfo li = mListenerInfo;
6242         if (li != null && li.mOnClickListener != null) {
6243             li.mOnClickListener.onClick(this);
6244             return true;
6245         }
6246         return false;
6247     }
6248
6249     /**
6250      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6251      * context menu if the OnLongClickListener did not consume the event.
6252      *
6253      * @return {@code true} if one of the above receivers consumed the event,
6254      *         {@code false} otherwise
6255      */
6256     public boolean performLongClick() {
6257         return performLongClickInternal(mLongClickX, mLongClickY);
6258     }
6259
6260     /**
6261      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6262      * context menu if the OnLongClickListener did not consume the event,
6263      * anchoring it to an (x,y) coordinate.
6264      *
6265      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6266      *          to disable anchoring
6267      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6268      *          to disable anchoring
6269      * @return {@code true} if one of the above receivers consumed the event,
6270      *         {@code false} otherwise
6271      */
6272     public boolean performLongClick(float x, float y) {
6273         mLongClickX = x;
6274         mLongClickY = y;
6275         final boolean handled = performLongClick();
6276         mLongClickX = Float.NaN;
6277         mLongClickY = Float.NaN;
6278         return handled;
6279     }
6280
6281     /**
6282      * Calls this view's OnLongClickListener, if it is defined. Invokes the
6283      * context menu if the OnLongClickListener did not consume the event,
6284      * optionally anchoring it to an (x,y) coordinate.
6285      *
6286      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6287      *          to disable anchoring
6288      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6289      *          to disable anchoring
6290      * @return {@code true} if one of the above receivers consumed the event,
6291      *         {@code false} otherwise
6292      */
6293     private boolean performLongClickInternal(float x, float y) {
6294         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6295
6296         boolean handled = false;
6297         final ListenerInfo li = mListenerInfo;
6298         if (li != null && li.mOnLongClickListener != null) {
6299             handled = li.mOnLongClickListener.onLongClick(View.this);
6300         }
6301         if (!handled) {
6302             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6303             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6304         }
6305         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6306             if (!handled) {
6307                 handled = showLongClickTooltip((int) x, (int) y);
6308             }
6309         }
6310         if (handled) {
6311             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6312         }
6313         return handled;
6314     }
6315
6316     /**
6317      * Call this view's OnContextClickListener, if it is defined.
6318      *
6319      * @param x the x coordinate of the context click
6320      * @param y the y coordinate of the context click
6321      * @return True if there was an assigned OnContextClickListener that consumed the event, false
6322      *         otherwise.
6323      */
6324     public boolean performContextClick(float x, float y) {
6325         return performContextClick();
6326     }
6327
6328     /**
6329      * Call this view's OnContextClickListener, if it is defined.
6330      *
6331      * @return True if there was an assigned OnContextClickListener that consumed the event, false
6332      *         otherwise.
6333      */
6334     public boolean performContextClick() {
6335         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6336
6337         boolean handled = false;
6338         ListenerInfo li = mListenerInfo;
6339         if (li != null && li.mOnContextClickListener != null) {
6340             handled = li.mOnContextClickListener.onContextClick(View.this);
6341         }
6342         if (handled) {
6343             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6344         }
6345         return handled;
6346     }
6347
6348     /**
6349      * Performs button-related actions during a touch down event.
6350      *
6351      * @param event The event.
6352      * @return True if the down was consumed.
6353      *
6354      * @hide
6355      */
6356     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6357         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6358             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6359             showContextMenu(event.getX(), event.getY());
6360             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6361             return true;
6362         }
6363         return false;
6364     }
6365
6366     /**
6367      * Shows the context menu for this view.
6368      *
6369      * @return {@code true} if the context menu was shown, {@code false}
6370      *         otherwise
6371      * @see #showContextMenu(float, float)
6372      */
6373     public boolean showContextMenu() {
6374         return getParent().showContextMenuForChild(this);
6375     }
6376
6377     /**
6378      * Shows the context menu for this view anchored to the specified
6379      * view-relative coordinate.
6380      *
6381      * @param x the X coordinate in pixels relative to the view to which the
6382      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6383      * @param y the Y coordinate in pixels relative to the view to which the
6384      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6385      * @return {@code true} if the context menu was shown, {@code false}
6386      *         otherwise
6387      */
6388     public boolean showContextMenu(float x, float y) {
6389         return getParent().showContextMenuForChild(this, x, y);
6390     }
6391
6392     /**
6393      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6394      *
6395      * @param callback Callback that will control the lifecycle of the action mode
6396      * @return The new action mode if it is started, null otherwise
6397      *
6398      * @see ActionMode
6399      * @see #startActionMode(android.view.ActionMode.Callback, int)
6400      */
6401     public ActionMode startActionMode(ActionMode.Callback callback) {
6402         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6403     }
6404
6405     /**
6406      * Start an action mode with the given type.
6407      *
6408      * @param callback Callback that will control the lifecycle of the action mode
6409      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6410      * @return The new action mode if it is started, null otherwise
6411      *
6412      * @see ActionMode
6413      */
6414     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6415         ViewParent parent = getParent();
6416         if (parent == null) return null;
6417         try {
6418             return parent.startActionModeForChild(this, callback, type);
6419         } catch (AbstractMethodError ame) {
6420             // Older implementations of custom views might not implement this.
6421             return parent.startActionModeForChild(this, callback);
6422         }
6423     }
6424
6425     /**
6426      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6427      * Context, creating a unique View identifier to retrieve the result.
6428      *
6429      * @param intent The Intent to be started.
6430      * @param requestCode The request code to use.
6431      * @hide
6432      */
6433     public void startActivityForResult(Intent intent, int requestCode) {
6434         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6435         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6436     }
6437
6438     /**
6439      * If this View corresponds to the calling who, dispatches the activity result.
6440      * @param who The identifier for the targeted View to receive the result.
6441      * @param requestCode The integer request code originally supplied to
6442      *                    startActivityForResult(), allowing you to identify who this
6443      *                    result came from.
6444      * @param resultCode The integer result code returned by the child activity
6445      *                   through its setResult().
6446      * @param data An Intent, which can return result data to the caller
6447      *               (various data can be attached to Intent "extras").
6448      * @return {@code true} if the activity result was dispatched.
6449      * @hide
6450      */
6451     public boolean dispatchActivityResult(
6452             String who, int requestCode, int resultCode, Intent data) {
6453         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6454             onActivityResult(requestCode, resultCode, data);
6455             mStartActivityRequestWho = null;
6456             return true;
6457         }
6458         return false;
6459     }
6460
6461     /**
6462      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6463      *
6464      * @param requestCode The integer request code originally supplied to
6465      *                    startActivityForResult(), allowing you to identify who this
6466      *                    result came from.
6467      * @param resultCode The integer result code returned by the child activity
6468      *                   through its setResult().
6469      * @param data An Intent, which can return result data to the caller
6470      *               (various data can be attached to Intent "extras").
6471      * @hide
6472      */
6473     public void onActivityResult(int requestCode, int resultCode, Intent data) {
6474         // Do nothing.
6475     }
6476
6477     /**
6478      * Register a callback to be invoked when a hardware key is pressed in this view.
6479      * Key presses in software input methods will generally not trigger the methods of
6480      * this listener.
6481      * @param l the key listener to attach to this view
6482      */
6483     public void setOnKeyListener(OnKeyListener l) {
6484         getListenerInfo().mOnKeyListener = l;
6485     }
6486
6487     /**
6488      * Register a callback to be invoked when a touch event is sent to this view.
6489      * @param l the touch listener to attach to this view
6490      */
6491     public void setOnTouchListener(OnTouchListener l) {
6492         getListenerInfo().mOnTouchListener = l;
6493     }
6494
6495     /**
6496      * Register a callback to be invoked when a generic motion event is sent to this view.
6497      * @param l the generic motion listener to attach to this view
6498      */
6499     public void setOnGenericMotionListener(OnGenericMotionListener l) {
6500         getListenerInfo().mOnGenericMotionListener = l;
6501     }
6502
6503     /**
6504      * Register a callback to be invoked when a hover event is sent to this view.
6505      * @param l the hover listener to attach to this view
6506      */
6507     public void setOnHoverListener(OnHoverListener l) {
6508         getListenerInfo().mOnHoverListener = l;
6509     }
6510
6511     /**
6512      * Register a drag event listener callback object for this View. The parameter is
6513      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6514      * View, the system calls the
6515      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6516      * @param l An implementation of {@link android.view.View.OnDragListener}.
6517      */
6518     public void setOnDragListener(OnDragListener l) {
6519         getListenerInfo().mOnDragListener = l;
6520     }
6521
6522     /**
6523      * Give this view focus. This will cause
6524      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6525      *
6526      * Note: this does not check whether this {@link View} should get focus, it just
6527      * gives it focus no matter what.  It should only be called internally by framework
6528      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6529      *
6530      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6531      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6532      *        focus moved when requestFocus() is called. It may not always
6533      *        apply, in which case use the default View.FOCUS_DOWN.
6534      * @param previouslyFocusedRect The rectangle of the view that had focus
6535      *        prior in this View's coordinate system.
6536      */
6537     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6538         if (DBG) {
6539             System.out.println(this + " requestFocus()");
6540         }
6541
6542         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6543             mPrivateFlags |= PFLAG_FOCUSED;
6544
6545             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6546
6547             if (mParent != null) {
6548                 mParent.requestChildFocus(this, this);
6549                 updateFocusedInCluster(oldFocus, direction);
6550             }
6551
6552             if (mAttachInfo != null) {
6553                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6554             }
6555
6556             onFocusChanged(true, direction, previouslyFocusedRect);
6557             refreshDrawableState();
6558         }
6559     }
6560
6561     /**
6562      * Sets this view's preference for reveal behavior when it gains focus.
6563      *
6564      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6565      * this view would prefer to be brought fully into view when it gains focus.
6566      * For example, a text field that a user is meant to type into. Other views such
6567      * as scrolling containers may prefer to opt-out of this behavior.</p>
6568      *
6569      * <p>The default value for views is true, though subclasses may change this
6570      * based on their preferred behavior.</p>
6571      *
6572      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6573      *
6574      * @see #getRevealOnFocusHint()
6575      */
6576     public final void setRevealOnFocusHint(boolean revealOnFocus) {
6577         if (revealOnFocus) {
6578             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6579         } else {
6580             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6581         }
6582     }
6583
6584     /**
6585      * Returns this view's preference for reveal behavior when it gains focus.
6586      *
6587      * <p>When this method returns true for a child view requesting focus, ancestor
6588      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6589      * should make a best effort to make the newly focused child fully visible to the user.
6590      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6591      * other properties affecting visibility to the user as part of the focus change.</p>
6592      *
6593      * @return true if this view would prefer to become fully visible when it gains focus,
6594      *         false if it would prefer not to disrupt scroll positioning
6595      *
6596      * @see #setRevealOnFocusHint(boolean)
6597      */
6598     public final boolean getRevealOnFocusHint() {
6599         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6600     }
6601
6602     /**
6603      * Populates <code>outRect</code> with the hotspot bounds. By default,
6604      * the hotspot bounds are identical to the screen bounds.
6605      *
6606      * @param outRect rect to populate with hotspot bounds
6607      * @hide Only for internal use by views and widgets.
6608      */
6609     public void getHotspotBounds(Rect outRect) {
6610         final Drawable background = getBackground();
6611         if (background != null) {
6612             background.getHotspotBounds(outRect);
6613         } else {
6614             getBoundsOnScreen(outRect);
6615         }
6616     }
6617
6618     /**
6619      * Request that a rectangle of this view be visible on the screen,
6620      * scrolling if necessary just enough.
6621      *
6622      * <p>A View should call this if it maintains some notion of which part
6623      * of its content is interesting.  For example, a text editing view
6624      * should call this when its cursor moves.
6625      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6626      * It should not be affected by which part of the View is currently visible or its scroll
6627      * position.
6628      *
6629      * @param rectangle The rectangle in the View's content coordinate space
6630      * @return Whether any parent scrolled.
6631      */
6632     public boolean requestRectangleOnScreen(Rect rectangle) {
6633         return requestRectangleOnScreen(rectangle, false);
6634     }
6635
6636     /**
6637      * Request that a rectangle of this view be visible on the screen,
6638      * scrolling if necessary just enough.
6639      *
6640      * <p>A View should call this if it maintains some notion of which part
6641      * of its content is interesting.  For example, a text editing view
6642      * should call this when its cursor moves.
6643      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6644      * It should not be affected by which part of the View is currently visible or its scroll
6645      * position.
6646      * <p>When <code>immediate</code> is set to true, scrolling will not be
6647      * animated.
6648      *
6649      * @param rectangle The rectangle in the View's content coordinate space
6650      * @param immediate True to forbid animated scrolling, false otherwise
6651      * @return Whether any parent scrolled.
6652      */
6653     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6654         if (mParent == null) {
6655             return false;
6656         }
6657
6658         View child = this;
6659
6660         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6661         position.set(rectangle);
6662
6663         ViewParent parent = mParent;
6664         boolean scrolled = false;
6665         while (parent != null) {
6666             rectangle.set((int) position.left, (int) position.top,
6667                     (int) position.right, (int) position.bottom);
6668
6669             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6670
6671             if (!(parent instanceof View)) {
6672                 break;
6673             }
6674
6675             // move it from child's content coordinate space to parent's content coordinate space
6676             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6677
6678             child = (View) parent;
6679             parent = child.getParent();
6680         }
6681
6682         return scrolled;
6683     }
6684
6685     /**
6686      * Called when this view wants to give up focus. If focus is cleared
6687      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6688      * <p>
6689      * <strong>Note:</strong> When a View clears focus the framework is trying
6690      * to give focus to the first focusable View from the top. Hence, if this
6691      * View is the first from the top that can take focus, then all callbacks
6692      * related to clearing focus will be invoked after which the framework will
6693      * give focus to this view.
6694      * </p>
6695      */
6696     public void clearFocus() {
6697         if (DBG) {
6698             System.out.println(this + " clearFocus()");
6699         }
6700
6701         clearFocusInternal(null, true, true);
6702     }
6703
6704     /**
6705      * Clears focus from the view, optionally propagating the change up through
6706      * the parent hierarchy and requesting that the root view place new focus.
6707      *
6708      * @param propagate whether to propagate the change up through the parent
6709      *            hierarchy
6710      * @param refocus when propagate is true, specifies whether to request the
6711      *            root view place new focus
6712      */
6713     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6714         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6715             mPrivateFlags &= ~PFLAG_FOCUSED;
6716
6717             if (propagate && mParent != null) {
6718                 mParent.clearChildFocus(this);
6719             }
6720
6721             onFocusChanged(false, 0, null);
6722             refreshDrawableState();
6723
6724             if (propagate && (!refocus || !rootViewRequestFocus())) {
6725                 notifyGlobalFocusCleared(this);
6726             }
6727         }
6728     }
6729
6730     void notifyGlobalFocusCleared(View oldFocus) {
6731         if (oldFocus != null && mAttachInfo != null) {
6732             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6733         }
6734     }
6735
6736     boolean rootViewRequestFocus() {
6737         final View root = getRootView();
6738         return root != null && root.requestFocus();
6739     }
6740
6741     /**
6742      * Called internally by the view system when a new view is getting focus.
6743      * This is what clears the old focus.
6744      * <p>
6745      * <b>NOTE:</b> The parent view's focused child must be updated manually
6746      * after calling this method. Otherwise, the view hierarchy may be left in
6747      * an inconstent state.
6748      */
6749     void unFocus(View focused) {
6750         if (DBG) {
6751             System.out.println(this + " unFocus()");
6752         }
6753
6754         clearFocusInternal(focused, false, false);
6755     }
6756
6757     /**
6758      * Returns true if this view has focus itself, or is the ancestor of the
6759      * view that has focus.
6760      *
6761      * @return True if this view has or contains focus, false otherwise.
6762      */
6763     @ViewDebug.ExportedProperty(category = "focus")
6764     public boolean hasFocus() {
6765         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6766     }
6767
6768     /**
6769      * Returns true if this view is focusable or if it contains a reachable View
6770      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6771      * is a view whose parents do not block descendants focus.
6772      * Only {@link #VISIBLE} views are considered focusable.
6773      *
6774      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6775      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6776      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6777      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6778      * {@code false} for views not explicitly marked as focusable.
6779      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6780      * behavior.</p>
6781      *
6782      * @return {@code true} if the view is focusable or if the view contains a focusable
6783      *         view, {@code false} otherwise
6784      *
6785      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6786      * @see ViewGroup#getTouchscreenBlocksFocus()
6787      * @see #hasExplicitFocusable()
6788      */
6789     public boolean hasFocusable() {
6790         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6791     }
6792
6793     /**
6794      * Returns true if this view is focusable or if it contains a reachable View
6795      * for which {@link #hasExplicitFocusable()} returns {@code true}.
6796      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6797      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6798      * {@link #FOCUSABLE} are considered focusable.
6799      *
6800      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6801      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6802      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6803      * to focusable will not.</p>
6804      *
6805      * @return {@code true} if the view is focusable or if the view contains a focusable
6806      *         view, {@code false} otherwise
6807      *
6808      * @see #hasFocusable()
6809      */
6810     public boolean hasExplicitFocusable() {
6811         return hasFocusable(false, true);
6812     }
6813
6814     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6815         if (!isFocusableInTouchMode()) {
6816             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6817                 final ViewGroup g = (ViewGroup) p;
6818                 if (g.shouldBlockFocusForTouchscreen()) {
6819                     return false;
6820                 }
6821             }
6822         }
6823
6824         // Invisible and gone views are never focusable.
6825         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6826             return false;
6827         }
6828
6829         // Only use effective focusable value when allowed.
6830         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6831             return true;
6832         }
6833
6834         return false;
6835     }
6836
6837     /**
6838      * Called by the view system when the focus state of this view changes.
6839      * When the focus change event is caused by directional navigation, direction
6840      * and previouslyFocusedRect provide insight into where the focus is coming from.
6841      * When overriding, be sure to call up through to the super class so that
6842      * the standard focus handling will occur.
6843      *
6844      * @param gainFocus True if the View has focus; false otherwise.
6845      * @param direction The direction focus has moved when requestFocus()
6846      *                  is called to give this view focus. Values are
6847      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6848      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6849      *                  It may not always apply, in which case use the default.
6850      * @param previouslyFocusedRect The rectangle, in this view's coordinate
6851      *        system, of the previously focused view.  If applicable, this will be
6852      *        passed in as finer grained information about where the focus is coming
6853      *        from (in addition to direction).  Will be <code>null</code> otherwise.
6854      */
6855     @CallSuper
6856     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6857             @Nullable Rect previouslyFocusedRect) {
6858         if (gainFocus) {
6859             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6860         } else {
6861             notifyViewAccessibilityStateChangedIfNeeded(
6862                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6863         }
6864
6865         // Here we check whether we still need the default focus highlight, and switch it on/off.
6866         switchDefaultFocusHighlight();
6867
6868         InputMethodManager imm = InputMethodManager.peekInstance();
6869         if (!gainFocus) {
6870             if (isPressed()) {
6871                 setPressed(false);
6872             }
6873             if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6874                 imm.focusOut(this);
6875             }
6876             onFocusLost();
6877         } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6878             imm.focusIn(this);
6879         }
6880
6881         invalidate(true);
6882         ListenerInfo li = mListenerInfo;
6883         if (li != null && li.mOnFocusChangeListener != null) {
6884             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6885         }
6886
6887         if (mAttachInfo != null) {
6888             mAttachInfo.mKeyDispatchState.reset(this);
6889         }
6890
6891         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6892     }
6893
6894     private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6895         if (isAutofillable() && isAttachedToWindow()) {
6896             AutofillManager afm = getAutofillManager();
6897             if (afm != null) {
6898                 if (enter && hasWindowFocus() && isFocused()) {
6899                     // We have not been laid out yet, hence cannot evaluate
6900                     // whether this view is visible to the user, we will do
6901                     // the evaluation once layout is complete.
6902                     if (!isLaidOut()) {
6903                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
6904                     } else if (isVisibleToUser()) {
6905                         afm.notifyViewEntered(this);
6906                     }
6907                 } else if (!hasWindowFocus() || !isFocused()) {
6908                     afm.notifyViewExited(this);
6909                 }
6910             }
6911         }
6912     }
6913
6914     /**
6915      * Sends an accessibility event of the given type. If accessibility is
6916      * not enabled this method has no effect. The default implementation calls
6917      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6918      * to populate information about the event source (this View), then calls
6919      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6920      * populate the text content of the event source including its descendants,
6921      * and last calls
6922      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6923      * on its parent to request sending of the event to interested parties.
6924      * <p>
6925      * If an {@link AccessibilityDelegate} has been specified via calling
6926      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6927      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6928      * responsible for handling this call.
6929      * </p>
6930      *
6931      * @param eventType The type of the event to send, as defined by several types from
6932      * {@link android.view.accessibility.AccessibilityEvent}, such as
6933      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6934      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6935      *
6936      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6937      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6938      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6939      * @see AccessibilityDelegate
6940      */
6941     public void sendAccessibilityEvent(int eventType) {
6942         if (mAccessibilityDelegate != null) {
6943             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6944         } else {
6945             sendAccessibilityEventInternal(eventType);
6946         }
6947     }
6948
6949     /**
6950      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6951      * {@link AccessibilityEvent} to make an announcement which is related to some
6952      * sort of a context change for which none of the events representing UI transitions
6953      * is a good fit. For example, announcing a new page in a book. If accessibility
6954      * is not enabled this method does nothing.
6955      *
6956      * @param text The announcement text.
6957      */
6958     public void announceForAccessibility(CharSequence text) {
6959         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6960             AccessibilityEvent event = AccessibilityEvent.obtain(
6961                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
6962             onInitializeAccessibilityEvent(event);
6963             event.getText().add(text);
6964             event.setContentDescription(null);
6965             mParent.requestSendAccessibilityEvent(this, event);
6966         }
6967     }
6968
6969     /**
6970      * @see #sendAccessibilityEvent(int)
6971      *
6972      * Note: Called from the default {@link AccessibilityDelegate}.
6973      *
6974      * @hide
6975      */
6976     public void sendAccessibilityEventInternal(int eventType) {
6977         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6978             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6979         }
6980     }
6981
6982     /**
6983      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6984      * takes as an argument an empty {@link AccessibilityEvent} and does not
6985      * perform a check whether accessibility is enabled.
6986      * <p>
6987      * If an {@link AccessibilityDelegate} has been specified via calling
6988      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6989      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6990      * is responsible for handling this call.
6991      * </p>
6992      *
6993      * @param event The event to send.
6994      *
6995      * @see #sendAccessibilityEvent(int)
6996      */
6997     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6998         if (mAccessibilityDelegate != null) {
6999             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7000         } else {
7001             sendAccessibilityEventUncheckedInternal(event);
7002         }
7003     }
7004
7005     /**
7006      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7007      *
7008      * Note: Called from the default {@link AccessibilityDelegate}.
7009      *
7010      * @hide
7011      */
7012     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
7013         if (!isShown()) {
7014             return;
7015         }
7016         onInitializeAccessibilityEvent(event);
7017         // Only a subset of accessibility events populates text content.
7018         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
7019             dispatchPopulateAccessibilityEvent(event);
7020         }
7021         // In the beginning we called #isShown(), so we know that getParent() is not null.
7022         ViewParent parent = getParent();
7023         if (parent != null) {
7024             getParent().requestSendAccessibilityEvent(this, event);
7025         }
7026     }
7027
7028     /**
7029      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
7030      * to its children for adding their text content to the event. Note that the
7031      * event text is populated in a separate dispatch path since we add to the
7032      * event not only the text of the source but also the text of all its descendants.
7033      * A typical implementation will call
7034      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
7035      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7036      * on each child. Override this method if custom population of the event text
7037      * content is required.
7038      * <p>
7039      * If an {@link AccessibilityDelegate} has been specified via calling
7040      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7041      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
7042      * is responsible for handling this call.
7043      * </p>
7044      * <p>
7045      * <em>Note:</em> Accessibility events of certain types are not dispatched for
7046      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
7047      * </p>
7048      *
7049      * @param event The event.
7050      *
7051      * @return True if the event population was completed.
7052      */
7053     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7054         if (mAccessibilityDelegate != null) {
7055             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
7056         } else {
7057             return dispatchPopulateAccessibilityEventInternal(event);
7058         }
7059     }
7060
7061     /**
7062      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7063      *
7064      * Note: Called from the default {@link AccessibilityDelegate}.
7065      *
7066      * @hide
7067      */
7068     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7069         onPopulateAccessibilityEvent(event);
7070         return false;
7071     }
7072
7073     /**
7074      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7075      * giving a chance to this View to populate the accessibility event with its
7076      * text content. While this method is free to modify event
7077      * attributes other than text content, doing so should normally be performed in
7078      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7079      * <p>
7080      * Example: Adding formatted date string to an accessibility event in addition
7081      *          to the text added by the super implementation:
7082      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7083      *     super.onPopulateAccessibilityEvent(event);
7084      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7085      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7086      *         mCurrentDate.getTimeInMillis(), flags);
7087      *     event.getText().add(selectedDateUtterance);
7088      * }</pre>
7089      * <p>
7090      * If an {@link AccessibilityDelegate} has been specified via calling
7091      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7092      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7093      * is responsible for handling this call.
7094      * </p>
7095      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7096      * information to the event, in case the default implementation has basic information to add.
7097      * </p>
7098      *
7099      * @param event The accessibility event which to populate.
7100      *
7101      * @see #sendAccessibilityEvent(int)
7102      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7103      */
7104     @CallSuper
7105     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7106         if (mAccessibilityDelegate != null) {
7107             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7108         } else {
7109             onPopulateAccessibilityEventInternal(event);
7110         }
7111     }
7112
7113     /**
7114      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7115      *
7116      * Note: Called from the default {@link AccessibilityDelegate}.
7117      *
7118      * @hide
7119      */
7120     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7121     }
7122
7123     /**
7124      * Initializes an {@link AccessibilityEvent} with information about
7125      * this View which is the event source. In other words, the source of
7126      * an accessibility event is the view whose state change triggered firing
7127      * the event.
7128      * <p>
7129      * Example: Setting the password property of an event in addition
7130      *          to properties set by the super implementation:
7131      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7132      *     super.onInitializeAccessibilityEvent(event);
7133      *     event.setPassword(true);
7134      * }</pre>
7135      * <p>
7136      * If an {@link AccessibilityDelegate} has been specified via calling
7137      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7138      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7139      * is responsible for handling this call.
7140      * </p>
7141      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7142      * information to the event, in case the default implementation has basic information to add.
7143      * </p>
7144      * @param event The event to initialize.
7145      *
7146      * @see #sendAccessibilityEvent(int)
7147      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7148      */
7149     @CallSuper
7150     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7151         if (mAccessibilityDelegate != null) {
7152             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7153         } else {
7154             onInitializeAccessibilityEventInternal(event);
7155         }
7156     }
7157
7158     /**
7159      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7160      *
7161      * Note: Called from the default {@link AccessibilityDelegate}.
7162      *
7163      * @hide
7164      */
7165     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7166         event.setSource(this);
7167         event.setClassName(getAccessibilityClassName());
7168         event.setPackageName(getContext().getPackageName());
7169         event.setEnabled(isEnabled());
7170         event.setContentDescription(mContentDescription);
7171
7172         switch (event.getEventType()) {
7173             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7174                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
7175                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7176                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7177                 event.setItemCount(focusablesTempList.size());
7178                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7179                 if (mAttachInfo != null) {
7180                     focusablesTempList.clear();
7181                 }
7182             } break;
7183             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7184                 CharSequence text = getIterableTextForAccessibility();
7185                 if (text != null && text.length() > 0) {
7186                     event.setFromIndex(getAccessibilitySelectionStart());
7187                     event.setToIndex(getAccessibilitySelectionEnd());
7188                     event.setItemCount(text.length());
7189                 }
7190             } break;
7191         }
7192     }
7193
7194     /**
7195      * Returns an {@link AccessibilityNodeInfo} representing this view from the
7196      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7197      * This method is responsible for obtaining an accessibility node info from a
7198      * pool of reusable instances and calling
7199      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7200      * initialize the former.
7201      * <p>
7202      * Note: The client is responsible for recycling the obtained instance by calling
7203      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7204      * </p>
7205      *
7206      * @return A populated {@link AccessibilityNodeInfo}.
7207      *
7208      * @see AccessibilityNodeInfo
7209      */
7210     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7211         if (mAccessibilityDelegate != null) {
7212             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7213         } else {
7214             return createAccessibilityNodeInfoInternal();
7215         }
7216     }
7217
7218     /**
7219      * @see #createAccessibilityNodeInfo()
7220      *
7221      * @hide
7222      */
7223     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7224         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7225         if (provider != null) {
7226             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7227         } else {
7228             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7229             onInitializeAccessibilityNodeInfo(info);
7230             return info;
7231         }
7232     }
7233
7234     /**
7235      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7236      * The base implementation sets:
7237      * <ul>
7238      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7239      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7240      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7241      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7242      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7243      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7244      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7245      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7246      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7247      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7248      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7249      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7250      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7251      * </ul>
7252      * <p>
7253      * Subclasses should override this method, call the super implementation,
7254      * and set additional attributes.
7255      * </p>
7256      * <p>
7257      * If an {@link AccessibilityDelegate} has been specified via calling
7258      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7259      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7260      * is responsible for handling this call.
7261      * </p>
7262      *
7263      * @param info The instance to initialize.
7264      */
7265     @CallSuper
7266     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7267         if (mAccessibilityDelegate != null) {
7268             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7269         } else {
7270             onInitializeAccessibilityNodeInfoInternal(info);
7271         }
7272     }
7273
7274     /**
7275      * Gets the location of this view in screen coordinates.
7276      *
7277      * @param outRect The output location
7278      * @hide
7279      */
7280     public void getBoundsOnScreen(Rect outRect) {
7281         getBoundsOnScreen(outRect, false);
7282     }
7283
7284     /**
7285      * Gets the location of this view in screen coordinates.
7286      *
7287      * @param outRect The output location
7288      * @param clipToParent Whether to clip child bounds to the parent ones.
7289      * @hide
7290      */
7291     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7292         if (mAttachInfo == null) {
7293             return;
7294         }
7295
7296         RectF position = mAttachInfo.mTmpTransformRect;
7297         position.set(0, 0, mRight - mLeft, mBottom - mTop);
7298         mapRectFromViewToScreenCoords(position, clipToParent);
7299         outRect.set(Math.round(position.left), Math.round(position.top),
7300                 Math.round(position.right), Math.round(position.bottom));
7301     }
7302
7303     /**
7304      * Map a rectangle from view-relative coordinates to screen-relative coordinates
7305      *
7306      * @param rect The rectangle to be mapped
7307      * @param clipToParent Whether to clip child bounds to the parent ones.
7308      * @hide
7309      */
7310     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7311         if (!hasIdentityMatrix()) {
7312             getMatrix().mapRect(rect);
7313         }
7314
7315         rect.offset(mLeft, mTop);
7316
7317         ViewParent parent = mParent;
7318         while (parent instanceof View) {
7319             View parentView = (View) parent;
7320
7321             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7322
7323             if (clipToParent) {
7324                 rect.left = Math.max(rect.left, 0);
7325                 rect.top = Math.max(rect.top, 0);
7326                 rect.right = Math.min(rect.right, parentView.getWidth());
7327                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7328             }
7329
7330             if (!parentView.hasIdentityMatrix()) {
7331                 parentView.getMatrix().mapRect(rect);
7332             }
7333
7334             rect.offset(parentView.mLeft, parentView.mTop);
7335
7336             parent = parentView.mParent;
7337         }
7338
7339         if (parent instanceof ViewRootImpl) {
7340             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7341             rect.offset(0, -viewRootImpl.mCurScrollY);
7342         }
7343
7344         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7345     }
7346
7347     /**
7348      * Return the class name of this object to be used for accessibility purposes.
7349      * Subclasses should only override this if they are implementing something that
7350      * should be seen as a completely new class of view when used by accessibility,
7351      * unrelated to the class it is deriving from.  This is used to fill in
7352      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7353      */
7354     public CharSequence getAccessibilityClassName() {
7355         return View.class.getName();
7356     }
7357
7358     /**
7359      * Called when assist structure is being retrieved from a view as part of
7360      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7361      * @param structure Fill in with structured view data.  The default implementation
7362      * fills in all data that can be inferred from the view itself.
7363      */
7364     public void onProvideStructure(ViewStructure structure) {
7365         onProvideStructureForAssistOrAutofill(structure, false, 0);
7366     }
7367
7368     /**
7369      * Called when assist structure is being retrieved from a view as part of an autofill request.
7370      *
7371      * <p>This method already provides most of what's needed for autofill, but should be overridden
7372      * when:
7373      * <ul>
7374      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7375      * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7376      *   <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
7377      * {@link ViewStructure#setAutofillOptions(CharSequence[])},
7378      * or {@link ViewStructure#setWebDomain(String)}.
7379      *   <li> The {@code left} and {@code top} values set in
7380      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} need to be relative to the next
7381      * {@link ViewGroup#isImportantForAutofill() included} parent in the structure.
7382      * </ul>
7383      *
7384      * @param structure Fill in with structured view data. The default implementation
7385      * fills in all data that can be inferred from the view itself.
7386      * @param flags optional flags.
7387      *
7388      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7389      */
7390     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
7391         onProvideStructureForAssistOrAutofill(structure, true, flags);
7392     }
7393
7394     private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7395             boolean forAutofill, @AutofillFlags int flags) {
7396         final int id = mID;
7397         if (id != NO_ID && !isViewIdGenerated(id)) {
7398             String pkg, type, entry;
7399             try {
7400                 final Resources res = getResources();
7401                 entry = res.getResourceEntryName(id);
7402                 type = res.getResourceTypeName(id);
7403                 pkg = res.getResourcePackageName(id);
7404             } catch (Resources.NotFoundException e) {
7405                 entry = type = pkg = null;
7406             }
7407             structure.setId(id, pkg, type, entry);
7408         } else {
7409             structure.setId(id, null, null, null);
7410         }
7411
7412         if (forAutofill) {
7413             final @AutofillType int autofillType = getAutofillType();
7414             // Don't need to fill autofill info if view does not support it.
7415             // For example, only TextViews that are editable support autofill
7416             if (autofillType != AUTOFILL_TYPE_NONE) {
7417                 structure.setAutofillType(autofillType);
7418                 structure.setAutofillHints(getAutofillHints());
7419                 structure.setAutofillValue(getAutofillValue());
7420             }
7421         }
7422
7423         int ignoredParentLeft = 0;
7424         int ignoredParentTop = 0;
7425         if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
7426             View parentGroup = null;
7427
7428             ViewParent viewParent = getParent();
7429             if (viewParent instanceof View) {
7430                 parentGroup = (View) viewParent;
7431             }
7432
7433             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
7434                 ignoredParentLeft += parentGroup.mLeft;
7435                 ignoredParentTop += parentGroup.mTop;
7436
7437                 viewParent = parentGroup.getParent();
7438                 if (viewParent instanceof View) {
7439                     parentGroup = (View) viewParent;
7440                 } else {
7441                     break;
7442                 }
7443             }
7444         }
7445
7446         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
7447                 mRight - mLeft, mBottom - mTop);
7448         if (!forAutofill) {
7449             if (!hasIdentityMatrix()) {
7450                 structure.setTransformation(getMatrix());
7451             }
7452             structure.setElevation(getZ());
7453         }
7454         structure.setVisibility(getVisibility());
7455         structure.setEnabled(isEnabled());
7456         if (isClickable()) {
7457             structure.setClickable(true);
7458         }
7459         if (isFocusable()) {
7460             structure.setFocusable(true);
7461         }
7462         if (isFocused()) {
7463             structure.setFocused(true);
7464         }
7465         if (isAccessibilityFocused()) {
7466             structure.setAccessibilityFocused(true);
7467         }
7468         if (isSelected()) {
7469             structure.setSelected(true);
7470         }
7471         if (isActivated()) {
7472             structure.setActivated(true);
7473         }
7474         if (isLongClickable()) {
7475             structure.setLongClickable(true);
7476         }
7477         if (this instanceof Checkable) {
7478             structure.setCheckable(true);
7479             if (((Checkable)this).isChecked()) {
7480                 structure.setChecked(true);
7481             }
7482         }
7483         if (isOpaque()) {
7484             structure.setOpaque(true);
7485         }
7486         if (isContextClickable()) {
7487             structure.setContextClickable(true);
7488         }
7489         structure.setClassName(getAccessibilityClassName().toString());
7490         structure.setContentDescription(getContentDescription());
7491     }
7492
7493     /**
7494      * Called when assist structure is being retrieved from a view as part of
7495      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7496      * generate additional virtual structure under this view.  The defaullt implementation
7497      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7498      * view's virtual accessibility nodes, if any.  You can override this for a more
7499      * optimal implementation providing this data.
7500      */
7501     public void onProvideVirtualStructure(ViewStructure structure) {
7502         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7503         if (provider != null) {
7504             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7505             structure.setChildCount(1);
7506             ViewStructure root = structure.newChild(0);
7507             populateVirtualStructure(root, provider, info);
7508             info.recycle();
7509         }
7510     }
7511
7512     /**
7513      * Called when assist structure is being retrieved from a view as part of an autofill request
7514      * to generate additional virtual structure under this view.
7515      *
7516      * <p>When implementing this method, subclasses must follow the rules below:
7517      *
7518      * <ol>
7519      * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7520      * children.
7521      * <li>Call
7522      * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
7523      * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7524      * when the focus inside the view changed.
7525      * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
7526      * AutofillValue)} when the value of a child changed.
7527      * <li>Call {@link AutofillManager#commit()} when the autofill context
7528      * of the view structure changed and you want the current autofill interaction if such
7529      * to be commited.
7530      * <li>Call {@link AutofillManager#cancel()} when the autofill context
7531      * of the view structure changed and you want the current autofill interaction if such
7532      * to be cancelled.
7533      * <li> The {@code left} and {@code top} values set in
7534      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} need to be relative to the next
7535      * {@link ViewGroup#isImportantForAutofill() included} parent in the structure.
7536      * </ol>
7537      *
7538      * @param structure Fill in with structured view data.
7539      * @param flags optional flags.
7540      *
7541      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7542      */
7543     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7544     }
7545
7546     /**
7547      * Automatically fills the content of this view with the {@code value}.
7548      *
7549      * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7550      * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7551      * to support the Autofill Framework.
7552      *
7553      * <p>Typically, it is implemented by:
7554      *
7555      * <ol>
7556      * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7557      * <li>Passing the actual value to the equivalent setter in the view.
7558      * </ol>
7559      *
7560      * <p>For example, a text-field view could implement the method this way:
7561      *
7562      * <pre class="prettyprint">
7563      * &#64;Override
7564      * public void autofill(AutofillValue value) {
7565      *   if (!value.isText() || !this.isEditable()) {
7566      *      return;
7567      *   }
7568      *   CharSequence text = value.getTextValue();
7569      *   if (text != null) {
7570      *     this.setText(text);
7571      *   }
7572      * }
7573      * </pre>
7574      *
7575      * <p>If the value is updated asynchronously the next call to
7576      * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
7577      * changed to the autofilled value. If not, the view will not be considered autofilled.
7578      *
7579      * @param value value to be autofilled.
7580      */
7581     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7582     }
7583
7584     /**
7585      * Automatically fills the content of a virtual views.
7586      *
7587      * <p>See {@link #autofill(AutofillValue)} and
7588      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7589      * <p>To indicate that a virtual view was autofilled
7590      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
7591      * changes.
7592      *
7593      * @param values map of values to be autofilled, keyed by virtual child id.
7594      *
7595      * @attr ref android.R.styleable#Theme_autofilledHighlight
7596      */
7597     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7598     }
7599
7600     /**
7601      * Gets the unique identifier of this view on the screen for Autofill purposes.
7602      *
7603      * @return The View's Autofill id.
7604      */
7605     public final AutofillId getAutofillId() {
7606         if (mAutofillId == null) {
7607             // The autofill id needs to be unique, but its value doesn't matter,
7608             // so it's better to reuse the accessibility id to save space.
7609             mAutofillId = new AutofillId(getAccessibilityViewId());
7610         }
7611         return mAutofillId;
7612     }
7613
7614     /**
7615      * Describes the autofill type that should be used on calls to
7616      * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
7617      *
7618      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7619      * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7620      */
7621     public @AutofillType int getAutofillType() {
7622         return AUTOFILL_TYPE_NONE;
7623     }
7624
7625     /**
7626      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
7627      * to autofill the view with the user's data.
7628      *
7629      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
7630      *
7631      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
7632      * {@code null} if no hints were set.
7633      *
7634      * @attr ref android.R.styleable#View_autofillHints
7635      */
7636     @ViewDebug.ExportedProperty()
7637     @Nullable public String[] getAutofillHints() {
7638         return mAutofillHints;
7639     }
7640
7641     /**
7642      * @hide
7643      */
7644     public boolean isAutofilled() {
7645         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7646     }
7647
7648     /**
7649      * Gets the {@link View}'s current autofill value.
7650      *
7651      * <p>By default returns {@code null}, but views should override it (and
7652      * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7653      * Framework.
7654      */
7655     @Nullable
7656     public AutofillValue getAutofillValue() {
7657         return null;
7658     }
7659
7660     /**
7661      * Gets the mode for determining whether this View is important for autofill.
7662      *
7663      * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7664      *
7665      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7666      * {@link #setImportantForAutofill(int)}.
7667      *
7668      * @attr ref android.R.styleable#View_importantForAutofill
7669      */
7670     @ViewDebug.ExportedProperty(mapping = {
7671             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7672             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7673             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7674             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7675                 to = "yesExcludeDescendants"),
7676             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7677                 to = "noExcludeDescendants")})
7678     public @AutofillImportance int getImportantForAutofill() {
7679         return (mPrivateFlags3
7680                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7681     }
7682
7683     /**
7684      * Sets the mode for determining whether this View is important for autofill.
7685      *
7686      * <p>This property controls how this view is presented to the autofill components
7687      * which help users to fill credentials, addresses, etc. For example, views
7688      * that contain labels and input fields are useful for autofill components to
7689      * determine the user context and provide values for the inputs. Note that the
7690      * user can always override this by manually triggering autotill which would
7691      * expose the view to the autofill provider.
7692      *
7693      * <p>The platform determines the importance for autofill automatically but you
7694      * can use this method to customize the behavior. See the autofill modes below
7695      * for more details.
7696      *
7697      * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7698      *
7699      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7700      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7701      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7702      *
7703      * @attr ref android.R.styleable#View_importantForAutofill
7704      */
7705     public void setImportantForAutofill(@AutofillImportance int mode) {
7706         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7707         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7708                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7709     }
7710
7711     /**
7712      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7713      * associated with this View should be included in a {@link ViewStructure} used for
7714      * autofill purposes.
7715      *
7716      * <p>Generally speaking, a view is important for autofill if:
7717      * <ol>
7718      * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7719      * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7720      * autofill other views.
7721      * <ol>
7722      *
7723      * <p>For example, view containers should typically return {@code false} for performance reasons
7724      * (since the important info is provided by their children), but if the container is actually
7725      * whose children are part of a compound view, it should return {@code true} (and then override
7726      * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7727      * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7728      * the structure). On the other hand, views representing labels or editable fields should
7729      * typically return {@code true}, but in some cases they could return {@code false} (for
7730      * example, if they're part of a "Captcha" mechanism).
7731      *
7732      * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7733      * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7734      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7735      * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7736      * should use {@link #setImportantForAutofill(int)} instead.
7737      *
7738      * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7739      * excluded from the structure; for example, if the user explicitly requested autofill, the
7740      * View might be always included.
7741      *
7742      * <p>This decision applies just for the view, not its children - if the view children are not
7743      * important for autofill, the view should override
7744      * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7745      * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7746      * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7747      *
7748      * @return whether the view is considered important for autofill.
7749      *
7750      * @see #setImportantForAutofill(int)
7751      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7752      * @see #IMPORTANT_FOR_AUTOFILL_YES
7753      * @see #IMPORTANT_FOR_AUTOFILL_NO
7754      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7755      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7756      */
7757     public final boolean isImportantForAutofill() {
7758         // Check parent mode to ensure we're not hidden.
7759         ViewParent parent = mParent;
7760         while (parent instanceof View) {
7761             final int parentImportance = ((View) parent).getImportantForAutofill();
7762             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7763                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
7764                 return false;
7765             }
7766             parent = parent.getParent();
7767         }
7768
7769         final int importance = getImportantForAutofill();
7770
7771         // First, check the explicit states.
7772         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7773                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
7774             return true;
7775         }
7776         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7777                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
7778             return false;
7779         }
7780
7781         // Then use some heuristics to handle AUTO.
7782
7783         // Always include views that have an explicit resource id.
7784         final int id = mID;
7785         if (id != NO_ID && !isViewIdGenerated(id)) {
7786             final Resources res = getResources();
7787             String entry = null;
7788             String pkg = null;
7789             try {
7790                 entry = res.getResourceEntryName(id);
7791                 pkg = res.getResourcePackageName(id);
7792             } catch (Resources.NotFoundException e) {
7793                 // ignore
7794             }
7795             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7796                 return true;
7797             }
7798         }
7799
7800         // Otherwise, assume it's not important...
7801         return false;
7802     }
7803
7804     @Nullable
7805     private AutofillManager getAutofillManager() {
7806         return mContext.getSystemService(AutofillManager.class);
7807     }
7808
7809     private boolean isAutofillable() {
7810         return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
7811                 && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID;
7812     }
7813
7814     private void populateVirtualStructure(ViewStructure structure,
7815             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
7816         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7817                 null, null, null);
7818         Rect rect = structure.getTempRect();
7819         info.getBoundsInParent(rect);
7820         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7821         structure.setVisibility(VISIBLE);
7822         structure.setEnabled(info.isEnabled());
7823         if (info.isClickable()) {
7824             structure.setClickable(true);
7825         }
7826         if (info.isFocusable()) {
7827             structure.setFocusable(true);
7828         }
7829         if (info.isFocused()) {
7830             structure.setFocused(true);
7831         }
7832         if (info.isAccessibilityFocused()) {
7833             structure.setAccessibilityFocused(true);
7834         }
7835         if (info.isSelected()) {
7836             structure.setSelected(true);
7837         }
7838         if (info.isLongClickable()) {
7839             structure.setLongClickable(true);
7840         }
7841         if (info.isCheckable()) {
7842             structure.setCheckable(true);
7843             if (info.isChecked()) {
7844                 structure.setChecked(true);
7845             }
7846         }
7847         if (info.isContextClickable()) {
7848             structure.setContextClickable(true);
7849         }
7850         CharSequence cname = info.getClassName();
7851         structure.setClassName(cname != null ? cname.toString() : null);
7852         structure.setContentDescription(info.getContentDescription());
7853         if ((info.getText() != null || info.getError() != null)) {
7854             structure.setText(info.getText(), info.getTextSelectionStart(),
7855                     info.getTextSelectionEnd());
7856         }
7857         final int NCHILDREN = info.getChildCount();
7858         if (NCHILDREN > 0) {
7859             structure.setChildCount(NCHILDREN);
7860             for (int i=0; i<NCHILDREN; i++) {
7861                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7862                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7863                 ViewStructure child = structure.newChild(i);
7864                 populateVirtualStructure(child, provider, cinfo);
7865                 cinfo.recycle();
7866             }
7867         }
7868     }
7869
7870     /**
7871      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7872      * implementation calls {@link #onProvideStructure} and
7873      * {@link #onProvideVirtualStructure}.
7874      */
7875     public void dispatchProvideStructure(ViewStructure structure) {
7876         dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
7877     }
7878
7879     /**
7880      * Dispatch creation of {@link ViewStructure} down the hierarchy.
7881      *
7882      * <p>The default implementation does the following:
7883      *
7884      * <ul>
7885      *   <li>Sets the {@link AutofillId} in the structure.
7886      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
7887      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7888      * </ul>
7889      *
7890      * <p>When overridden, it must either call
7891      * {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
7892      * set the {@link AutofillId} in the structure (for example, by calling
7893      * {@code structure.setAutofillId(getAutofillId())}).
7894      *
7895      * <p>When providing your implementation you need to decide how to handle
7896      * the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag which instructs you
7897      * to report all views to the structure regardless if {@link #isImportantForAutofill()}
7898      * returns true. We encourage you respect the importance property for a better
7899      * user experience in your app. If the flag is not set then you should filter out
7900      * not important views to optimize autofill performance in your app.
7901      *
7902      * @param structure Fill in with structured view data.
7903      * @param flags optional flags.
7904      *
7905      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7906      */
7907     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
7908             @AutofillFlags int flags) {
7909         dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
7910     }
7911
7912     private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7913             boolean forAutofill, @AutofillFlags int flags) {
7914         if (forAutofill) {
7915             structure.setAutofillId(getAutofillId());
7916             onProvideAutofillStructure(structure, flags);
7917             onProvideAutofillVirtualStructure(structure, flags);
7918         } else if (!isAssistBlocked()) {
7919             onProvideStructure(structure);
7920             onProvideVirtualStructure(structure);
7921         } else {
7922             structure.setClassName(getAccessibilityClassName().toString());
7923             structure.setAssistBlocked(true);
7924         }
7925     }
7926
7927     /**
7928      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7929      *
7930      * Note: Called from the default {@link AccessibilityDelegate}.
7931      *
7932      * @hide
7933      */
7934     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7935         if (mAttachInfo == null) {
7936             return;
7937         }
7938
7939         Rect bounds = mAttachInfo.mTmpInvalRect;
7940
7941         getDrawingRect(bounds);
7942         info.setBoundsInParent(bounds);
7943
7944         getBoundsOnScreen(bounds, true);
7945         info.setBoundsInScreen(bounds);
7946
7947         ViewParent parent = getParentForAccessibility();
7948         if (parent instanceof View) {
7949             info.setParent((View) parent);
7950         }
7951
7952         if (mID != View.NO_ID) {
7953             View rootView = getRootView();
7954             if (rootView == null) {
7955                 rootView = this;
7956             }
7957
7958             View label = rootView.findLabelForView(this, mID);
7959             if (label != null) {
7960                 info.setLabeledBy(label);
7961             }
7962
7963             if ((mAttachInfo.mAccessibilityFetchFlags
7964                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7965                     && Resources.resourceHasPackage(mID)) {
7966                 try {
7967                     String viewId = getResources().getResourceName(mID);
7968                     info.setViewIdResourceName(viewId);
7969                 } catch (Resources.NotFoundException nfe) {
7970                     /* ignore */
7971                 }
7972             }
7973         }
7974
7975         if (mLabelForId != View.NO_ID) {
7976             View rootView = getRootView();
7977             if (rootView == null) {
7978                 rootView = this;
7979             }
7980             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7981             if (labeled != null) {
7982                 info.setLabelFor(labeled);
7983             }
7984         }
7985
7986         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7987             View rootView = getRootView();
7988             if (rootView == null) {
7989                 rootView = this;
7990             }
7991             View next = rootView.findViewInsideOutShouldExist(this,
7992                     mAccessibilityTraversalBeforeId);
7993             if (next != null && next.includeForAccessibility()) {
7994                 info.setTraversalBefore(next);
7995             }
7996         }
7997
7998         if (mAccessibilityTraversalAfterId != View.NO_ID) {
7999             View rootView = getRootView();
8000             if (rootView == null) {
8001                 rootView = this;
8002             }
8003             View next = rootView.findViewInsideOutShouldExist(this,
8004                     mAccessibilityTraversalAfterId);
8005             if (next != null && next.includeForAccessibility()) {
8006                 info.setTraversalAfter(next);
8007             }
8008         }
8009
8010         info.setVisibleToUser(isVisibleToUser());
8011
8012         info.setImportantForAccessibility(isImportantForAccessibility());
8013         info.setPackageName(mContext.getPackageName());
8014         info.setClassName(getAccessibilityClassName());
8015         info.setContentDescription(getContentDescription());
8016
8017         info.setEnabled(isEnabled());
8018         info.setClickable(isClickable());
8019         info.setFocusable(isFocusable());
8020         info.setFocused(isFocused());
8021         info.setAccessibilityFocused(isAccessibilityFocused());
8022         info.setSelected(isSelected());
8023         info.setLongClickable(isLongClickable());
8024         info.setContextClickable(isContextClickable());
8025         info.setLiveRegion(getAccessibilityLiveRegion());
8026
8027         // TODO: These make sense only if we are in an AdapterView but all
8028         // views can be selected. Maybe from accessibility perspective
8029         // we should report as selectable view in an AdapterView.
8030         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
8031         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
8032
8033         if (isFocusable()) {
8034             if (isFocused()) {
8035                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
8036             } else {
8037                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
8038             }
8039         }
8040
8041         if (!isAccessibilityFocused()) {
8042             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
8043         } else {
8044             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
8045         }
8046
8047         if (isClickable() && isEnabled()) {
8048             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
8049         }
8050
8051         if (isLongClickable() && isEnabled()) {
8052             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
8053         }
8054
8055         if (isContextClickable() && isEnabled()) {
8056             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
8057         }
8058
8059         CharSequence text = getIterableTextForAccessibility();
8060         if (text != null && text.length() > 0) {
8061             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
8062
8063             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
8064             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
8065             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
8066             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
8067                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
8068                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
8069         }
8070
8071         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
8072         populateAccessibilityNodeInfoDrawingOrderInParent(info);
8073     }
8074
8075     /**
8076      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
8077      * additional data.
8078      * <p>
8079      * This method only needs overloading if the node is marked as having extra data available.
8080      * </p>
8081      *
8082      * @param info The info to which to add the extra data. Never {@code null}.
8083      * @param extraDataKey A key specifying the type of extra data to add to the info. The
8084      *                     extra data should be added to the {@link Bundle} returned by
8085      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
8086      *                     {@code null}.
8087      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
8088      *                  {@code null} if the service provided no arguments.
8089      *
8090      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
8091      */
8092     public void addExtraDataToAccessibilityNodeInfo(
8093             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
8094             @Nullable Bundle arguments) {
8095     }
8096
8097     /**
8098      * Determine the order in which this view will be drawn relative to its siblings for a11y
8099      *
8100      * @param info The info whose drawing order should be populated
8101      */
8102     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8103         /*
8104          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8105          * drawing order may not be well-defined, and some Views with custom drawing order may
8106          * not be initialized sufficiently to respond properly getChildDrawingOrder.
8107          */
8108         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8109             info.setDrawingOrder(0);
8110             return;
8111         }
8112         int drawingOrderInParent = 1;
8113         // Iterate up the hierarchy if parents are not important for a11y
8114         View viewAtDrawingLevel = this;
8115         final ViewParent parent = getParentForAccessibility();
8116         while (viewAtDrawingLevel != parent) {
8117             final ViewParent currentParent = viewAtDrawingLevel.getParent();
8118             if (!(currentParent instanceof ViewGroup)) {
8119                 // Should only happen for the Decor
8120                 drawingOrderInParent = 0;
8121                 break;
8122             } else {
8123                 final ViewGroup parentGroup = (ViewGroup) currentParent;
8124                 final int childCount = parentGroup.getChildCount();
8125                 if (childCount > 1) {
8126                     List<View> preorderedList = parentGroup.buildOrderedChildList();
8127                     if (preorderedList != null) {
8128                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8129                         for (int i = 0; i < childDrawIndex; i++) {
8130                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8131                         }
8132                     } else {
8133                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8134                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8135                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8136                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
8137                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8138                         if (childDrawIndex != 0) {
8139                             for (int i = 0; i < numChildrenToIterate; i++) {
8140                                 final int otherDrawIndex = (customOrder ?
8141                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
8142                                 if (otherDrawIndex < childDrawIndex) {
8143                                     drawingOrderInParent +=
8144                                             numViewsForAccessibility(parentGroup.getChildAt(i));
8145                                 }
8146                             }
8147                         }
8148                     }
8149                 }
8150             }
8151             viewAtDrawingLevel = (View) currentParent;
8152         }
8153         info.setDrawingOrder(drawingOrderInParent);
8154     }
8155
8156     private static int numViewsForAccessibility(View view) {
8157         if (view != null) {
8158             if (view.includeForAccessibility()) {
8159                 return 1;
8160             } else if (view instanceof ViewGroup) {
8161                 return ((ViewGroup) view).getNumChildrenForAccessibility();
8162             }
8163         }
8164         return 0;
8165     }
8166
8167     private View findLabelForView(View view, int labeledId) {
8168         if (mMatchLabelForPredicate == null) {
8169             mMatchLabelForPredicate = new MatchLabelForPredicate();
8170         }
8171         mMatchLabelForPredicate.mLabeledId = labeledId;
8172         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8173     }
8174
8175     /**
8176      * Computes whether this view is visible to the user. Such a view is
8177      * attached, visible, all its predecessors are visible, it is not clipped
8178      * entirely by its predecessors, and has an alpha greater than zero.
8179      *
8180      * @return Whether the view is visible on the screen.
8181      *
8182      * @hide
8183      */
8184     protected boolean isVisibleToUser() {
8185         return isVisibleToUser(null);
8186     }
8187
8188     /**
8189      * Computes whether the given portion of this view is visible to the user.
8190      * Such a view is attached, visible, all its predecessors are visible,
8191      * has an alpha greater than zero, and the specified portion is not
8192      * clipped entirely by its predecessors.
8193      *
8194      * @param boundInView the portion of the view to test; coordinates should be relative; may be
8195      *                    <code>null</code>, and the entire view will be tested in this case.
8196      *                    When <code>true</code> is returned by the function, the actual visible
8197      *                    region will be stored in this parameter; that is, if boundInView is fully
8198      *                    contained within the view, no modification will be made, otherwise regions
8199      *                    outside of the visible area of the view will be clipped.
8200      *
8201      * @return Whether the specified portion of the view is visible on the screen.
8202      *
8203      * @hide
8204      */
8205     protected boolean isVisibleToUser(Rect boundInView) {
8206         if (mAttachInfo != null) {
8207             // Attached to invisible window means this view is not visible.
8208             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8209                 return false;
8210             }
8211             // An invisible predecessor or one with alpha zero means
8212             // that this view is not visible to the user.
8213             Object current = this;
8214             while (current instanceof View) {
8215                 View view = (View) current;
8216                 // We have attach info so this view is attached and there is no
8217                 // need to check whether we reach to ViewRootImpl on the way up.
8218                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8219                         view.getVisibility() != VISIBLE) {
8220                     return false;
8221                 }
8222                 current = view.mParent;
8223             }
8224             // Check if the view is entirely covered by its predecessors.
8225             Rect visibleRect = mAttachInfo.mTmpInvalRect;
8226             Point offset = mAttachInfo.mPoint;
8227             if (!getGlobalVisibleRect(visibleRect, offset)) {
8228                 return false;
8229             }
8230             // Check if the visible portion intersects the rectangle of interest.
8231             if (boundInView != null) {
8232                 visibleRect.offset(-offset.x, -offset.y);
8233                 return boundInView.intersect(visibleRect);
8234             }
8235             return true;
8236         }
8237         return false;
8238     }
8239
8240     /**
8241      * Returns the delegate for implementing accessibility support via
8242      * composition. For more details see {@link AccessibilityDelegate}.
8243      *
8244      * @return The delegate, or null if none set.
8245      *
8246      * @hide
8247      */
8248     public AccessibilityDelegate getAccessibilityDelegate() {
8249         return mAccessibilityDelegate;
8250     }
8251
8252     /**
8253      * Sets a delegate for implementing accessibility support via composition
8254      * (as opposed to inheritance). For more details, see
8255      * {@link AccessibilityDelegate}.
8256      * <p>
8257      * <strong>Note:</strong> On platform versions prior to
8258      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8259      * views in the {@code android.widget.*} package are called <i>before</i>
8260      * host methods. This prevents certain properties such as class name from
8261      * being modified by overriding
8262      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8263      * as any changes will be overwritten by the host class.
8264      * <p>
8265      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8266      * methods are called <i>after</i> host methods, which all properties to be
8267      * modified without being overwritten by the host class.
8268      *
8269      * @param delegate the object to which accessibility method calls should be
8270      *                 delegated
8271      * @see AccessibilityDelegate
8272      */
8273     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8274         mAccessibilityDelegate = delegate;
8275     }
8276
8277     /**
8278      * Gets the provider for managing a virtual view hierarchy rooted at this View
8279      * and reported to {@link android.accessibilityservice.AccessibilityService}s
8280      * that explore the window content.
8281      * <p>
8282      * If this method returns an instance, this instance is responsible for managing
8283      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8284      * View including the one representing the View itself. Similarly the returned
8285      * instance is responsible for performing accessibility actions on any virtual
8286      * view or the root view itself.
8287      * </p>
8288      * <p>
8289      * If an {@link AccessibilityDelegate} has been specified via calling
8290      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8291      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8292      * is responsible for handling this call.
8293      * </p>
8294      *
8295      * @return The provider.
8296      *
8297      * @see AccessibilityNodeProvider
8298      */
8299     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8300         if (mAccessibilityDelegate != null) {
8301             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8302         } else {
8303             return null;
8304         }
8305     }
8306
8307     /**
8308      * Gets the unique identifier of this view on the screen for accessibility purposes.
8309      *
8310      * @return The view accessibility id.
8311      *
8312      * @hide
8313      */
8314     public int getAccessibilityViewId() {
8315         if (mAccessibilityViewId == NO_ID) {
8316             mAccessibilityViewId = mContext.getNextAccessibilityId();
8317         }
8318         return mAccessibilityViewId;
8319     }
8320
8321     /**
8322      * Gets the unique identifier of the window in which this View reseides.
8323      *
8324      * @return The window accessibility id.
8325      *
8326      * @hide
8327      */
8328     public int getAccessibilityWindowId() {
8329         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8330                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8331     }
8332
8333     /**
8334      * Returns the {@link View}'s content description.
8335      * <p>
8336      * <strong>Note:</strong> Do not override this method, as it will have no
8337      * effect on the content description presented to accessibility services.
8338      * You must call {@link #setContentDescription(CharSequence)} to modify the
8339      * content description.
8340      *
8341      * @return the content description
8342      * @see #setContentDescription(CharSequence)
8343      * @attr ref android.R.styleable#View_contentDescription
8344      */
8345     @ViewDebug.ExportedProperty(category = "accessibility")
8346     public CharSequence getContentDescription() {
8347         return mContentDescription;
8348     }
8349
8350     /**
8351      * Sets the {@link View}'s content description.
8352      * <p>
8353      * A content description briefly describes the view and is primarily used
8354      * for accessibility support to determine how a view should be presented to
8355      * the user. In the case of a view with no textual representation, such as
8356      * {@link android.widget.ImageButton}, a useful content description
8357      * explains what the view does. For example, an image button with a phone
8358      * icon that is used to place a call may use "Call" as its content
8359      * description. An image of a floppy disk that is used to save a file may
8360      * use "Save".
8361      *
8362      * @param contentDescription The content description.
8363      * @see #getContentDescription()
8364      * @attr ref android.R.styleable#View_contentDescription
8365      */
8366     @RemotableViewMethod
8367     public void setContentDescription(CharSequence contentDescription) {
8368         if (mContentDescription == null) {
8369             if (contentDescription == null) {
8370                 return;
8371             }
8372         } else if (mContentDescription.equals(contentDescription)) {
8373             return;
8374         }
8375         mContentDescription = contentDescription;
8376         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8377         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8378             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8379             notifySubtreeAccessibilityStateChangedIfNeeded();
8380         } else {
8381             notifyViewAccessibilityStateChangedIfNeeded(
8382                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8383         }
8384     }
8385
8386     /**
8387      * Sets the id of a view before which this one is visited in accessibility traversal.
8388      * A screen-reader must visit the content of this view before the content of the one
8389      * it precedes. For example, if view B is set to be before view A, then a screen-reader
8390      * will traverse the entire content of B before traversing the entire content of A,
8391      * regardles of what traversal strategy it is using.
8392      * <p>
8393      * Views that do not have specified before/after relationships are traversed in order
8394      * determined by the screen-reader.
8395      * </p>
8396      * <p>
8397      * Setting that this view is before a view that is not important for accessibility
8398      * or if this view is not important for accessibility will have no effect as the
8399      * screen-reader is not aware of unimportant views.
8400      * </p>
8401      *
8402      * @param beforeId The id of a view this one precedes in accessibility traversal.
8403      *
8404      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8405      *
8406      * @see #setImportantForAccessibility(int)
8407      */
8408     @RemotableViewMethod
8409     public void setAccessibilityTraversalBefore(int beforeId) {
8410         if (mAccessibilityTraversalBeforeId == beforeId) {
8411             return;
8412         }
8413         mAccessibilityTraversalBeforeId = beforeId;
8414         notifyViewAccessibilityStateChangedIfNeeded(
8415                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8416     }
8417
8418     /**
8419      * Gets the id of a view before which this one is visited in accessibility traversal.
8420      *
8421      * @return The id of a view this one precedes in accessibility traversal if
8422      *         specified, otherwise {@link #NO_ID}.
8423      *
8424      * @see #setAccessibilityTraversalBefore(int)
8425      */
8426     public int getAccessibilityTraversalBefore() {
8427         return mAccessibilityTraversalBeforeId;
8428     }
8429
8430     /**
8431      * Sets the id of a view after which this one is visited in accessibility traversal.
8432      * A screen-reader must visit the content of the other view before the content of this
8433      * one. For example, if view B is set to be after view A, then a screen-reader
8434      * will traverse the entire content of A before traversing the entire content of B,
8435      * regardles of what traversal strategy it is using.
8436      * <p>
8437      * Views that do not have specified before/after relationships are traversed in order
8438      * determined by the screen-reader.
8439      * </p>
8440      * <p>
8441      * Setting that this view is after a view that is not important for accessibility
8442      * or if this view is not important for accessibility will have no effect as the
8443      * screen-reader is not aware of unimportant views.
8444      * </p>
8445      *
8446      * @param afterId The id of a view this one succedees in accessibility traversal.
8447      *
8448      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8449      *
8450      * @see #setImportantForAccessibility(int)
8451      */
8452     @RemotableViewMethod
8453     public void setAccessibilityTraversalAfter(int afterId) {
8454         if (mAccessibilityTraversalAfterId == afterId) {
8455             return;
8456         }
8457         mAccessibilityTraversalAfterId = afterId;
8458         notifyViewAccessibilityStateChangedIfNeeded(
8459                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8460     }
8461
8462     /**
8463      * Gets the id of a view after which this one is visited in accessibility traversal.
8464      *
8465      * @return The id of a view this one succeedes in accessibility traversal if
8466      *         specified, otherwise {@link #NO_ID}.
8467      *
8468      * @see #setAccessibilityTraversalAfter(int)
8469      */
8470     public int getAccessibilityTraversalAfter() {
8471         return mAccessibilityTraversalAfterId;
8472     }
8473
8474     /**
8475      * Gets the id of a view for which this view serves as a label for
8476      * accessibility purposes.
8477      *
8478      * @return The labeled view id.
8479      */
8480     @ViewDebug.ExportedProperty(category = "accessibility")
8481     public int getLabelFor() {
8482         return mLabelForId;
8483     }
8484
8485     /**
8486      * Sets the id of a view for which this view serves as a label for
8487      * accessibility purposes.
8488      *
8489      * @param id The labeled view id.
8490      */
8491     @RemotableViewMethod
8492     public void setLabelFor(@IdRes int id) {
8493         if (mLabelForId == id) {
8494             return;
8495         }
8496         mLabelForId = id;
8497         if (mLabelForId != View.NO_ID
8498                 && mID == View.NO_ID) {
8499             mID = generateViewId();
8500         }
8501         notifyViewAccessibilityStateChangedIfNeeded(
8502                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8503     }
8504
8505     /**
8506      * Invoked whenever this view loses focus, either by losing window focus or by losing
8507      * focus within its window. This method can be used to clear any state tied to the
8508      * focus. For instance, if a button is held pressed with the trackball and the window
8509      * loses focus, this method can be used to cancel the press.
8510      *
8511      * Subclasses of View overriding this method should always call super.onFocusLost().
8512      *
8513      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8514      * @see #onWindowFocusChanged(boolean)
8515      *
8516      * @hide pending API council approval
8517      */
8518     @CallSuper
8519     protected void onFocusLost() {
8520         resetPressedState();
8521     }
8522
8523     private void resetPressedState() {
8524         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8525             return;
8526         }
8527
8528         if (isPressed()) {
8529             setPressed(false);
8530
8531             if (!mHasPerformedLongPress) {
8532                 removeLongPressCallback();
8533             }
8534         }
8535     }
8536
8537     /**
8538      * Returns true if this view has focus
8539      *
8540      * @return True if this view has focus, false otherwise.
8541      */
8542     @ViewDebug.ExportedProperty(category = "focus")
8543     public boolean isFocused() {
8544         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8545     }
8546
8547     /**
8548      * Find the view in the hierarchy rooted at this view that currently has
8549      * focus.
8550      *
8551      * @return The view that currently has focus, or null if no focused view can
8552      *         be found.
8553      */
8554     public View findFocus() {
8555         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8556     }
8557
8558     /**
8559      * Indicates whether this view is one of the set of scrollable containers in
8560      * its window.
8561      *
8562      * @return whether this view is one of the set of scrollable containers in
8563      * its window
8564      *
8565      * @attr ref android.R.styleable#View_isScrollContainer
8566      */
8567     public boolean isScrollContainer() {
8568         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8569     }
8570
8571     /**
8572      * Change whether this view is one of the set of scrollable containers in
8573      * its window.  This will be used to determine whether the window can
8574      * resize or must pan when a soft input area is open -- scrollable
8575      * containers allow the window to use resize mode since the container
8576      * will appropriately shrink.
8577      *
8578      * @attr ref android.R.styleable#View_isScrollContainer
8579      */
8580     public void setScrollContainer(boolean isScrollContainer) {
8581         if (isScrollContainer) {
8582             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8583                 mAttachInfo.mScrollContainers.add(this);
8584                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8585             }
8586             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8587         } else {
8588             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8589                 mAttachInfo.mScrollContainers.remove(this);
8590             }
8591             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8592         }
8593     }
8594
8595     /**
8596      * Returns the quality of the drawing cache.
8597      *
8598      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8599      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8600      *
8601      * @see #setDrawingCacheQuality(int)
8602      * @see #setDrawingCacheEnabled(boolean)
8603      * @see #isDrawingCacheEnabled()
8604      *
8605      * @attr ref android.R.styleable#View_drawingCacheQuality
8606      */
8607     @DrawingCacheQuality
8608     public int getDrawingCacheQuality() {
8609         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8610     }
8611
8612     /**
8613      * Set the drawing cache quality of this view. This value is used only when the
8614      * drawing cache is enabled
8615      *
8616      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8617      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8618      *
8619      * @see #getDrawingCacheQuality()
8620      * @see #setDrawingCacheEnabled(boolean)
8621      * @see #isDrawingCacheEnabled()
8622      *
8623      * @attr ref android.R.styleable#View_drawingCacheQuality
8624      */
8625     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8626         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8627     }
8628
8629     /**
8630      * Returns whether the screen should remain on, corresponding to the current
8631      * value of {@link #KEEP_SCREEN_ON}.
8632      *
8633      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8634      *
8635      * @see #setKeepScreenOn(boolean)
8636      *
8637      * @attr ref android.R.styleable#View_keepScreenOn
8638      */
8639     public boolean getKeepScreenOn() {
8640         return (mViewFlags & KEEP_SCREEN_ON) != 0;
8641     }
8642
8643     /**
8644      * Controls whether the screen should remain on, modifying the
8645      * value of {@link #KEEP_SCREEN_ON}.
8646      *
8647      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8648      *
8649      * @see #getKeepScreenOn()
8650      *
8651      * @attr ref android.R.styleable#View_keepScreenOn
8652      */
8653     public void setKeepScreenOn(boolean keepScreenOn) {
8654         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8655     }
8656
8657     /**
8658      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8659      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8660      *
8661      * @attr ref android.R.styleable#View_nextFocusLeft
8662      */
8663     public int getNextFocusLeftId() {
8664         return mNextFocusLeftId;
8665     }
8666
8667     /**
8668      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8669      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8670      * decide automatically.
8671      *
8672      * @attr ref android.R.styleable#View_nextFocusLeft
8673      */
8674     public void setNextFocusLeftId(int nextFocusLeftId) {
8675         mNextFocusLeftId = nextFocusLeftId;
8676     }
8677
8678     /**
8679      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8680      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8681      *
8682      * @attr ref android.R.styleable#View_nextFocusRight
8683      */
8684     public int getNextFocusRightId() {
8685         return mNextFocusRightId;
8686     }
8687
8688     /**
8689      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8690      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8691      * decide automatically.
8692      *
8693      * @attr ref android.R.styleable#View_nextFocusRight
8694      */
8695     public void setNextFocusRightId(int nextFocusRightId) {
8696         mNextFocusRightId = nextFocusRightId;
8697     }
8698
8699     /**
8700      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8701      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8702      *
8703      * @attr ref android.R.styleable#View_nextFocusUp
8704      */
8705     public int getNextFocusUpId() {
8706         return mNextFocusUpId;
8707     }
8708
8709     /**
8710      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8711      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8712      * decide automatically.
8713      *
8714      * @attr ref android.R.styleable#View_nextFocusUp
8715      */
8716     public void setNextFocusUpId(int nextFocusUpId) {
8717         mNextFocusUpId = nextFocusUpId;
8718     }
8719
8720     /**
8721      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8722      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8723      *
8724      * @attr ref android.R.styleable#View_nextFocusDown
8725      */
8726     public int getNextFocusDownId() {
8727         return mNextFocusDownId;
8728     }
8729
8730     /**
8731      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8732      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8733      * decide automatically.
8734      *
8735      * @attr ref android.R.styleable#View_nextFocusDown
8736      */
8737     public void setNextFocusDownId(int nextFocusDownId) {
8738         mNextFocusDownId = nextFocusDownId;
8739     }
8740
8741     /**
8742      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8743      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8744      *
8745      * @attr ref android.R.styleable#View_nextFocusForward
8746      */
8747     public int getNextFocusForwardId() {
8748         return mNextFocusForwardId;
8749     }
8750
8751     /**
8752      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8753      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8754      * decide automatically.
8755      *
8756      * @attr ref android.R.styleable#View_nextFocusForward
8757      */
8758     public void setNextFocusForwardId(int nextFocusForwardId) {
8759         mNextFocusForwardId = nextFocusForwardId;
8760     }
8761
8762     /**
8763      * Gets the id of the root of the next keyboard navigation cluster.
8764      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8765      * decide automatically.
8766      *
8767      * @attr ref android.R.styleable#View_nextClusterForward
8768      */
8769     public int getNextClusterForwardId() {
8770         return mNextClusterForwardId;
8771     }
8772
8773     /**
8774      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8775      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8776      * decide automatically.
8777      *
8778      * @attr ref android.R.styleable#View_nextClusterForward
8779      */
8780     public void setNextClusterForwardId(int nextClusterForwardId) {
8781         mNextClusterForwardId = nextClusterForwardId;
8782     }
8783
8784     /**
8785      * Returns the visibility of this view and all of its ancestors
8786      *
8787      * @return True if this view and all of its ancestors are {@link #VISIBLE}
8788      */
8789     public boolean isShown() {
8790         View current = this;
8791         //noinspection ConstantConditions
8792         do {
8793             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8794                 return false;
8795             }
8796             ViewParent parent = current.mParent;
8797             if (parent == null) {
8798                 return false; // We are not attached to the view root
8799             }
8800             if (!(parent instanceof View)) {
8801                 return true;
8802             }
8803             current = (View) parent;
8804         } while (current != null);
8805
8806         return false;
8807     }
8808
8809     /**
8810      * Called by the view hierarchy when the content insets for a window have
8811      * changed, to allow it to adjust its content to fit within those windows.
8812      * The content insets tell you the space that the status bar, input method,
8813      * and other system windows infringe on the application's window.
8814      *
8815      * <p>You do not normally need to deal with this function, since the default
8816      * window decoration given to applications takes care of applying it to the
8817      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8818      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8819      * and your content can be placed under those system elements.  You can then
8820      * use this method within your view hierarchy if you have parts of your UI
8821      * which you would like to ensure are not being covered.
8822      *
8823      * <p>The default implementation of this method simply applies the content
8824      * insets to the view's padding, consuming that content (modifying the
8825      * insets to be 0), and returning true.  This behavior is off by default, but can
8826      * be enabled through {@link #setFitsSystemWindows(boolean)}.
8827      *
8828      * <p>This function's traversal down the hierarchy is depth-first.  The same content
8829      * insets object is propagated down the hierarchy, so any changes made to it will
8830      * be seen by all following views (including potentially ones above in
8831      * the hierarchy since this is a depth-first traversal).  The first view
8832      * that returns true will abort the entire traversal.
8833      *
8834      * <p>The default implementation works well for a situation where it is
8835      * used with a container that covers the entire window, allowing it to
8836      * apply the appropriate insets to its content on all edges.  If you need
8837      * a more complicated layout (such as two different views fitting system
8838      * windows, one on the top of the window, and one on the bottom),
8839      * you can override the method and handle the insets however you would like.
8840      * Note that the insets provided by the framework are always relative to the
8841      * far edges of the window, not accounting for the location of the called view
8842      * within that window.  (In fact when this method is called you do not yet know
8843      * where the layout will place the view, as it is done before layout happens.)
8844      *
8845      * <p>Note: unlike many View methods, there is no dispatch phase to this
8846      * call.  If you are overriding it in a ViewGroup and want to allow the
8847      * call to continue to your children, you must be sure to call the super
8848      * implementation.
8849      *
8850      * <p>Here is a sample layout that makes use of fitting system windows
8851      * to have controls for a video view placed inside of the window decorations
8852      * that it hides and shows.  This can be used with code like the second
8853      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8854      *
8855      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8856      *
8857      * @param insets Current content insets of the window.  Prior to
8858      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8859      * the insets or else you and Android will be unhappy.
8860      *
8861      * @return {@code true} if this view applied the insets and it should not
8862      * continue propagating further down the hierarchy, {@code false} otherwise.
8863      * @see #getFitsSystemWindows()
8864      * @see #setFitsSystemWindows(boolean)
8865      * @see #setSystemUiVisibility(int)
8866      *
8867      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8868      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8869      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8870      * to implement handling their own insets.
8871      */
8872     @Deprecated
8873     protected boolean fitSystemWindows(Rect insets) {
8874         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8875             if (insets == null) {
8876                 // Null insets by definition have already been consumed.
8877                 // This call cannot apply insets since there are none to apply,
8878                 // so return false.
8879                 return false;
8880             }
8881             // If we're not in the process of dispatching the newer apply insets call,
8882             // that means we're not in the compatibility path. Dispatch into the newer
8883             // apply insets path and take things from there.
8884             try {
8885                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8886                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8887             } finally {
8888                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8889             }
8890         } else {
8891             // We're being called from the newer apply insets path.
8892             // Perform the standard fallback behavior.
8893             return fitSystemWindowsInt(insets);
8894         }
8895     }
8896
8897     private boolean fitSystemWindowsInt(Rect insets) {
8898         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8899             mUserPaddingStart = UNDEFINED_PADDING;
8900             mUserPaddingEnd = UNDEFINED_PADDING;
8901             Rect localInsets = sThreadLocal.get();
8902             if (localInsets == null) {
8903                 localInsets = new Rect();
8904                 sThreadLocal.set(localInsets);
8905             }
8906             boolean res = computeFitSystemWindows(insets, localInsets);
8907             mUserPaddingLeftInitial = localInsets.left;
8908             mUserPaddingRightInitial = localInsets.right;
8909             internalSetPadding(localInsets.left, localInsets.top,
8910                     localInsets.right, localInsets.bottom);
8911             return res;
8912         }
8913         return false;
8914     }
8915
8916     /**
8917      * Called when the view should apply {@link WindowInsets} according to its internal policy.
8918      *
8919      * <p>This method should be overridden by views that wish to apply a policy different from or
8920      * in addition to the default behavior. Clients that wish to force a view subtree
8921      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8922      *
8923      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8924      * it will be called during dispatch instead of this method. The listener may optionally
8925      * call this method from its own implementation if it wishes to apply the view's default
8926      * insets policy in addition to its own.</p>
8927      *
8928      * <p>Implementations of this method should either return the insets parameter unchanged
8929      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8930      * that this view applied itself. This allows new inset types added in future platform
8931      * versions to pass through existing implementations unchanged without being erroneously
8932      * consumed.</p>
8933      *
8934      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8935      * property is set then the view will consume the system window insets and apply them
8936      * as padding for the view.</p>
8937      *
8938      * @param insets Insets to apply
8939      * @return The supplied insets with any applied insets consumed
8940      */
8941     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8942         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8943             // We weren't called from within a direct call to fitSystemWindows,
8944             // call into it as a fallback in case we're in a class that overrides it
8945             // and has logic to perform.
8946             if (fitSystemWindows(insets.getSystemWindowInsets())) {
8947                 return insets.consumeSystemWindowInsets();
8948             }
8949         } else {
8950             // We were called from within a direct call to fitSystemWindows.
8951             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8952                 return insets.consumeSystemWindowInsets();
8953             }
8954         }
8955         return insets;
8956     }
8957
8958     /**
8959      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8960      * window insets to this view. The listener's
8961      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8962      * method will be called instead of the view's
8963      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8964      *
8965      * @param listener Listener to set
8966      *
8967      * @see #onApplyWindowInsets(WindowInsets)
8968      */
8969     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8970         getListenerInfo().mOnApplyWindowInsetsListener = listener;
8971     }
8972
8973     /**
8974      * Request to apply the given window insets to this view or another view in its subtree.
8975      *
8976      * <p>This method should be called by clients wishing to apply insets corresponding to areas
8977      * obscured by window decorations or overlays. This can include the status and navigation bars,
8978      * action bars, input methods and more. New inset categories may be added in the future.
8979      * The method returns the insets provided minus any that were applied by this view or its
8980      * children.</p>
8981      *
8982      * <p>Clients wishing to provide custom behavior should override the
8983      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8984      * {@link OnApplyWindowInsetsListener} via the
8985      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8986      * method.</p>
8987      *
8988      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8989      * </p>
8990      *
8991      * @param insets Insets to apply
8992      * @return The provided insets minus the insets that were consumed
8993      */
8994     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8995         try {
8996             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8997             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8998                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8999             } else {
9000                 return onApplyWindowInsets(insets);
9001             }
9002         } finally {
9003             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
9004         }
9005     }
9006
9007     /**
9008      * Compute the view's coordinate within the surface.
9009      *
9010      * <p>Computes the coordinates of this view in its surface. The argument
9011      * must be an array of two integers. After the method returns, the array
9012      * contains the x and y location in that order.</p>
9013      * @hide
9014      * @param location an array of two integers in which to hold the coordinates
9015      */
9016     public void getLocationInSurface(@Size(2) int[] location) {
9017         getLocationInWindow(location);
9018         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
9019             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
9020             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
9021         }
9022     }
9023
9024     /**
9025      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
9026      * only available if the view is attached.
9027      *
9028      * @return WindowInsets from the top of the view hierarchy or null if View is detached
9029      */
9030     public WindowInsets getRootWindowInsets() {
9031         if (mAttachInfo != null) {
9032             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
9033         }
9034         return null;
9035     }
9036
9037     /**
9038      * @hide Compute the insets that should be consumed by this view and the ones
9039      * that should propagate to those under it.
9040      */
9041     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
9042         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9043                 || mAttachInfo == null
9044                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
9045                         && !mAttachInfo.mOverscanRequested)) {
9046             outLocalInsets.set(inoutInsets);
9047             inoutInsets.set(0, 0, 0, 0);
9048             return true;
9049         } else {
9050             // The application wants to take care of fitting system window for
9051             // the content...  however we still need to take care of any overscan here.
9052             final Rect overscan = mAttachInfo.mOverscanInsets;
9053             outLocalInsets.set(overscan);
9054             inoutInsets.left -= overscan.left;
9055             inoutInsets.top -= overscan.top;
9056             inoutInsets.right -= overscan.right;
9057             inoutInsets.bottom -= overscan.bottom;
9058             return false;
9059         }
9060     }
9061
9062     /**
9063      * Compute insets that should be consumed by this view and the ones that should propagate
9064      * to those under it.
9065      *
9066      * @param in Insets currently being processed by this View, likely received as a parameter
9067      *           to {@link #onApplyWindowInsets(WindowInsets)}.
9068      * @param outLocalInsets A Rect that will receive the insets that should be consumed
9069      *                       by this view
9070      * @return Insets that should be passed along to views under this one
9071      */
9072     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
9073         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9074                 || mAttachInfo == null
9075                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
9076             outLocalInsets.set(in.getSystemWindowInsets());
9077             return in.consumeSystemWindowInsets();
9078         } else {
9079             outLocalInsets.set(0, 0, 0, 0);
9080             return in;
9081         }
9082     }
9083
9084     /**
9085      * Sets whether or not this view should account for system screen decorations
9086      * such as the status bar and inset its content; that is, controlling whether
9087      * the default implementation of {@link #fitSystemWindows(Rect)} will be
9088      * executed.  See that method for more details.
9089      *
9090      * <p>Note that if you are providing your own implementation of
9091      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
9092      * flag to true -- your implementation will be overriding the default
9093      * implementation that checks this flag.
9094      *
9095      * @param fitSystemWindows If true, then the default implementation of
9096      * {@link #fitSystemWindows(Rect)} will be executed.
9097      *
9098      * @attr ref android.R.styleable#View_fitsSystemWindows
9099      * @see #getFitsSystemWindows()
9100      * @see #fitSystemWindows(Rect)
9101      * @see #setSystemUiVisibility(int)
9102      */
9103     public void setFitsSystemWindows(boolean fitSystemWindows) {
9104         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9105     }
9106
9107     /**
9108      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9109      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9110      * will be executed.
9111      *
9112      * @return {@code true} if the default implementation of
9113      * {@link #fitSystemWindows(Rect)} will be executed.
9114      *
9115      * @attr ref android.R.styleable#View_fitsSystemWindows
9116      * @see #setFitsSystemWindows(boolean)
9117      * @see #fitSystemWindows(Rect)
9118      * @see #setSystemUiVisibility(int)
9119      */
9120     @ViewDebug.ExportedProperty
9121     public boolean getFitsSystemWindows() {
9122         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9123     }
9124
9125     /** @hide */
9126     public boolean fitsSystemWindows() {
9127         return getFitsSystemWindows();
9128     }
9129
9130     /**
9131      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9132      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9133      */
9134     @Deprecated
9135     public void requestFitSystemWindows() {
9136         if (mParent != null) {
9137             mParent.requestFitSystemWindows();
9138         }
9139     }
9140
9141     /**
9142      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9143      */
9144     public void requestApplyInsets() {
9145         requestFitSystemWindows();
9146     }
9147
9148     /**
9149      * For use by PhoneWindow to make its own system window fitting optional.
9150      * @hide
9151      */
9152     public void makeOptionalFitsSystemWindows() {
9153         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9154     }
9155
9156     /**
9157      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9158      * treat them as such.
9159      * @hide
9160      */
9161     public void getOutsets(Rect outOutsetRect) {
9162         if (mAttachInfo != null) {
9163             outOutsetRect.set(mAttachInfo.mOutsets);
9164         } else {
9165             outOutsetRect.setEmpty();
9166         }
9167     }
9168
9169     /**
9170      * Returns the visibility status for this view.
9171      *
9172      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9173      * @attr ref android.R.styleable#View_visibility
9174      */
9175     @ViewDebug.ExportedProperty(mapping = {
9176         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9177         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9178         @ViewDebug.IntToString(from = GONE,      to = "GONE")
9179     })
9180     @Visibility
9181     public int getVisibility() {
9182         return mViewFlags & VISIBILITY_MASK;
9183     }
9184
9185     /**
9186      * Set the visibility state of this view.
9187      *
9188      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9189      * @attr ref android.R.styleable#View_visibility
9190      */
9191     @RemotableViewMethod
9192     public void setVisibility(@Visibility int visibility) {
9193         setFlags(visibility, VISIBILITY_MASK);
9194     }
9195
9196     /**
9197      * Returns the enabled status for this view. The interpretation of the
9198      * enabled state varies by subclass.
9199      *
9200      * @return True if this view is enabled, false otherwise.
9201      */
9202     @ViewDebug.ExportedProperty
9203     public boolean isEnabled() {
9204         return (mViewFlags & ENABLED_MASK) == ENABLED;
9205     }
9206
9207     /**
9208      * Set the enabled state of this view. The interpretation of the enabled
9209      * state varies by subclass.
9210      *
9211      * @param enabled True if this view is enabled, false otherwise.
9212      */
9213     @RemotableViewMethod
9214     public void setEnabled(boolean enabled) {
9215         if (enabled == isEnabled()) return;
9216
9217         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9218
9219         /*
9220          * The View most likely has to change its appearance, so refresh
9221          * the drawable state.
9222          */
9223         refreshDrawableState();
9224
9225         // Invalidate too, since the default behavior for views is to be
9226         // be drawn at 50% alpha rather than to change the drawable.
9227         invalidate(true);
9228
9229         if (!enabled) {
9230             cancelPendingInputEvents();
9231         }
9232     }
9233
9234     /**
9235      * Set whether this view can receive the focus.
9236      * <p>
9237      * Setting this to false will also ensure that this view is not focusable
9238      * in touch mode.
9239      *
9240      * @param focusable If true, this view can receive the focus.
9241      *
9242      * @see #setFocusableInTouchMode(boolean)
9243      * @see #setFocusable(int)
9244      * @attr ref android.R.styleable#View_focusable
9245      */
9246     public void setFocusable(boolean focusable) {
9247         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9248     }
9249
9250     /**
9251      * Sets whether this view can receive focus.
9252      * <p>
9253      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9254      * automatically based on the view's interactivity. This is the default.
9255      * <p>
9256      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9257      * in touch mode.
9258      *
9259      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9260      *                  or {@link #FOCUSABLE_AUTO}.
9261      * @see #setFocusableInTouchMode(boolean)
9262      * @attr ref android.R.styleable#View_focusable
9263      */
9264     public void setFocusable(@Focusable int focusable) {
9265         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9266             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9267         }
9268         setFlags(focusable, FOCUSABLE_MASK);
9269     }
9270
9271     /**
9272      * Set whether this view can receive focus while in touch mode.
9273      *
9274      * Setting this to true will also ensure that this view is focusable.
9275      *
9276      * @param focusableInTouchMode If true, this view can receive the focus while
9277      *   in touch mode.
9278      *
9279      * @see #setFocusable(boolean)
9280      * @attr ref android.R.styleable#View_focusableInTouchMode
9281      */
9282     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9283         // Focusable in touch mode should always be set before the focusable flag
9284         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9285         // which, in touch mode, will not successfully request focus on this view
9286         // because the focusable in touch mode flag is not set
9287         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9288
9289         // Clear FOCUSABLE_AUTO if set.
9290         if (focusableInTouchMode) {
9291             // Clears FOCUSABLE_AUTO if set.
9292             setFlags(FOCUSABLE, FOCUSABLE_MASK);
9293         }
9294     }
9295
9296     /**
9297      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
9298      * to autofill the view with the user's data.
9299      *
9300      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
9301      * For example, if the application accepts either an username or email address to identify
9302      * an user.
9303      *
9304      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
9305      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
9306      * constants such as:
9307      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
9308      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
9309      * {@link #AUTOFILL_HINT_NAME},
9310      * {@link #AUTOFILL_HINT_PHONE},
9311      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
9312      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
9313      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
9314      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
9315      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
9316      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
9317      *
9318      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9319      * @attr ref android.R.styleable#View_autofillHints
9320      */
9321     public void setAutofillHints(@Nullable String... autofillHints) {
9322         if (autofillHints == null || autofillHints.length == 0) {
9323             mAutofillHints = null;
9324         } else {
9325             mAutofillHints = autofillHints;
9326         }
9327     }
9328
9329     /**
9330      * @hide
9331      */
9332     @TestApi
9333     public void setAutofilled(boolean isAutofilled) {
9334         boolean wasChanged = isAutofilled != isAutofilled();
9335
9336         if (wasChanged) {
9337             if (isAutofilled) {
9338                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9339             } else {
9340                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9341             }
9342
9343             invalidate();
9344         }
9345     }
9346
9347     /**
9348      * Set whether this view should have sound effects enabled for events such as
9349      * clicking and touching.
9350      *
9351      * <p>You may wish to disable sound effects for a view if you already play sounds,
9352      * for instance, a dial key that plays dtmf tones.
9353      *
9354      * @param soundEffectsEnabled whether sound effects are enabled for this view.
9355      * @see #isSoundEffectsEnabled()
9356      * @see #playSoundEffect(int)
9357      * @attr ref android.R.styleable#View_soundEffectsEnabled
9358      */
9359     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9360         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9361     }
9362
9363     /**
9364      * @return whether this view should have sound effects enabled for events such as
9365      *     clicking and touching.
9366      *
9367      * @see #setSoundEffectsEnabled(boolean)
9368      * @see #playSoundEffect(int)
9369      * @attr ref android.R.styleable#View_soundEffectsEnabled
9370      */
9371     @ViewDebug.ExportedProperty
9372     public boolean isSoundEffectsEnabled() {
9373         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9374     }
9375
9376     /**
9377      * Set whether this view should have haptic feedback for events such as
9378      * long presses.
9379      *
9380      * <p>You may wish to disable haptic feedback if your view already controls
9381      * its own haptic feedback.
9382      *
9383      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9384      * @see #isHapticFeedbackEnabled()
9385      * @see #performHapticFeedback(int)
9386      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9387      */
9388     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9389         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9390     }
9391
9392     /**
9393      * @return whether this view should have haptic feedback enabled for events
9394      * long presses.
9395      *
9396      * @see #setHapticFeedbackEnabled(boolean)
9397      * @see #performHapticFeedback(int)
9398      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9399      */
9400     @ViewDebug.ExportedProperty
9401     public boolean isHapticFeedbackEnabled() {
9402         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9403     }
9404
9405     /**
9406      * Returns the layout direction for this view.
9407      *
9408      * @return One of {@link #LAYOUT_DIRECTION_LTR},
9409      *   {@link #LAYOUT_DIRECTION_RTL},
9410      *   {@link #LAYOUT_DIRECTION_INHERIT} or
9411      *   {@link #LAYOUT_DIRECTION_LOCALE}.
9412      *
9413      * @attr ref android.R.styleable#View_layoutDirection
9414      *
9415      * @hide
9416      */
9417     @ViewDebug.ExportedProperty(category = "layout", mapping = {
9418         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9419         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9420         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9421         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9422     })
9423     @LayoutDir
9424     public int getRawLayoutDirection() {
9425         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9426     }
9427
9428     /**
9429      * Set the layout direction for this view. This will propagate a reset of layout direction
9430      * resolution to the view's children and resolve layout direction for this view.
9431      *
9432      * @param layoutDirection the layout direction to set. Should be one of:
9433      *
9434      * {@link #LAYOUT_DIRECTION_LTR},
9435      * {@link #LAYOUT_DIRECTION_RTL},
9436      * {@link #LAYOUT_DIRECTION_INHERIT},
9437      * {@link #LAYOUT_DIRECTION_LOCALE}.
9438      *
9439      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9440      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9441      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9442      *
9443      * @attr ref android.R.styleable#View_layoutDirection
9444      */
9445     @RemotableViewMethod
9446     public void setLayoutDirection(@LayoutDir int layoutDirection) {
9447         if (getRawLayoutDirection() != layoutDirection) {
9448             // Reset the current layout direction and the resolved one
9449             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9450             resetRtlProperties();
9451             // Set the new layout direction (filtered)
9452             mPrivateFlags2 |=
9453                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9454             // We need to resolve all RTL properties as they all depend on layout direction
9455             resolveRtlPropertiesIfNeeded();
9456             requestLayout();
9457             invalidate(true);
9458         }
9459     }
9460
9461     /**
9462      * Returns the resolved layout direction for this view.
9463      *
9464      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9465      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9466      *
9467      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9468      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9469      *
9470      * @attr ref android.R.styleable#View_layoutDirection
9471      */
9472     @ViewDebug.ExportedProperty(category = "layout", mapping = {
9473         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9474         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9475     })
9476     @ResolvedLayoutDir
9477     public int getLayoutDirection() {
9478         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9479         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9480             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9481             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9482         }
9483         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9484                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9485     }
9486
9487     /**
9488      * Indicates whether or not this view's layout is right-to-left. This is resolved from
9489      * layout attribute and/or the inherited value from the parent
9490      *
9491      * @return true if the layout is right-to-left.
9492      *
9493      * @hide
9494      */
9495     @ViewDebug.ExportedProperty(category = "layout")
9496     public boolean isLayoutRtl() {
9497         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9498     }
9499
9500     /**
9501      * Indicates whether the view is currently tracking transient state that the
9502      * app should not need to concern itself with saving and restoring, but that
9503      * the framework should take special note to preserve when possible.
9504      *
9505      * <p>A view with transient state cannot be trivially rebound from an external
9506      * data source, such as an adapter binding item views in a list. This may be
9507      * because the view is performing an animation, tracking user selection
9508      * of content, or similar.</p>
9509      *
9510      * @return true if the view has transient state
9511      */
9512     @ViewDebug.ExportedProperty(category = "layout")
9513     public boolean hasTransientState() {
9514         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9515     }
9516
9517     /**
9518      * Set whether this view is currently tracking transient state that the
9519      * framework should attempt to preserve when possible. This flag is reference counted,
9520      * so every call to setHasTransientState(true) should be paired with a later call
9521      * to setHasTransientState(false).
9522      *
9523      * <p>A view with transient state cannot be trivially rebound from an external
9524      * data source, such as an adapter binding item views in a list. This may be
9525      * because the view is performing an animation, tracking user selection
9526      * of content, or similar.</p>
9527      *
9528      * @param hasTransientState true if this view has transient state
9529      */
9530     public void setHasTransientState(boolean hasTransientState) {
9531         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9532                 mTransientStateCount - 1;
9533         if (mTransientStateCount < 0) {
9534             mTransientStateCount = 0;
9535             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9536                     "unmatched pair of setHasTransientState calls");
9537         } else if ((hasTransientState && mTransientStateCount == 1) ||
9538                 (!hasTransientState && mTransientStateCount == 0)) {
9539             // update flag if we've just incremented up from 0 or decremented down to 0
9540             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9541                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9542             if (mParent != null) {
9543                 try {
9544                     mParent.childHasTransientStateChanged(this, hasTransientState);
9545                 } catch (AbstractMethodError e) {
9546                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9547                             " does not fully implement ViewParent", e);
9548                 }
9549             }
9550         }
9551     }
9552
9553     /**
9554      * Returns true if this view is currently attached to a window.
9555      */
9556     public boolean isAttachedToWindow() {
9557         return mAttachInfo != null;
9558     }
9559
9560     /**
9561      * Returns true if this view has been through at least one layout since it
9562      * was last attached to or detached from a window.
9563      */
9564     public boolean isLaidOut() {
9565         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9566     }
9567
9568     /**
9569      * If this view doesn't do any drawing on its own, set this flag to
9570      * allow further optimizations. By default, this flag is not set on
9571      * View, but could be set on some View subclasses such as ViewGroup.
9572      *
9573      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9574      * you should clear this flag.
9575      *
9576      * @param willNotDraw whether or not this View draw on its own
9577      */
9578     public void setWillNotDraw(boolean willNotDraw) {
9579         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9580     }
9581
9582     /**
9583      * Returns whether or not this View draws on its own.
9584      *
9585      * @return true if this view has nothing to draw, false otherwise
9586      */
9587     @ViewDebug.ExportedProperty(category = "drawing")
9588     public boolean willNotDraw() {
9589         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9590     }
9591
9592     /**
9593      * When a View's drawing cache is enabled, drawing is redirected to an
9594      * offscreen bitmap. Some views, like an ImageView, must be able to
9595      * bypass this mechanism if they already draw a single bitmap, to avoid
9596      * unnecessary usage of the memory.
9597      *
9598      * @param willNotCacheDrawing true if this view does not cache its
9599      *        drawing, false otherwise
9600      */
9601     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9602         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9603     }
9604
9605     /**
9606      * Returns whether or not this View can cache its drawing or not.
9607      *
9608      * @return true if this view does not cache its drawing, false otherwise
9609      */
9610     @ViewDebug.ExportedProperty(category = "drawing")
9611     public boolean willNotCacheDrawing() {
9612         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9613     }
9614
9615     /**
9616      * Indicates whether this view reacts to click events or not.
9617      *
9618      * @return true if the view is clickable, false otherwise
9619      *
9620      * @see #setClickable(boolean)
9621      * @attr ref android.R.styleable#View_clickable
9622      */
9623     @ViewDebug.ExportedProperty
9624     public boolean isClickable() {
9625         return (mViewFlags & CLICKABLE) == CLICKABLE;
9626     }
9627
9628     /**
9629      * Enables or disables click events for this view. When a view
9630      * is clickable it will change its state to "pressed" on every click.
9631      * Subclasses should set the view clickable to visually react to
9632      * user's clicks.
9633      *
9634      * @param clickable true to make the view clickable, false otherwise
9635      *
9636      * @see #isClickable()
9637      * @attr ref android.R.styleable#View_clickable
9638      */
9639     public void setClickable(boolean clickable) {
9640         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9641     }
9642
9643     /**
9644      * Indicates whether this view reacts to long click events or not.
9645      *
9646      * @return true if the view is long clickable, false otherwise
9647      *
9648      * @see #setLongClickable(boolean)
9649      * @attr ref android.R.styleable#View_longClickable
9650      */
9651     public boolean isLongClickable() {
9652         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9653     }
9654
9655     /**
9656      * Enables or disables long click events for this view. When a view is long
9657      * clickable it reacts to the user holding down the button for a longer
9658      * duration than a tap. This event can either launch the listener or a
9659      * context menu.
9660      *
9661      * @param longClickable true to make the view long clickable, false otherwise
9662      * @see #isLongClickable()
9663      * @attr ref android.R.styleable#View_longClickable
9664      */
9665     public void setLongClickable(boolean longClickable) {
9666         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9667     }
9668
9669     /**
9670      * Indicates whether this view reacts to context clicks or not.
9671      *
9672      * @return true if the view is context clickable, false otherwise
9673      * @see #setContextClickable(boolean)
9674      * @attr ref android.R.styleable#View_contextClickable
9675      */
9676     public boolean isContextClickable() {
9677         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9678     }
9679
9680     /**
9681      * Enables or disables context clicking for this view. This event can launch the listener.
9682      *
9683      * @param contextClickable true to make the view react to a context click, false otherwise
9684      * @see #isContextClickable()
9685      * @attr ref android.R.styleable#View_contextClickable
9686      */
9687     public void setContextClickable(boolean contextClickable) {
9688         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9689     }
9690
9691     /**
9692      * Sets the pressed state for this view and provides a touch coordinate for
9693      * animation hinting.
9694      *
9695      * @param pressed Pass true to set the View's internal state to "pressed",
9696      *            or false to reverts the View's internal state from a
9697      *            previously set "pressed" state.
9698      * @param x The x coordinate of the touch that caused the press
9699      * @param y The y coordinate of the touch that caused the press
9700      */
9701     private void setPressed(boolean pressed, float x, float y) {
9702         if (pressed) {
9703             drawableHotspotChanged(x, y);
9704         }
9705
9706         setPressed(pressed);
9707     }
9708
9709     /**
9710      * Sets the pressed state for this view.
9711      *
9712      * @see #isClickable()
9713      * @see #setClickable(boolean)
9714      *
9715      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9716      *        the View's internal state from a previously set "pressed" state.
9717      */
9718     public void setPressed(boolean pressed) {
9719         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9720
9721         if (pressed) {
9722             mPrivateFlags |= PFLAG_PRESSED;
9723         } else {
9724             mPrivateFlags &= ~PFLAG_PRESSED;
9725         }
9726
9727         if (needsRefresh) {
9728             refreshDrawableState();
9729         }
9730         dispatchSetPressed(pressed);
9731     }
9732
9733     /**
9734      * Dispatch setPressed to all of this View's children.
9735      *
9736      * @see #setPressed(boolean)
9737      *
9738      * @param pressed The new pressed state
9739      */
9740     protected void dispatchSetPressed(boolean pressed) {
9741     }
9742
9743     /**
9744      * Indicates whether the view is currently in pressed state. Unless
9745      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9746      * the pressed state.
9747      *
9748      * @see #setPressed(boolean)
9749      * @see #isClickable()
9750      * @see #setClickable(boolean)
9751      *
9752      * @return true if the view is currently pressed, false otherwise
9753      */
9754     @ViewDebug.ExportedProperty
9755     public boolean isPressed() {
9756         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9757     }
9758
9759     /**
9760      * @hide
9761      * Indicates whether this view will participate in data collection through
9762      * {@link ViewStructure}.  If true, it will not provide any data
9763      * for itself or its children.  If false, the normal data collection will be allowed.
9764      *
9765      * @return Returns false if assist data collection is not blocked, else true.
9766      *
9767      * @see #setAssistBlocked(boolean)
9768      * @attr ref android.R.styleable#View_assistBlocked
9769      */
9770     public boolean isAssistBlocked() {
9771         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9772     }
9773
9774     /**
9775      * @hide
9776      * Controls whether assist data collection from this view and its children is enabled
9777      * (that is, whether {@link #onProvideStructure} and
9778      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9779      * allowing normal assist collection.  Setting this to false will disable assist collection.
9780      *
9781      * @param enabled Set to true to <em>disable</em> assist data collection, or false
9782      * (the default) to allow it.
9783      *
9784      * @see #isAssistBlocked()
9785      * @see #onProvideStructure
9786      * @see #onProvideVirtualStructure
9787      * @attr ref android.R.styleable#View_assistBlocked
9788      */
9789     public void setAssistBlocked(boolean enabled) {
9790         if (enabled) {
9791             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9792         } else {
9793             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9794         }
9795     }
9796
9797     /**
9798      * Indicates whether this view will save its state (that is,
9799      * whether its {@link #onSaveInstanceState} method will be called).
9800      *
9801      * @return Returns true if the view state saving is enabled, else false.
9802      *
9803      * @see #setSaveEnabled(boolean)
9804      * @attr ref android.R.styleable#View_saveEnabled
9805      */
9806     public boolean isSaveEnabled() {
9807         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9808     }
9809
9810     /**
9811      * Controls whether the saving of this view's state is
9812      * enabled (that is, whether its {@link #onSaveInstanceState} method
9813      * will be called).  Note that even if freezing is enabled, the
9814      * view still must have an id assigned to it (via {@link #setId(int)})
9815      * for its state to be saved.  This flag can only disable the
9816      * saving of this view; any child views may still have their state saved.
9817      *
9818      * @param enabled Set to false to <em>disable</em> state saving, or true
9819      * (the default) to allow it.
9820      *
9821      * @see #isSaveEnabled()
9822      * @see #setId(int)
9823      * @see #onSaveInstanceState()
9824      * @attr ref android.R.styleable#View_saveEnabled
9825      */
9826     public void setSaveEnabled(boolean enabled) {
9827         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9828     }
9829
9830     /**
9831      * Gets whether the framework should discard touches when the view's
9832      * window is obscured by another visible window.
9833      * Refer to the {@link View} security documentation for more details.
9834      *
9835      * @return True if touch filtering is enabled.
9836      *
9837      * @see #setFilterTouchesWhenObscured(boolean)
9838      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9839      */
9840     @ViewDebug.ExportedProperty
9841     public boolean getFilterTouchesWhenObscured() {
9842         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9843     }
9844
9845     /**
9846      * Sets whether the framework should discard touches when the view's
9847      * window is obscured by another visible window.
9848      * Refer to the {@link View} security documentation for more details.
9849      *
9850      * @param enabled True if touch filtering should be enabled.
9851      *
9852      * @see #getFilterTouchesWhenObscured
9853      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9854      */
9855     public void setFilterTouchesWhenObscured(boolean enabled) {
9856         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9857                 FILTER_TOUCHES_WHEN_OBSCURED);
9858     }
9859
9860     /**
9861      * Indicates whether the entire hierarchy under this view will save its
9862      * state when a state saving traversal occurs from its parent.  The default
9863      * is true; if false, these views will not be saved unless
9864      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9865      *
9866      * @return Returns true if the view state saving from parent is enabled, else false.
9867      *
9868      * @see #setSaveFromParentEnabled(boolean)
9869      */
9870     public boolean isSaveFromParentEnabled() {
9871         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9872     }
9873
9874     /**
9875      * Controls whether the entire hierarchy under this view will save its
9876      * state when a state saving traversal occurs from its parent.  The default
9877      * is true; if false, these views will not be saved unless
9878      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9879      *
9880      * @param enabled Set to false to <em>disable</em> state saving, or true
9881      * (the default) to allow it.
9882      *
9883      * @see #isSaveFromParentEnabled()
9884      * @see #setId(int)
9885      * @see #onSaveInstanceState()
9886      */
9887     public void setSaveFromParentEnabled(boolean enabled) {
9888         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9889     }
9890
9891
9892     /**
9893      * Returns whether this View is currently able to take focus.
9894      *
9895      * @return True if this view can take focus, or false otherwise.
9896      */
9897     @ViewDebug.ExportedProperty(category = "focus")
9898     public final boolean isFocusable() {
9899         return FOCUSABLE == (mViewFlags & FOCUSABLE);
9900     }
9901
9902     /**
9903      * Returns the focusable setting for this view.
9904      *
9905      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9906      * @attr ref android.R.styleable#View_focusable
9907      */
9908     @ViewDebug.ExportedProperty(mapping = {
9909             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9910             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9911             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9912             }, category = "focus")
9913     @Focusable
9914     public int getFocusable() {
9915         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9916     }
9917
9918     /**
9919      * When a view is focusable, it may not want to take focus when in touch mode.
9920      * For example, a button would like focus when the user is navigating via a D-pad
9921      * so that the user can click on it, but once the user starts touching the screen,
9922      * the button shouldn't take focus
9923      * @return Whether the view is focusable in touch mode.
9924      * @attr ref android.R.styleable#View_focusableInTouchMode
9925      */
9926     @ViewDebug.ExportedProperty(category = "focus")
9927     public final boolean isFocusableInTouchMode() {
9928         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9929     }
9930
9931     /**
9932      * Find the nearest view in the specified direction that can take focus.
9933      * This does not actually give focus to that view.
9934      *
9935      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9936      *
9937      * @return The nearest focusable in the specified direction, or null if none
9938      *         can be found.
9939      */
9940     public View focusSearch(@FocusRealDirection int direction) {
9941         if (mParent != null) {
9942             return mParent.focusSearch(this, direction);
9943         } else {
9944             return null;
9945         }
9946     }
9947
9948     /**
9949      * Returns whether this View is a root of a keyboard navigation cluster.
9950      *
9951      * @return True if this view is a root of a cluster, or false otherwise.
9952      * @attr ref android.R.styleable#View_keyboardNavigationCluster
9953      */
9954     @ViewDebug.ExportedProperty(category = "focus")
9955     public final boolean isKeyboardNavigationCluster() {
9956         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9957     }
9958
9959     /**
9960      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
9961      * will be ignored.
9962      *
9963      * @return the keyboard navigation cluster that this view is in (can be this view)
9964      *         or {@code null} if not in one
9965      */
9966     View findKeyboardNavigationCluster() {
9967         if (mParent instanceof View) {
9968             View cluster = ((View) mParent).findKeyboardNavigationCluster();
9969             if (cluster != null) {
9970                 return cluster;
9971             } else if (isKeyboardNavigationCluster()) {
9972                 return this;
9973             }
9974         }
9975         return null;
9976     }
9977
9978     /**
9979      * Set whether this view is a root of a keyboard navigation cluster.
9980      *
9981      * @param isCluster If true, this view is a root of a cluster.
9982      *
9983      * @attr ref android.R.styleable#View_keyboardNavigationCluster
9984      */
9985     public void setKeyboardNavigationCluster(boolean isCluster) {
9986         if (isCluster) {
9987             mPrivateFlags3 |= PFLAG3_CLUSTER;
9988         } else {
9989             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9990         }
9991     }
9992
9993     /**
9994      * Sets this View as the one which receives focus the next time cluster navigation jumps
9995      * to the cluster containing this View. This does NOT change focus even if the cluster
9996      * containing this view is current.
9997      *
9998      * @hide
9999      */
10000     public final void setFocusedInCluster() {
10001         setFocusedInCluster(findKeyboardNavigationCluster());
10002     }
10003
10004     private void setFocusedInCluster(View cluster) {
10005         if (this instanceof ViewGroup) {
10006             ((ViewGroup) this).mFocusedInCluster = null;
10007         }
10008         if (cluster == this) {
10009             return;
10010         }
10011         ViewParent parent = mParent;
10012         View child = this;
10013         while (parent instanceof ViewGroup) {
10014             ((ViewGroup) parent).mFocusedInCluster = child;
10015             if (parent == cluster) {
10016                 break;
10017             }
10018             child = (View) parent;
10019             parent = parent.getParent();
10020         }
10021     }
10022
10023     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
10024         if (oldFocus != null) {
10025             View oldCluster = oldFocus.findKeyboardNavigationCluster();
10026             View cluster = findKeyboardNavigationCluster();
10027             if (oldCluster != cluster) {
10028                 // Going from one cluster to another, so save last-focused.
10029                 // This covers cluster jumps because they are always FOCUS_DOWN
10030                 oldFocus.setFocusedInCluster(oldCluster);
10031                 if (!(oldFocus.mParent instanceof ViewGroup)) {
10032                     return;
10033                 }
10034                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
10035                     // This is a result of ordered navigation so consider navigation through
10036                     // the previous cluster "complete" and clear its last-focused memory.
10037                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10038                 } else if (oldFocus instanceof ViewGroup
10039                         && ((ViewGroup) oldFocus).getDescendantFocusability()
10040                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
10041                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
10042                     // This means oldFocus is not focusable since it obviously has a focusable
10043                     // child (this). Don't restore focus to it in the future.
10044                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10045                 }
10046             }
10047         }
10048     }
10049
10050     /**
10051      * Returns whether this View should receive focus when the focus is restored for the view
10052      * hierarchy containing this view.
10053      * <p>
10054      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10055      * window or serves as a target of cluster navigation.
10056      *
10057      * @see #restoreDefaultFocus()
10058      *
10059      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
10060      * @attr ref android.R.styleable#View_focusedByDefault
10061      */
10062     @ViewDebug.ExportedProperty(category = "focus")
10063     public final boolean isFocusedByDefault() {
10064         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
10065     }
10066
10067     /**
10068      * Sets whether this View should receive focus when the focus is restored for the view
10069      * hierarchy containing this view.
10070      * <p>
10071      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10072      * window or serves as a target of cluster navigation.
10073      *
10074      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
10075      *                           {@code false} otherwise.
10076      *
10077      * @see #restoreDefaultFocus()
10078      *
10079      * @attr ref android.R.styleable#View_focusedByDefault
10080      */
10081     public void setFocusedByDefault(boolean isFocusedByDefault) {
10082         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
10083             return;
10084         }
10085
10086         if (isFocusedByDefault) {
10087             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
10088         } else {
10089             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
10090         }
10091
10092         if (mParent instanceof ViewGroup) {
10093             if (isFocusedByDefault) {
10094                 ((ViewGroup) mParent).setDefaultFocus(this);
10095             } else {
10096                 ((ViewGroup) mParent).clearDefaultFocus(this);
10097             }
10098         }
10099     }
10100
10101     /**
10102      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
10103      *
10104      * @return {@code true} if this view has default focus, {@code false} otherwise
10105      */
10106     boolean hasDefaultFocus() {
10107         return isFocusedByDefault();
10108     }
10109
10110     /**
10111      * Find the nearest keyboard navigation cluster in the specified direction.
10112      * This does not actually give focus to that cluster.
10113      *
10114      * @param currentCluster The starting point of the search. Null means the current cluster is not
10115      *                       found yet
10116      * @param direction Direction to look
10117      *
10118      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
10119      *         can be found
10120      */
10121     public View keyboardNavigationClusterSearch(View currentCluster,
10122             @FocusDirection int direction) {
10123         if (isKeyboardNavigationCluster()) {
10124             currentCluster = this;
10125         }
10126         if (isRootNamespace()) {
10127             // Root namespace means we should consider ourselves the top of the
10128             // tree for group searching; otherwise we could be group searching
10129             // into other tabs.  see LocalActivityManager and TabHost for more info.
10130             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
10131                     this, currentCluster, direction);
10132         } else if (mParent != null) {
10133             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
10134         }
10135         return null;
10136     }
10137
10138     /**
10139      * This method is the last chance for the focused view and its ancestors to
10140      * respond to an arrow key. This is called when the focused view did not
10141      * consume the key internally, nor could the view system find a new view in
10142      * the requested direction to give focus to.
10143      *
10144      * @param focused The currently focused view.
10145      * @param direction The direction focus wants to move. One of FOCUS_UP,
10146      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
10147      * @return True if the this view consumed this unhandled move.
10148      */
10149     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
10150         return false;
10151     }
10152
10153     /**
10154      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10155      * have {@link android.R.attr#state_focused} defined in its background.
10156      *
10157      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10158      *                                      highlight, {@code false} otherwise.
10159      *
10160      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10161      */
10162     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10163         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10164     }
10165
10166     /**
10167
10168     /**
10169      * Returns whether this View should use a default focus highlight when it gets focused but
10170      * doesn't have {@link android.R.attr#state_focused} defined in its background.
10171      *
10172      * @return True if this View should use a default focus highlight.
10173      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10174      */
10175     @ViewDebug.ExportedProperty(category = "focus")
10176     public final boolean getDefaultFocusHighlightEnabled() {
10177         return mDefaultFocusHighlightEnabled;
10178     }
10179
10180     /**
10181      * If a user manually specified the next view id for a particular direction,
10182      * use the root to look up the view.
10183      * @param root The root view of the hierarchy containing this view.
10184      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10185      * or FOCUS_BACKWARD.
10186      * @return The user specified next view, or null if there is none.
10187      */
10188     View findUserSetNextFocus(View root, @FocusDirection int direction) {
10189         switch (direction) {
10190             case FOCUS_LEFT:
10191                 if (mNextFocusLeftId == View.NO_ID) return null;
10192                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10193             case FOCUS_RIGHT:
10194                 if (mNextFocusRightId == View.NO_ID) return null;
10195                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
10196             case FOCUS_UP:
10197                 if (mNextFocusUpId == View.NO_ID) return null;
10198                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
10199             case FOCUS_DOWN:
10200                 if (mNextFocusDownId == View.NO_ID) return null;
10201                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
10202             case FOCUS_FORWARD:
10203                 if (mNextFocusForwardId == View.NO_ID) return null;
10204                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10205             case FOCUS_BACKWARD: {
10206                 if (mID == View.NO_ID) return null;
10207                 final int id = mID;
10208                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10209                     @Override
10210                     public boolean test(View t) {
10211                         return t.mNextFocusForwardId == id;
10212                     }
10213                 });
10214             }
10215         }
10216         return null;
10217     }
10218
10219     /**
10220      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10221      * use the root to look up the view.
10222      *
10223      * @param root the root view of the hierarchy containing this view
10224      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10225      * @return the user-specified next cluster, or {@code null} if there is none
10226      */
10227     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10228         switch (direction) {
10229             case FOCUS_FORWARD:
10230                 if (mNextClusterForwardId == View.NO_ID) return null;
10231                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10232             case FOCUS_BACKWARD: {
10233                 if (mID == View.NO_ID) return null;
10234                 final int id = mID;
10235                 return root.findViewByPredicateInsideOut(this,
10236                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
10237             }
10238         }
10239         return null;
10240     }
10241
10242     private View findViewInsideOutShouldExist(View root, int id) {
10243         if (mMatchIdPredicate == null) {
10244             mMatchIdPredicate = new MatchIdPredicate();
10245         }
10246         mMatchIdPredicate.mId = id;
10247         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10248         if (result == null) {
10249             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10250         }
10251         return result;
10252     }
10253
10254     /**
10255      * Find and return all focusable views that are descendants of this view,
10256      * possibly including this view if it is focusable itself.
10257      *
10258      * @param direction The direction of the focus
10259      * @return A list of focusable views
10260      */
10261     public ArrayList<View> getFocusables(@FocusDirection int direction) {
10262         ArrayList<View> result = new ArrayList<View>(24);
10263         addFocusables(result, direction);
10264         return result;
10265     }
10266
10267     /**
10268      * Add any focusable views that are descendants of this view (possibly
10269      * including this view if it is focusable itself) to views.  If we are in touch mode,
10270      * only add views that are also focusable in touch mode.
10271      *
10272      * @param views Focusable views found so far
10273      * @param direction The direction of the focus
10274      */
10275     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10276         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10277     }
10278
10279     /**
10280      * Adds any focusable views that are descendants of this view (possibly
10281      * including this view if it is focusable itself) to views. This method
10282      * adds all focusable views regardless if we are in touch mode or
10283      * only views focusable in touch mode if we are in touch mode or
10284      * only views that can take accessibility focus if accessibility is enabled
10285      * depending on the focusable mode parameter.
10286      *
10287      * @param views Focusable views found so far or null if all we are interested is
10288      *        the number of focusables.
10289      * @param direction The direction of the focus.
10290      * @param focusableMode The type of focusables to be added.
10291      *
10292      * @see #FOCUSABLES_ALL
10293      * @see #FOCUSABLES_TOUCH_MODE
10294      */
10295     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10296             @FocusableMode int focusableMode) {
10297         if (views == null) {
10298             return;
10299         }
10300         if (!isFocusable()) {
10301             return;
10302         }
10303         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10304                 && !isFocusableInTouchMode()) {
10305             return;
10306         }
10307         views.add(this);
10308     }
10309
10310     /**
10311      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10312      * including this view if it is a cluster root itself) to views.
10313      *
10314      * @param views Keyboard navigation cluster roots found so far
10315      * @param direction Direction to look
10316      */
10317     public void addKeyboardNavigationClusters(
10318             @NonNull Collection<View> views,
10319             int direction) {
10320         if (!isKeyboardNavigationCluster()) {
10321             return;
10322         }
10323         if (!hasFocusable()) {
10324             return;
10325         }
10326         views.add(this);
10327     }
10328
10329     /**
10330      * Finds the Views that contain given text. The containment is case insensitive.
10331      * The search is performed by either the text that the View renders or the content
10332      * description that describes the view for accessibility purposes and the view does
10333      * not render or both. Clients can specify how the search is to be performed via
10334      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10335      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10336      *
10337      * @param outViews The output list of matching Views.
10338      * @param searched The text to match against.
10339      *
10340      * @see #FIND_VIEWS_WITH_TEXT
10341      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10342      * @see #setContentDescription(CharSequence)
10343      */
10344     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10345             @FindViewFlags int flags) {
10346         if (getAccessibilityNodeProvider() != null) {
10347             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10348                 outViews.add(this);
10349             }
10350         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10351                 && (searched != null && searched.length() > 0)
10352                 && (mContentDescription != null && mContentDescription.length() > 0)) {
10353             String searchedLowerCase = searched.toString().toLowerCase();
10354             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10355             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10356                 outViews.add(this);
10357             }
10358         }
10359     }
10360
10361     /**
10362      * Find and return all touchable views that are descendants of this view,
10363      * possibly including this view if it is touchable itself.
10364      *
10365      * @return A list of touchable views
10366      */
10367     public ArrayList<View> getTouchables() {
10368         ArrayList<View> result = new ArrayList<View>();
10369         addTouchables(result);
10370         return result;
10371     }
10372
10373     /**
10374      * Add any touchable views that are descendants of this view (possibly
10375      * including this view if it is touchable itself) to views.
10376      *
10377      * @param views Touchable views found so far
10378      */
10379     public void addTouchables(ArrayList<View> views) {
10380         final int viewFlags = mViewFlags;
10381
10382         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10383                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10384                 && (viewFlags & ENABLED_MASK) == ENABLED) {
10385             views.add(this);
10386         }
10387     }
10388
10389     /**
10390      * Returns whether this View is accessibility focused.
10391      *
10392      * @return True if this View is accessibility focused.
10393      */
10394     public boolean isAccessibilityFocused() {
10395         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10396     }
10397
10398     /**
10399      * Call this to try to give accessibility focus to this view.
10400      *
10401      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10402      * returns false or the view is no visible or the view already has accessibility
10403      * focus.
10404      *
10405      * See also {@link #focusSearch(int)}, which is what you call to say that you
10406      * have focus, and you want your parent to look for the next one.
10407      *
10408      * @return Whether this view actually took accessibility focus.
10409      *
10410      * @hide
10411      */
10412     public boolean requestAccessibilityFocus() {
10413         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10414         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10415             return false;
10416         }
10417         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10418             return false;
10419         }
10420         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10421             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10422             ViewRootImpl viewRootImpl = getViewRootImpl();
10423             if (viewRootImpl != null) {
10424                 viewRootImpl.setAccessibilityFocus(this, null);
10425             }
10426             invalidate();
10427             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10428             return true;
10429         }
10430         return false;
10431     }
10432
10433     /**
10434      * Call this to try to clear accessibility focus of this view.
10435      *
10436      * See also {@link #focusSearch(int)}, which is what you call to say that you
10437      * have focus, and you want your parent to look for the next one.
10438      *
10439      * @hide
10440      */
10441     public void clearAccessibilityFocus() {
10442         clearAccessibilityFocusNoCallbacks(0);
10443
10444         // Clear the global reference of accessibility focus if this view or
10445         // any of its descendants had accessibility focus. This will NOT send
10446         // an event or update internal state if focus is cleared from a
10447         // descendant view, which may leave views in inconsistent states.
10448         final ViewRootImpl viewRootImpl = getViewRootImpl();
10449         if (viewRootImpl != null) {
10450             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10451             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10452                 viewRootImpl.setAccessibilityFocus(null, null);
10453             }
10454         }
10455     }
10456
10457     private void sendAccessibilityHoverEvent(int eventType) {
10458         // Since we are not delivering to a client accessibility events from not
10459         // important views (unless the clinet request that) we need to fire the
10460         // event from the deepest view exposed to the client. As a consequence if
10461         // the user crosses a not exposed view the client will see enter and exit
10462         // of the exposed predecessor followed by and enter and exit of that same
10463         // predecessor when entering and exiting the not exposed descendant. This
10464         // is fine since the client has a clear idea which view is hovered at the
10465         // price of a couple more events being sent. This is a simple and
10466         // working solution.
10467         View source = this;
10468         while (true) {
10469             if (source.includeForAccessibility()) {
10470                 source.sendAccessibilityEvent(eventType);
10471                 return;
10472             }
10473             ViewParent parent = source.getParent();
10474             if (parent instanceof View) {
10475                 source = (View) parent;
10476             } else {
10477                 return;
10478             }
10479         }
10480     }
10481
10482     /**
10483      * Clears accessibility focus without calling any callback methods
10484      * normally invoked in {@link #clearAccessibilityFocus()}. This method
10485      * is used separately from that one for clearing accessibility focus when
10486      * giving this focus to another view.
10487      *
10488      * @param action The action, if any, that led to focus being cleared. Set to
10489      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10490      * the window.
10491      */
10492     void clearAccessibilityFocusNoCallbacks(int action) {
10493         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10494             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10495             invalidate();
10496             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10497                 AccessibilityEvent event = AccessibilityEvent.obtain(
10498                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10499                 event.setAction(action);
10500                 if (mAccessibilityDelegate != null) {
10501                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10502                 } else {
10503                     sendAccessibilityEventUnchecked(event);
10504                 }
10505             }
10506         }
10507     }
10508
10509     /**
10510      * Call this to try to give focus to a specific view or to one of its
10511      * descendants.
10512      *
10513      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10514      * false), or if it is focusable and it is not focusable in touch mode
10515      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10516      *
10517      * See also {@link #focusSearch(int)}, which is what you call to say that you
10518      * have focus, and you want your parent to look for the next one.
10519      *
10520      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10521      * {@link #FOCUS_DOWN} and <code>null</code>.
10522      *
10523      * @return Whether this view or one of its descendants actually took focus.
10524      */
10525     public final boolean requestFocus() {
10526         return requestFocus(View.FOCUS_DOWN);
10527     }
10528
10529     /**
10530      * This will request focus for whichever View was last focused within this
10531      * cluster before a focus-jump out of it.
10532      *
10533      * @hide
10534      */
10535     @TestApi
10536     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10537         // Prioritize focusableByDefault over algorithmic focus selection.
10538         if (restoreDefaultFocus()) {
10539             return true;
10540         }
10541         return requestFocus(direction);
10542     }
10543
10544     /**
10545      * This will request focus for whichever View not in a cluster was last focused before a
10546      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10547      * the "first" focusable view it finds.
10548      *
10549      * @hide
10550      */
10551     @TestApi
10552     public boolean restoreFocusNotInCluster() {
10553         return requestFocus(View.FOCUS_DOWN);
10554     }
10555
10556     /**
10557      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10558      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10559      *
10560      * @return Whether this view or one of its descendants actually took focus
10561      */
10562     public boolean restoreDefaultFocus() {
10563         return requestFocus(View.FOCUS_DOWN);
10564     }
10565
10566     /**
10567      * Call this to try to give focus to a specific view or to one of its
10568      * descendants and give it a hint about what direction focus is heading.
10569      *
10570      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10571      * false), or if it is focusable and it is not focusable in touch mode
10572      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10573      *
10574      * See also {@link #focusSearch(int)}, which is what you call to say that you
10575      * have focus, and you want your parent to look for the next one.
10576      *
10577      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10578      * <code>null</code> set for the previously focused rectangle.
10579      *
10580      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10581      * @return Whether this view or one of its descendants actually took focus.
10582      */
10583     public final boolean requestFocus(int direction) {
10584         return requestFocus(direction, null);
10585     }
10586
10587     /**
10588      * Call this to try to give focus to a specific view or to one of its descendants
10589      * and give it hints about the direction and a specific rectangle that the focus
10590      * is coming from.  The rectangle can help give larger views a finer grained hint
10591      * about where focus is coming from, and therefore, where to show selection, or
10592      * forward focus change internally.
10593      *
10594      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10595      * false), or if it is focusable and it is not focusable in touch mode
10596      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10597      *
10598      * A View will not take focus if it is not visible.
10599      *
10600      * A View will not take focus if one of its parents has
10601      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10602      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10603      *
10604      * See also {@link #focusSearch(int)}, which is what you call to say that you
10605      * have focus, and you want your parent to look for the next one.
10606      *
10607      * You may wish to override this method if your custom {@link View} has an internal
10608      * {@link View} that it wishes to forward the request to.
10609      *
10610      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10611      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10612      *        to give a finer grained hint about where focus is coming from.  May be null
10613      *        if there is no hint.
10614      * @return Whether this view or one of its descendants actually took focus.
10615      */
10616     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10617         return requestFocusNoSearch(direction, previouslyFocusedRect);
10618     }
10619
10620     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10621         // need to be focusable
10622         if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10623                 || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10624             return false;
10625         }
10626
10627         // need to be focusable in touch mode if in touch mode
10628         if (isInTouchMode() &&
10629             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10630                return false;
10631         }
10632
10633         // need to not have any parents blocking us
10634         if (hasAncestorThatBlocksDescendantFocus()) {
10635             return false;
10636         }
10637
10638         handleFocusGainInternal(direction, previouslyFocusedRect);
10639         return true;
10640     }
10641
10642     /**
10643      * Call this to try to give focus to a specific view or to one of its descendants. This is a
10644      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10645      * touch mode to request focus when they are touched.
10646      *
10647      * @return Whether this view or one of its descendants actually took focus.
10648      *
10649      * @see #isInTouchMode()
10650      *
10651      */
10652     public final boolean requestFocusFromTouch() {
10653         // Leave touch mode if we need to
10654         if (isInTouchMode()) {
10655             ViewRootImpl viewRoot = getViewRootImpl();
10656             if (viewRoot != null) {
10657                 viewRoot.ensureTouchMode(false);
10658             }
10659         }
10660         return requestFocus(View.FOCUS_DOWN);
10661     }
10662
10663     /**
10664      * @return Whether any ancestor of this view blocks descendant focus.
10665      */
10666     private boolean hasAncestorThatBlocksDescendantFocus() {
10667         final boolean focusableInTouchMode = isFocusableInTouchMode();
10668         ViewParent ancestor = mParent;
10669         while (ancestor instanceof ViewGroup) {
10670             final ViewGroup vgAncestor = (ViewGroup) ancestor;
10671             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10672                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10673                 return true;
10674             } else {
10675                 ancestor = vgAncestor.getParent();
10676             }
10677         }
10678         return false;
10679     }
10680
10681     /**
10682      * Gets the mode for determining whether this View is important for accessibility.
10683      * A view is important for accessibility if it fires accessibility events and if it
10684      * is reported to accessibility services that query the screen.
10685      *
10686      * @return The mode for determining whether a view is important for accessibility, one
10687      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10688      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10689      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10690      *
10691      * @attr ref android.R.styleable#View_importantForAccessibility
10692      *
10693      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10694      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10695      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10696      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10697      */
10698     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10699             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10700             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10701             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10702             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10703                     to = "noHideDescendants")
10704         })
10705     public int getImportantForAccessibility() {
10706         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10707                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10708     }
10709
10710     /**
10711      * Sets the live region mode for this view. This indicates to accessibility
10712      * services whether they should automatically notify the user about changes
10713      * to the view's content description or text, or to the content descriptions
10714      * or text of the view's children (where applicable).
10715      * <p>
10716      * For example, in a login screen with a TextView that displays an "incorrect
10717      * password" notification, that view should be marked as a live region with
10718      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10719      * <p>
10720      * To disable change notifications for this view, use
10721      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10722      * mode for most views.
10723      * <p>
10724      * To indicate that the user should be notified of changes, use
10725      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10726      * <p>
10727      * If the view's changes should interrupt ongoing speech and notify the user
10728      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10729      *
10730      * @param mode The live region mode for this view, one of:
10731      *        <ul>
10732      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10733      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10734      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10735      *        </ul>
10736      * @attr ref android.R.styleable#View_accessibilityLiveRegion
10737      */
10738     public void setAccessibilityLiveRegion(int mode) {
10739         if (mode != getAccessibilityLiveRegion()) {
10740             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10741             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10742                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10743             notifyViewAccessibilityStateChangedIfNeeded(
10744                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10745         }
10746     }
10747
10748     /**
10749      * Gets the live region mode for this View.
10750      *
10751      * @return The live region mode for the view.
10752      *
10753      * @attr ref android.R.styleable#View_accessibilityLiveRegion
10754      *
10755      * @see #setAccessibilityLiveRegion(int)
10756      */
10757     public int getAccessibilityLiveRegion() {
10758         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10759                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10760     }
10761
10762     /**
10763      * Sets how to determine whether this view is important for accessibility
10764      * which is if it fires accessibility events and if it is reported to
10765      * accessibility services that query the screen.
10766      *
10767      * @param mode How to determine whether this view is important for accessibility.
10768      *
10769      * @attr ref android.R.styleable#View_importantForAccessibility
10770      *
10771      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10772      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10773      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10774      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10775      */
10776     public void setImportantForAccessibility(int mode) {
10777         final int oldMode = getImportantForAccessibility();
10778         if (mode != oldMode) {
10779             final boolean hideDescendants =
10780                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10781
10782             // If this node or its descendants are no longer important, try to
10783             // clear accessibility focus.
10784             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10785                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
10786                 if (focusHost != null) {
10787                     focusHost.clearAccessibilityFocus();
10788                 }
10789             }
10790
10791             // If we're moving between AUTO and another state, we might not need
10792             // to send a subtree changed notification. We'll store the computed
10793             // importance, since we'll need to check it later to make sure.
10794             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10795                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10796             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10797             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10798             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10799                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10800             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10801                 notifySubtreeAccessibilityStateChangedIfNeeded();
10802             } else {
10803                 notifyViewAccessibilityStateChangedIfNeeded(
10804                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10805             }
10806         }
10807     }
10808
10809     /**
10810      * Returns the view within this view's hierarchy that is hosting
10811      * accessibility focus.
10812      *
10813      * @param searchDescendants whether to search for focus in descendant views
10814      * @return the view hosting accessibility focus, or {@code null}
10815      */
10816     private View findAccessibilityFocusHost(boolean searchDescendants) {
10817         if (isAccessibilityFocusedViewOrHost()) {
10818             return this;
10819         }
10820
10821         if (searchDescendants) {
10822             final ViewRootImpl viewRoot = getViewRootImpl();
10823             if (viewRoot != null) {
10824                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
10825                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10826                     return focusHost;
10827                 }
10828             }
10829         }
10830
10831         return null;
10832     }
10833
10834     /**
10835      * Computes whether this view should be exposed for accessibility. In
10836      * general, views that are interactive or provide information are exposed
10837      * while views that serve only as containers are hidden.
10838      * <p>
10839      * If an ancestor of this view has importance
10840      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10841      * returns <code>false</code>.
10842      * <p>
10843      * Otherwise, the value is computed according to the view's
10844      * {@link #getImportantForAccessibility()} value:
10845      * <ol>
10846      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10847      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10848      * </code>
10849      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10850      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10851      * view satisfies any of the following:
10852      * <ul>
10853      * <li>Is actionable, e.g. {@link #isClickable()},
10854      * {@link #isLongClickable()}, or {@link #isFocusable()}
10855      * <li>Has an {@link AccessibilityDelegate}
10856      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10857      * {@link OnKeyListener}, etc.
10858      * <li>Is an accessibility live region, e.g.
10859      * {@link #getAccessibilityLiveRegion()} is not
10860      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10861      * </ul>
10862      * </ol>
10863      *
10864      * @return Whether the view is exposed for accessibility.
10865      * @see #setImportantForAccessibility(int)
10866      * @see #getImportantForAccessibility()
10867      */
10868     public boolean isImportantForAccessibility() {
10869         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10870                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10871         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10872                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10873             return false;
10874         }
10875
10876         // Check parent mode to ensure we're not hidden.
10877         ViewParent parent = mParent;
10878         while (parent instanceof View) {
10879             if (((View) parent).getImportantForAccessibility()
10880                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10881                 return false;
10882             }
10883             parent = parent.getParent();
10884         }
10885
10886         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10887                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10888                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10889     }
10890
10891     /**
10892      * Gets the parent for accessibility purposes. Note that the parent for
10893      * accessibility is not necessary the immediate parent. It is the first
10894      * predecessor that is important for accessibility.
10895      *
10896      * @return The parent for accessibility purposes.
10897      */
10898     public ViewParent getParentForAccessibility() {
10899         if (mParent instanceof View) {
10900             View parentView = (View) mParent;
10901             if (parentView.includeForAccessibility()) {
10902                 return mParent;
10903             } else {
10904                 return mParent.getParentForAccessibility();
10905             }
10906         }
10907         return null;
10908     }
10909
10910     /**
10911      * Adds the children of this View relevant for accessibility to the given list
10912      * as output. Since some Views are not important for accessibility the added
10913      * child views are not necessarily direct children of this view, rather they are
10914      * the first level of descendants important for accessibility.
10915      *
10916      * @param outChildren The output list that will receive children for accessibility.
10917      */
10918     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10919
10920     }
10921
10922     /**
10923      * Whether to regard this view for accessibility. A view is regarded for
10924      * accessibility if it is important for accessibility or the querying
10925      * accessibility service has explicitly requested that view not
10926      * important for accessibility are regarded.
10927      *
10928      * @return Whether to regard the view for accessibility.
10929      *
10930      * @hide
10931      */
10932     public boolean includeForAccessibility() {
10933         if (mAttachInfo != null) {
10934             return (mAttachInfo.mAccessibilityFetchFlags
10935                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10936                     || isImportantForAccessibility();
10937         }
10938         return false;
10939     }
10940
10941     /**
10942      * Returns whether the View is considered actionable from
10943      * accessibility perspective. Such view are important for
10944      * accessibility.
10945      *
10946      * @return True if the view is actionable for accessibility.
10947      *
10948      * @hide
10949      */
10950     public boolean isActionableForAccessibility() {
10951         return (isClickable() || isLongClickable() || isFocusable());
10952     }
10953
10954     /**
10955      * Returns whether the View has registered callbacks which makes it
10956      * important for accessibility.
10957      *
10958      * @return True if the view is actionable for accessibility.
10959      */
10960     private boolean hasListenersForAccessibility() {
10961         ListenerInfo info = getListenerInfo();
10962         return mTouchDelegate != null || info.mOnKeyListener != null
10963                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10964                 || info.mOnHoverListener != null || info.mOnDragListener != null;
10965     }
10966
10967     /**
10968      * Notifies that the accessibility state of this view changed. The change
10969      * is local to this view and does not represent structural changes such
10970      * as children and parent. For example, the view became focusable. The
10971      * notification is at at most once every
10972      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10973      * to avoid unnecessary load to the system. Also once a view has a pending
10974      * notification this method is a NOP until the notification has been sent.
10975      *
10976      * @hide
10977      */
10978     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10979         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10980             return;
10981         }
10982         if (mSendViewStateChangedAccessibilityEvent == null) {
10983             mSendViewStateChangedAccessibilityEvent =
10984                     new SendViewStateChangedAccessibilityEvent();
10985         }
10986         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10987     }
10988
10989     /**
10990      * Notifies that the accessibility state of this view changed. The change
10991      * is *not* local to this view and does represent structural changes such
10992      * as children and parent. For example, the view size changed. The
10993      * notification is at at most once every
10994      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10995      * to avoid unnecessary load to the system. Also once a view has a pending
10996      * notification this method is a NOP until the notification has been sent.
10997      *
10998      * @hide
10999      */
11000     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
11001         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11002             return;
11003         }
11004         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
11005             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11006             if (mParent != null) {
11007                 try {
11008                     mParent.notifySubtreeAccessibilityStateChanged(
11009                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
11010                 } catch (AbstractMethodError e) {
11011                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11012                             " does not fully implement ViewParent", e);
11013                 }
11014             }
11015         }
11016     }
11017
11018     /**
11019      * Change the visibility of the View without triggering any other changes. This is
11020      * important for transitions, where visibility changes should not adjust focus or
11021      * trigger a new layout. This is only used when the visibility has already been changed
11022      * and we need a transient value during an animation. When the animation completes,
11023      * the original visibility value is always restored.
11024      *
11025      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11026      * @hide
11027      */
11028     public void setTransitionVisibility(@Visibility int visibility) {
11029         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
11030     }
11031
11032     /**
11033      * Reset the flag indicating the accessibility state of the subtree rooted
11034      * at this view changed.
11035      */
11036     void resetSubtreeAccessibilityStateChanged() {
11037         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11038     }
11039
11040     /**
11041      * Report an accessibility action to this view's parents for delegated processing.
11042      *
11043      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
11044      * call this method to delegate an accessibility action to a supporting parent. If the parent
11045      * returns true from its
11046      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
11047      * method this method will return true to signify that the action was consumed.</p>
11048      *
11049      * <p>This method is useful for implementing nested scrolling child views. If
11050      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
11051      * a custom view implementation may invoke this method to allow a parent to consume the
11052      * scroll first. If this method returns true the custom view should skip its own scrolling
11053      * behavior.</p>
11054      *
11055      * @param action Accessibility action to delegate
11056      * @param arguments Optional action arguments
11057      * @return true if the action was consumed by a parent
11058      */
11059     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
11060         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
11061             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
11062                 return true;
11063             }
11064         }
11065         return false;
11066     }
11067
11068     /**
11069      * Performs the specified accessibility action on the view. For
11070      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
11071      * <p>
11072      * If an {@link AccessibilityDelegate} has been specified via calling
11073      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11074      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
11075      * is responsible for handling this call.
11076      * </p>
11077      *
11078      * <p>The default implementation will delegate
11079      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
11080      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
11081      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
11082      *
11083      * @param action The action to perform.
11084      * @param arguments Optional action arguments.
11085      * @return Whether the action was performed.
11086      */
11087     public boolean performAccessibilityAction(int action, Bundle arguments) {
11088       if (mAccessibilityDelegate != null) {
11089           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
11090       } else {
11091           return performAccessibilityActionInternal(action, arguments);
11092       }
11093     }
11094
11095    /**
11096     * @see #performAccessibilityAction(int, Bundle)
11097     *
11098     * Note: Called from the default {@link AccessibilityDelegate}.
11099     *
11100     * @hide
11101     */
11102     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
11103         if (isNestedScrollingEnabled()
11104                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
11105                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
11106                 || action == R.id.accessibilityActionScrollUp
11107                 || action == R.id.accessibilityActionScrollLeft
11108                 || action == R.id.accessibilityActionScrollDown
11109                 || action == R.id.accessibilityActionScrollRight)) {
11110             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
11111                 return true;
11112             }
11113         }
11114
11115         switch (action) {
11116             case AccessibilityNodeInfo.ACTION_CLICK: {
11117                 if (isClickable()) {
11118                     performClick();
11119                     return true;
11120                 }
11121             } break;
11122             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
11123                 if (isLongClickable()) {
11124                     performLongClick();
11125                     return true;
11126                 }
11127             } break;
11128             case AccessibilityNodeInfo.ACTION_FOCUS: {
11129                 if (!hasFocus()) {
11130                     // Get out of touch mode since accessibility
11131                     // wants to move focus around.
11132                     getViewRootImpl().ensureTouchMode(false);
11133                     return requestFocus();
11134                 }
11135             } break;
11136             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
11137                 if (hasFocus()) {
11138                     clearFocus();
11139                     return !isFocused();
11140                 }
11141             } break;
11142             case AccessibilityNodeInfo.ACTION_SELECT: {
11143                 if (!isSelected()) {
11144                     setSelected(true);
11145                     return isSelected();
11146                 }
11147             } break;
11148             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
11149                 if (isSelected()) {
11150                     setSelected(false);
11151                     return !isSelected();
11152                 }
11153             } break;
11154             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11155                 if (!isAccessibilityFocused()) {
11156                     return requestAccessibilityFocus();
11157                 }
11158             } break;
11159             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11160                 if (isAccessibilityFocused()) {
11161                     clearAccessibilityFocus();
11162                     return true;
11163                 }
11164             } break;
11165             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
11166                 if (arguments != null) {
11167                     final int granularity = arguments.getInt(
11168                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11169                     final boolean extendSelection = arguments.getBoolean(
11170                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11171                     return traverseAtGranularity(granularity, true, extendSelection);
11172                 }
11173             } break;
11174             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11175                 if (arguments != null) {
11176                     final int granularity = arguments.getInt(
11177                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11178                     final boolean extendSelection = arguments.getBoolean(
11179                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11180                     return traverseAtGranularity(granularity, false, extendSelection);
11181                 }
11182             } break;
11183             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11184                 CharSequence text = getIterableTextForAccessibility();
11185                 if (text == null) {
11186                     return false;
11187                 }
11188                 final int start = (arguments != null) ? arguments.getInt(
11189                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11190                 final int end = (arguments != null) ? arguments.getInt(
11191                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11192                 // Only cursor position can be specified (selection length == 0)
11193                 if ((getAccessibilitySelectionStart() != start
11194                         || getAccessibilitySelectionEnd() != end)
11195                         && (start == end)) {
11196                     setAccessibilitySelection(start, end);
11197                     notifyViewAccessibilityStateChangedIfNeeded(
11198                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11199                     return true;
11200                 }
11201             } break;
11202             case R.id.accessibilityActionShowOnScreen: {
11203                 if (mAttachInfo != null) {
11204                     final Rect r = mAttachInfo.mTmpInvalRect;
11205                     getDrawingRect(r);
11206                     return requestRectangleOnScreen(r, true);
11207                 }
11208             } break;
11209             case R.id.accessibilityActionContextClick: {
11210                 if (isContextClickable()) {
11211                     performContextClick();
11212                     return true;
11213                 }
11214             } break;
11215         }
11216         return false;
11217     }
11218
11219     private boolean traverseAtGranularity(int granularity, boolean forward,
11220             boolean extendSelection) {
11221         CharSequence text = getIterableTextForAccessibility();
11222         if (text == null || text.length() == 0) {
11223             return false;
11224         }
11225         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11226         if (iterator == null) {
11227             return false;
11228         }
11229         int current = getAccessibilitySelectionEnd();
11230         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11231             current = forward ? 0 : text.length();
11232         }
11233         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11234         if (range == null) {
11235             return false;
11236         }
11237         final int segmentStart = range[0];
11238         final int segmentEnd = range[1];
11239         int selectionStart;
11240         int selectionEnd;
11241         if (extendSelection && isAccessibilitySelectionExtendable()) {
11242             selectionStart = getAccessibilitySelectionStart();
11243             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11244                 selectionStart = forward ? segmentStart : segmentEnd;
11245             }
11246             selectionEnd = forward ? segmentEnd : segmentStart;
11247         } else {
11248             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11249         }
11250         setAccessibilitySelection(selectionStart, selectionEnd);
11251         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11252                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11253         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11254         return true;
11255     }
11256
11257     /**
11258      * Gets the text reported for accessibility purposes.
11259      *
11260      * @return The accessibility text.
11261      *
11262      * @hide
11263      */
11264     public CharSequence getIterableTextForAccessibility() {
11265         return getContentDescription();
11266     }
11267
11268     /**
11269      * Gets whether accessibility selection can be extended.
11270      *
11271      * @return If selection is extensible.
11272      *
11273      * @hide
11274      */
11275     public boolean isAccessibilitySelectionExtendable() {
11276         return false;
11277     }
11278
11279     /**
11280      * @hide
11281      */
11282     public int getAccessibilitySelectionStart() {
11283         return mAccessibilityCursorPosition;
11284     }
11285
11286     /**
11287      * @hide
11288      */
11289     public int getAccessibilitySelectionEnd() {
11290         return getAccessibilitySelectionStart();
11291     }
11292
11293     /**
11294      * @hide
11295      */
11296     public void setAccessibilitySelection(int start, int end) {
11297         if (start ==  end && end == mAccessibilityCursorPosition) {
11298             return;
11299         }
11300         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11301             mAccessibilityCursorPosition = start;
11302         } else {
11303             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11304         }
11305         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11306     }
11307
11308     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11309             int fromIndex, int toIndex) {
11310         if (mParent == null) {
11311             return;
11312         }
11313         AccessibilityEvent event = AccessibilityEvent.obtain(
11314                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11315         onInitializeAccessibilityEvent(event);
11316         onPopulateAccessibilityEvent(event);
11317         event.setFromIndex(fromIndex);
11318         event.setToIndex(toIndex);
11319         event.setAction(action);
11320         event.setMovementGranularity(granularity);
11321         mParent.requestSendAccessibilityEvent(this, event);
11322     }
11323
11324     /**
11325      * @hide
11326      */
11327     public TextSegmentIterator getIteratorForGranularity(int granularity) {
11328         switch (granularity) {
11329             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11330                 CharSequence text = getIterableTextForAccessibility();
11331                 if (text != null && text.length() > 0) {
11332                     CharacterTextSegmentIterator iterator =
11333                         CharacterTextSegmentIterator.getInstance(
11334                                 mContext.getResources().getConfiguration().locale);
11335                     iterator.initialize(text.toString());
11336                     return iterator;
11337                 }
11338             } break;
11339             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11340                 CharSequence text = getIterableTextForAccessibility();
11341                 if (text != null && text.length() > 0) {
11342                     WordTextSegmentIterator iterator =
11343                         WordTextSegmentIterator.getInstance(
11344                                 mContext.getResources().getConfiguration().locale);
11345                     iterator.initialize(text.toString());
11346                     return iterator;
11347                 }
11348             } break;
11349             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11350                 CharSequence text = getIterableTextForAccessibility();
11351                 if (text != null && text.length() > 0) {
11352                     ParagraphTextSegmentIterator iterator =
11353                         ParagraphTextSegmentIterator.getInstance();
11354                     iterator.initialize(text.toString());
11355                     return iterator;
11356                 }
11357             } break;
11358         }
11359         return null;
11360     }
11361
11362     /**
11363      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11364      * and {@link #onFinishTemporaryDetach()}.
11365      *
11366      * <p>This method always returns {@code true} when called directly or indirectly from
11367      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11368      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11369      * <ul>
11370      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11371      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11372      * </ul>
11373      * </p>
11374      *
11375      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11376      * and {@link #onFinishTemporaryDetach()}.
11377      */
11378     public final boolean isTemporarilyDetached() {
11379         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11380     }
11381
11382     /**
11383      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11384      * a container View.
11385      */
11386     @CallSuper
11387     public void dispatchStartTemporaryDetach() {
11388         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11389         notifyEnterOrExitForAutoFillIfNeeded(false);
11390         onStartTemporaryDetach();
11391     }
11392
11393     /**
11394      * This is called when a container is going to temporarily detach a child, with
11395      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11396      * It will either be followed by {@link #onFinishTemporaryDetach()} or
11397      * {@link #onDetachedFromWindow()} when the container is done.
11398      */
11399     public void onStartTemporaryDetach() {
11400         removeUnsetPressCallback();
11401         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11402     }
11403
11404     /**
11405      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11406      * a container View.
11407      */
11408     @CallSuper
11409     public void dispatchFinishTemporaryDetach() {
11410         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11411         onFinishTemporaryDetach();
11412         if (hasWindowFocus() && hasFocus()) {
11413             InputMethodManager.getInstance().focusIn(this);
11414         }
11415         notifyEnterOrExitForAutoFillIfNeeded(true);
11416     }
11417
11418     /**
11419      * Called after {@link #onStartTemporaryDetach} when the container is done
11420      * changing the view.
11421      */
11422     public void onFinishTemporaryDetach() {
11423     }
11424
11425     /**
11426      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11427      * for this view's window.  Returns null if the view is not currently attached
11428      * to the window.  Normally you will not need to use this directly, but
11429      * just use the standard high-level event callbacks like
11430      * {@link #onKeyDown(int, KeyEvent)}.
11431      */
11432     public KeyEvent.DispatcherState getKeyDispatcherState() {
11433         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11434     }
11435
11436     /**
11437      * Dispatch a key event before it is processed by any input method
11438      * associated with the view hierarchy.  This can be used to intercept
11439      * key events in special situations before the IME consumes them; a
11440      * typical example would be handling the BACK key to update the application's
11441      * UI instead of allowing the IME to see it and close itself.
11442      *
11443      * @param event The key event to be dispatched.
11444      * @return True if the event was handled, false otherwise.
11445      */
11446     public boolean dispatchKeyEventPreIme(KeyEvent event) {
11447         return onKeyPreIme(event.getKeyCode(), event);
11448     }
11449
11450     /**
11451      * Dispatch a key event to the next view on the focus path. This path runs
11452      * from the top of the view tree down to the currently focused view. If this
11453      * view has focus, it will dispatch to itself. Otherwise it will dispatch
11454      * the next node down the focus path. This method also fires any key
11455      * listeners.
11456      *
11457      * @param event The key event to be dispatched.
11458      * @return True if the event was handled, false otherwise.
11459      */
11460     public boolean dispatchKeyEvent(KeyEvent event) {
11461         if (mInputEventConsistencyVerifier != null) {
11462             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11463         }
11464
11465         // Give any attached key listener a first crack at the event.
11466         //noinspection SimplifiableIfStatement
11467         ListenerInfo li = mListenerInfo;
11468         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11469                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11470             return true;
11471         }
11472
11473         if (event.dispatch(this, mAttachInfo != null
11474                 ? mAttachInfo.mKeyDispatchState : null, this)) {
11475             return true;
11476         }
11477
11478         if (mInputEventConsistencyVerifier != null) {
11479             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11480         }
11481         return false;
11482     }
11483
11484     /**
11485      * Dispatches a key shortcut event.
11486      *
11487      * @param event The key event to be dispatched.
11488      * @return True if the event was handled by the view, false otherwise.
11489      */
11490     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11491         return onKeyShortcut(event.getKeyCode(), event);
11492     }
11493
11494     /**
11495      * Pass the touch screen motion event down to the target view, or this
11496      * view if it is the target.
11497      *
11498      * @param event The motion event to be dispatched.
11499      * @return True if the event was handled by the view, false otherwise.
11500      */
11501     public boolean dispatchTouchEvent(MotionEvent event) {
11502         // If the event should be handled by accessibility focus first.
11503         if (event.isTargetAccessibilityFocus()) {
11504             // We don't have focus or no virtual descendant has it, do not handle the event.
11505             if (!isAccessibilityFocusedViewOrHost()) {
11506                 return false;
11507             }
11508             // We have focus and got the event, then use normal event dispatch.
11509             event.setTargetAccessibilityFocus(false);
11510         }
11511
11512         boolean result = false;
11513
11514         if (mInputEventConsistencyVerifier != null) {
11515             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11516         }
11517
11518         final int actionMasked = event.getActionMasked();
11519         if (actionMasked == MotionEvent.ACTION_DOWN) {
11520             // Defensive cleanup for new gesture
11521             stopNestedScroll();
11522         }
11523
11524         if (onFilterTouchEventForSecurity(event)) {
11525             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11526                 result = true;
11527             }
11528             //noinspection SimplifiableIfStatement
11529             ListenerInfo li = mListenerInfo;
11530             if (li != null && li.mOnTouchListener != null
11531                     && (mViewFlags & ENABLED_MASK) == ENABLED
11532                     && li.mOnTouchListener.onTouch(this, event)) {
11533                 result = true;
11534             }
11535
11536             if (!result && onTouchEvent(event)) {
11537                 result = true;
11538             }
11539         }
11540
11541         if (!result && mInputEventConsistencyVerifier != null) {
11542             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11543         }
11544
11545         // Clean up after nested scrolls if this is the end of a gesture;
11546         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11547         // of the gesture.
11548         if (actionMasked == MotionEvent.ACTION_UP ||
11549                 actionMasked == MotionEvent.ACTION_CANCEL ||
11550                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11551             stopNestedScroll();
11552         }
11553
11554         return result;
11555     }
11556
11557     boolean isAccessibilityFocusedViewOrHost() {
11558         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11559                 .getAccessibilityFocusedHost() == this);
11560     }
11561
11562     /**
11563      * Filter the touch event to apply security policies.
11564      *
11565      * @param event The motion event to be filtered.
11566      * @return True if the event should be dispatched, false if the event should be dropped.
11567      *
11568      * @see #getFilterTouchesWhenObscured
11569      */
11570     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11571         //noinspection RedundantIfStatement
11572         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11573                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11574             // Window is obscured, drop this touch.
11575             return false;
11576         }
11577         return true;
11578     }
11579
11580     /**
11581      * Pass a trackball motion event down to the focused view.
11582      *
11583      * @param event The motion event to be dispatched.
11584      * @return True if the event was handled by the view, false otherwise.
11585      */
11586     public boolean dispatchTrackballEvent(MotionEvent event) {
11587         if (mInputEventConsistencyVerifier != null) {
11588             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11589         }
11590
11591         return onTrackballEvent(event);
11592     }
11593
11594     /**
11595      * Pass a captured pointer event down to the focused view.
11596      *
11597      * @param event The motion event to be dispatched.
11598      * @return True if the event was handled by the view, false otherwise.
11599      */
11600     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11601         if (!hasPointerCapture()) {
11602             return false;
11603         }
11604         //noinspection SimplifiableIfStatement
11605         ListenerInfo li = mListenerInfo;
11606         if (li != null && li.mOnCapturedPointerListener != null
11607                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11608             return true;
11609         }
11610         return onCapturedPointerEvent(event);
11611     }
11612
11613     /**
11614      * Dispatch a generic motion event.
11615      * <p>
11616      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11617      * are delivered to the view under the pointer.  All other generic motion events are
11618      * delivered to the focused view.  Hover events are handled specially and are delivered
11619      * to {@link #onHoverEvent(MotionEvent)}.
11620      * </p>
11621      *
11622      * @param event The motion event to be dispatched.
11623      * @return True if the event was handled by the view, false otherwise.
11624      */
11625     public boolean dispatchGenericMotionEvent(MotionEvent event) {
11626         if (mInputEventConsistencyVerifier != null) {
11627             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11628         }
11629
11630         final int source = event.getSource();
11631         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11632             final int action = event.getAction();
11633             if (action == MotionEvent.ACTION_HOVER_ENTER
11634                     || action == MotionEvent.ACTION_HOVER_MOVE
11635                     || action == MotionEvent.ACTION_HOVER_EXIT) {
11636                 if (dispatchHoverEvent(event)) {
11637                     return true;
11638                 }
11639             } else if (dispatchGenericPointerEvent(event)) {
11640                 return true;
11641             }
11642         } else if (dispatchGenericFocusedEvent(event)) {
11643             return true;
11644         }
11645
11646         if (dispatchGenericMotionEventInternal(event)) {
11647             return true;
11648         }
11649
11650         if (mInputEventConsistencyVerifier != null) {
11651             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11652         }
11653         return false;
11654     }
11655
11656     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11657         //noinspection SimplifiableIfStatement
11658         ListenerInfo li = mListenerInfo;
11659         if (li != null && li.mOnGenericMotionListener != null
11660                 && (mViewFlags & ENABLED_MASK) == ENABLED
11661                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11662             return true;
11663         }
11664
11665         if (onGenericMotionEvent(event)) {
11666             return true;
11667         }
11668
11669         final int actionButton = event.getActionButton();
11670         switch (event.getActionMasked()) {
11671             case MotionEvent.ACTION_BUTTON_PRESS:
11672                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11673                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11674                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11675                     if (performContextClick(event.getX(), event.getY())) {
11676                         mInContextButtonPress = true;
11677                         setPressed(true, event.getX(), event.getY());
11678                         removeTapCallback();
11679                         removeLongPressCallback();
11680                         return true;
11681                     }
11682                 }
11683                 break;
11684
11685             case MotionEvent.ACTION_BUTTON_RELEASE:
11686                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11687                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11688                     mInContextButtonPress = false;
11689                     mIgnoreNextUpEvent = true;
11690                 }
11691                 break;
11692         }
11693
11694         if (mInputEventConsistencyVerifier != null) {
11695             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11696         }
11697         return false;
11698     }
11699
11700     /**
11701      * Dispatch a hover event.
11702      * <p>
11703      * Do not call this method directly.
11704      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11705      * </p>
11706      *
11707      * @param event The motion event to be dispatched.
11708      * @return True if the event was handled by the view, false otherwise.
11709      */
11710     protected boolean dispatchHoverEvent(MotionEvent event) {
11711         ListenerInfo li = mListenerInfo;
11712         //noinspection SimplifiableIfStatement
11713         if (li != null && li.mOnHoverListener != null
11714                 && (mViewFlags & ENABLED_MASK) == ENABLED
11715                 && li.mOnHoverListener.onHover(this, event)) {
11716             return true;
11717         }
11718
11719         return onHoverEvent(event);
11720     }
11721
11722     /**
11723      * Returns true if the view has a child to which it has recently sent
11724      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11725      * it does not have a hovered child, then it must be the innermost hovered view.
11726      * @hide
11727      */
11728     protected boolean hasHoveredChild() {
11729         return false;
11730     }
11731
11732     /**
11733      * Dispatch a generic motion event to the view under the first pointer.
11734      * <p>
11735      * Do not call this method directly.
11736      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11737      * </p>
11738      *
11739      * @param event The motion event to be dispatched.
11740      * @return True if the event was handled by the view, false otherwise.
11741      */
11742     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11743         return false;
11744     }
11745
11746     /**
11747      * Dispatch a generic motion event to the currently focused view.
11748      * <p>
11749      * Do not call this method directly.
11750      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11751      * </p>
11752      *
11753      * @param event The motion event to be dispatched.
11754      * @return True if the event was handled by the view, false otherwise.
11755      */
11756     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11757         return false;
11758     }
11759
11760     /**
11761      * Dispatch a pointer event.
11762      * <p>
11763      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11764      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11765      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11766      * and should not be expected to handle other pointing device features.
11767      * </p>
11768      *
11769      * @param event The motion event to be dispatched.
11770      * @return True if the event was handled by the view, false otherwise.
11771      * @hide
11772      */
11773     public final boolean dispatchPointerEvent(MotionEvent event) {
11774         if (event.isTouchEvent()) {
11775             return dispatchTouchEvent(event);
11776         } else {
11777             return dispatchGenericMotionEvent(event);
11778         }
11779     }
11780
11781     /**
11782      * Called when the window containing this view gains or loses window focus.
11783      * ViewGroups should override to route to their children.
11784      *
11785      * @param hasFocus True if the window containing this view now has focus,
11786      *        false otherwise.
11787      */
11788     public void dispatchWindowFocusChanged(boolean hasFocus) {
11789         onWindowFocusChanged(hasFocus);
11790     }
11791
11792     /**
11793      * Called when the window containing this view gains or loses focus.  Note
11794      * that this is separate from view focus: to receive key events, both
11795      * your view and its window must have focus.  If a window is displayed
11796      * on top of yours that takes input focus, then your own window will lose
11797      * focus but the view focus will remain unchanged.
11798      *
11799      * @param hasWindowFocus True if the window containing this view now has
11800      *        focus, false otherwise.
11801      */
11802     public void onWindowFocusChanged(boolean hasWindowFocus) {
11803         InputMethodManager imm = InputMethodManager.peekInstance();
11804         if (!hasWindowFocus) {
11805             if (isPressed()) {
11806                 setPressed(false);
11807             }
11808             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11809             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11810                 imm.focusOut(this);
11811             }
11812             removeLongPressCallback();
11813             removeTapCallback();
11814             onFocusLost();
11815         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11816             imm.focusIn(this);
11817         }
11818
11819         notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11820
11821         refreshDrawableState();
11822     }
11823
11824     /**
11825      * Returns true if this view is in a window that currently has window focus.
11826      * Note that this is not the same as the view itself having focus.
11827      *
11828      * @return True if this view is in a window that currently has window focus.
11829      */
11830     public boolean hasWindowFocus() {
11831         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11832     }
11833
11834     /**
11835      * Dispatch a view visibility change down the view hierarchy.
11836      * ViewGroups should override to route to their children.
11837      * @param changedView The view whose visibility changed. Could be 'this' or
11838      * an ancestor view.
11839      * @param visibility The new visibility of changedView: {@link #VISIBLE},
11840      * {@link #INVISIBLE} or {@link #GONE}.
11841      */
11842     protected void dispatchVisibilityChanged(@NonNull View changedView,
11843             @Visibility int visibility) {
11844         onVisibilityChanged(changedView, visibility);
11845     }
11846
11847     /**
11848      * Called when the visibility of the view or an ancestor of the view has
11849      * changed.
11850      *
11851      * @param changedView The view whose visibility changed. May be
11852      *                    {@code this} or an ancestor view.
11853      * @param visibility The new visibility, one of {@link #VISIBLE},
11854      *                   {@link #INVISIBLE} or {@link #GONE}.
11855      */
11856     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11857     }
11858
11859     /**
11860      * Dispatch a hint about whether this view is displayed. For instance, when
11861      * a View moves out of the screen, it might receives a display hint indicating
11862      * the view is not displayed. Applications should not <em>rely</em> on this hint
11863      * as there is no guarantee that they will receive one.
11864      *
11865      * @param hint A hint about whether or not this view is displayed:
11866      * {@link #VISIBLE} or {@link #INVISIBLE}.
11867      */
11868     public void dispatchDisplayHint(@Visibility int hint) {
11869         onDisplayHint(hint);
11870     }
11871
11872     /**
11873      * Gives this view a hint about whether is displayed or not. For instance, when
11874      * a View moves out of the screen, it might receives a display hint indicating
11875      * the view is not displayed. Applications should not <em>rely</em> on this hint
11876      * as there is no guarantee that they will receive one.
11877      *
11878      * @param hint A hint about whether or not this view is displayed:
11879      * {@link #VISIBLE} or {@link #INVISIBLE}.
11880      */
11881     protected void onDisplayHint(@Visibility int hint) {
11882     }
11883
11884     /**
11885      * Dispatch a window visibility change down the view hierarchy.
11886      * ViewGroups should override to route to their children.
11887      *
11888      * @param visibility The new visibility of the window.
11889      *
11890      * @see #onWindowVisibilityChanged(int)
11891      */
11892     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11893         onWindowVisibilityChanged(visibility);
11894     }
11895
11896     /**
11897      * Called when the window containing has change its visibility
11898      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11899      * that this tells you whether or not your window is being made visible
11900      * to the window manager; this does <em>not</em> tell you whether or not
11901      * your window is obscured by other windows on the screen, even if it
11902      * is itself visible.
11903      *
11904      * @param visibility The new visibility of the window.
11905      */
11906     protected void onWindowVisibilityChanged(@Visibility int visibility) {
11907         if (visibility == VISIBLE) {
11908             initialAwakenScrollBars();
11909         }
11910     }
11911
11912     /**
11913      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11914      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11915      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11916      *
11917      * @param isVisible true if this view's visibility to the user is uninterrupted by its
11918      *                  ancestors or by window visibility
11919      * @return true if this view is visible to the user, not counting clipping or overlapping
11920      */
11921     boolean dispatchVisibilityAggregated(boolean isVisible) {
11922         final boolean thisVisible = getVisibility() == VISIBLE;
11923         // If we're not visible but something is telling us we are, ignore it.
11924         if (thisVisible || !isVisible) {
11925             onVisibilityAggregated(isVisible);
11926         }
11927         return thisVisible && isVisible;
11928     }
11929
11930     /**
11931      * Called when the user-visibility of this View is potentially affected by a change
11932      * to this view itself, an ancestor view or the window this view is attached to.
11933      *
11934      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11935      *                  and this view's window is also visible
11936      */
11937     @CallSuper
11938     public void onVisibilityAggregated(boolean isVisible) {
11939         if (isVisible && mAttachInfo != null) {
11940             initialAwakenScrollBars();
11941         }
11942
11943         final Drawable dr = mBackground;
11944         if (dr != null && isVisible != dr.isVisible()) {
11945             dr.setVisible(isVisible, false);
11946         }
11947         final Drawable hl = mDefaultFocusHighlight;
11948         if (hl != null && isVisible != hl.isVisible()) {
11949             hl.setVisible(isVisible, false);
11950         }
11951         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11952         if (fg != null && isVisible != fg.isVisible()) {
11953             fg.setVisible(isVisible, false);
11954         }
11955
11956         if (isAutofillable()) {
11957             AutofillManager afm = getAutofillManager();
11958
11959             if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
11960                 if (mVisibilityChangeForAutofillHandler != null) {
11961                     mVisibilityChangeForAutofillHandler.removeMessages(0);
11962                 }
11963
11964                 // If the view is in the background but still part of the hierarchy this is called
11965                 // with isVisible=false. Hence visibility==false requires further checks
11966                 if (isVisible) {
11967                     afm.notifyViewVisibilityChange(this, true);
11968                 } else {
11969                     if (mVisibilityChangeForAutofillHandler == null) {
11970                         mVisibilityChangeForAutofillHandler =
11971                                 new VisibilityChangeForAutofillHandler(afm, this);
11972                     }
11973                     // Let current operation (e.g. removal of the view from the hierarchy)
11974                     // finish before checking state
11975                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
11976                 }
11977             }
11978         }
11979     }
11980
11981     /**
11982      * Returns the current visibility of the window this view is attached to
11983      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11984      *
11985      * @return Returns the current visibility of the view's window.
11986      */
11987     @Visibility
11988     public int getWindowVisibility() {
11989         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11990     }
11991
11992     /**
11993      * Retrieve the overall visible display size in which the window this view is
11994      * attached to has been positioned in.  This takes into account screen
11995      * decorations above the window, for both cases where the window itself
11996      * is being position inside of them or the window is being placed under
11997      * then and covered insets are used for the window to position its content
11998      * inside.  In effect, this tells you the available area where content can
11999      * be placed and remain visible to users.
12000      *
12001      * <p>This function requires an IPC back to the window manager to retrieve
12002      * the requested information, so should not be used in performance critical
12003      * code like drawing.
12004      *
12005      * @param outRect Filled in with the visible display frame.  If the view
12006      * is not attached to a window, this is simply the raw display size.
12007      */
12008     public void getWindowVisibleDisplayFrame(Rect outRect) {
12009         if (mAttachInfo != null) {
12010             try {
12011                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12012             } catch (RemoteException e) {
12013                 return;
12014             }
12015             // XXX This is really broken, and probably all needs to be done
12016             // in the window manager, and we need to know more about whether
12017             // we want the area behind or in front of the IME.
12018             final Rect insets = mAttachInfo.mVisibleInsets;
12019             outRect.left += insets.left;
12020             outRect.top += insets.top;
12021             outRect.right -= insets.right;
12022             outRect.bottom -= insets.bottom;
12023             return;
12024         }
12025         // The view is not attached to a display so we don't have a context.
12026         // Make a best guess about the display size.
12027         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12028         d.getRectSize(outRect);
12029     }
12030
12031     /**
12032      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
12033      * is currently in without any insets.
12034      *
12035      * @hide
12036      */
12037     public void getWindowDisplayFrame(Rect outRect) {
12038         if (mAttachInfo != null) {
12039             try {
12040                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12041             } catch (RemoteException e) {
12042                 return;
12043             }
12044             return;
12045         }
12046         // The view is not attached to a display so we don't have a context.
12047         // Make a best guess about the display size.
12048         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12049         d.getRectSize(outRect);
12050     }
12051
12052     /**
12053      * Dispatch a notification about a resource configuration change down
12054      * the view hierarchy.
12055      * ViewGroups should override to route to their children.
12056      *
12057      * @param newConfig The new resource configuration.
12058      *
12059      * @see #onConfigurationChanged(android.content.res.Configuration)
12060      */
12061     public void dispatchConfigurationChanged(Configuration newConfig) {
12062         onConfigurationChanged(newConfig);
12063     }
12064
12065     /**
12066      * Called when the current configuration of the resources being used
12067      * by the application have changed.  You can use this to decide when
12068      * to reload resources that can changed based on orientation and other
12069      * configuration characteristics.  You only need to use this if you are
12070      * not relying on the normal {@link android.app.Activity} mechanism of
12071      * recreating the activity instance upon a configuration change.
12072      *
12073      * @param newConfig The new resource configuration.
12074      */
12075     protected void onConfigurationChanged(Configuration newConfig) {
12076     }
12077
12078     /**
12079      * Private function to aggregate all per-view attributes in to the view
12080      * root.
12081      */
12082     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12083         performCollectViewAttributes(attachInfo, visibility);
12084     }
12085
12086     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12087         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
12088             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
12089                 attachInfo.mKeepScreenOn = true;
12090             }
12091             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
12092             ListenerInfo li = mListenerInfo;
12093             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
12094                 attachInfo.mHasSystemUiListeners = true;
12095             }
12096         }
12097     }
12098
12099     void needGlobalAttributesUpdate(boolean force) {
12100         final AttachInfo ai = mAttachInfo;
12101         if (ai != null && !ai.mRecomputeGlobalAttributes) {
12102             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
12103                     || ai.mHasSystemUiListeners) {
12104                 ai.mRecomputeGlobalAttributes = true;
12105             }
12106         }
12107     }
12108
12109     /**
12110      * Returns whether the device is currently in touch mode.  Touch mode is entered
12111      * once the user begins interacting with the device by touch, and affects various
12112      * things like whether focus is always visible to the user.
12113      *
12114      * @return Whether the device is in touch mode.
12115      */
12116     @ViewDebug.ExportedProperty
12117     public boolean isInTouchMode() {
12118         if (mAttachInfo != null) {
12119             return mAttachInfo.mInTouchMode;
12120         } else {
12121             return ViewRootImpl.isInTouchMode();
12122         }
12123     }
12124
12125     /**
12126      * Returns the context the view is running in, through which it can
12127      * access the current theme, resources, etc.
12128      *
12129      * @return The view's Context.
12130      */
12131     @ViewDebug.CapturedViewProperty
12132     public final Context getContext() {
12133         return mContext;
12134     }
12135
12136     /**
12137      * Handle a key event before it is processed by any input method
12138      * associated with the view hierarchy.  This can be used to intercept
12139      * key events in special situations before the IME consumes them; a
12140      * typical example would be handling the BACK key to update the application's
12141      * UI instead of allowing the IME to see it and close itself.
12142      *
12143      * @param keyCode The value in event.getKeyCode().
12144      * @param event Description of the key event.
12145      * @return If you handled the event, return true. If you want to allow the
12146      *         event to be handled by the next receiver, return false.
12147      */
12148     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
12149         return false;
12150     }
12151
12152     /**
12153      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
12154      * KeyEvent.Callback.onKeyDown()}: perform press of the view
12155      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
12156      * is released, if the view is enabled and clickable.
12157      * <p>
12158      * Key presses in software keyboards will generally NOT trigger this
12159      * listener, although some may elect to do so in some situations. Do not
12160      * rely on this to catch software key presses.
12161      *
12162      * @param keyCode a key code that represents the button pressed, from
12163      *                {@link android.view.KeyEvent}
12164      * @param event the KeyEvent object that defines the button action
12165      */
12166     public boolean onKeyDown(int keyCode, KeyEvent event) {
12167         if (KeyEvent.isConfirmKey(keyCode)) {
12168             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12169                 return true;
12170             }
12171
12172             if (event.getRepeatCount() == 0) {
12173                 // Long clickable items don't necessarily have to be clickable.
12174                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
12175                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12176                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
12177                     // For the purposes of menu anchoring and drawable hotspots,
12178                     // key events are considered to be at the center of the view.
12179                     final float x = getWidth() / 2f;
12180                     final float y = getHeight() / 2f;
12181                     if (clickable) {
12182                         setPressed(true, x, y);
12183                     }
12184                     checkForLongClick(0, x, y);
12185                     return true;
12186                 }
12187             }
12188         }
12189
12190         return false;
12191     }
12192
12193     /**
12194      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12195      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12196      * the event).
12197      * <p>Key presses in software keyboards will generally NOT trigger this listener,
12198      * although some may elect to do so in some situations. Do not rely on this to
12199      * catch software key presses.
12200      */
12201     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12202         return false;
12203     }
12204
12205     /**
12206      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12207      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12208      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12209      * or {@link KeyEvent#KEYCODE_SPACE} is released.
12210      * <p>Key presses in software keyboards will generally NOT trigger this listener,
12211      * although some may elect to do so in some situations. Do not rely on this to
12212      * catch software key presses.
12213      *
12214      * @param keyCode A key code that represents the button pressed, from
12215      *                {@link android.view.KeyEvent}.
12216      * @param event   The KeyEvent object that defines the button action.
12217      */
12218     public boolean onKeyUp(int keyCode, KeyEvent event) {
12219         if (KeyEvent.isConfirmKey(keyCode)) {
12220             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12221                 return true;
12222             }
12223             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12224                 setPressed(false);
12225
12226                 if (!mHasPerformedLongPress) {
12227                     // This is a tap, so remove the longpress check
12228                     removeLongPressCallback();
12229                     if (!event.isCanceled()) {
12230                         return performClick();
12231                     }
12232                 }
12233             }
12234         }
12235         return false;
12236     }
12237
12238     /**
12239      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12240      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12241      * the event).
12242      * <p>Key presses in software keyboards will generally NOT trigger this listener,
12243      * although some may elect to do so in some situations. Do not rely on this to
12244      * catch software key presses.
12245      *
12246      * @param keyCode     A key code that represents the button pressed, from
12247      *                    {@link android.view.KeyEvent}.
12248      * @param repeatCount The number of times the action was made.
12249      * @param event       The KeyEvent object that defines the button action.
12250      */
12251     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12252         return false;
12253     }
12254
12255     /**
12256      * Called on the focused view when a key shortcut event is not handled.
12257      * Override this method to implement local key shortcuts for the View.
12258      * Key shortcuts can also be implemented by setting the
12259      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12260      *
12261      * @param keyCode The value in event.getKeyCode().
12262      * @param event Description of the key event.
12263      * @return If you handled the event, return true. If you want to allow the
12264      *         event to be handled by the next receiver, return false.
12265      */
12266     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12267         return false;
12268     }
12269
12270     /**
12271      * Check whether the called view is a text editor, in which case it
12272      * would make sense to automatically display a soft input window for
12273      * it.  Subclasses should override this if they implement
12274      * {@link #onCreateInputConnection(EditorInfo)} to return true if
12275      * a call on that method would return a non-null InputConnection, and
12276      * they are really a first-class editor that the user would normally
12277      * start typing on when the go into a window containing your view.
12278      *
12279      * <p>The default implementation always returns false.  This does
12280      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12281      * will not be called or the user can not otherwise perform edits on your
12282      * view; it is just a hint to the system that this is not the primary
12283      * purpose of this view.
12284      *
12285      * @return Returns true if this view is a text editor, else false.
12286      */
12287     public boolean onCheckIsTextEditor() {
12288         return false;
12289     }
12290
12291     /**
12292      * Create a new InputConnection for an InputMethod to interact
12293      * with the view.  The default implementation returns null, since it doesn't
12294      * support input methods.  You can override this to implement such support.
12295      * This is only needed for views that take focus and text input.
12296      *
12297      * <p>When implementing this, you probably also want to implement
12298      * {@link #onCheckIsTextEditor()} to indicate you will return a
12299      * non-null InputConnection.</p>
12300      *
12301      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12302      * object correctly and in its entirety, so that the connected IME can rely
12303      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12304      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12305      * must be filled in with the correct cursor position for IMEs to work correctly
12306      * with your application.</p>
12307      *
12308      * @param outAttrs Fill in with attribute information about the connection.
12309      */
12310     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12311         return null;
12312     }
12313
12314     /**
12315      * Called by the {@link android.view.inputmethod.InputMethodManager}
12316      * when a view who is not the current
12317      * input connection target is trying to make a call on the manager.  The
12318      * default implementation returns false; you can override this to return
12319      * true for certain views if you are performing InputConnection proxying
12320      * to them.
12321      * @param view The View that is making the InputMethodManager call.
12322      * @return Return true to allow the call, false to reject.
12323      */
12324     public boolean checkInputConnectionProxy(View view) {
12325         return false;
12326     }
12327
12328     /**
12329      * Show the context menu for this view. It is not safe to hold on to the
12330      * menu after returning from this method.
12331      *
12332      * You should normally not overload this method. Overload
12333      * {@link #onCreateContextMenu(ContextMenu)} or define an
12334      * {@link OnCreateContextMenuListener} to add items to the context menu.
12335      *
12336      * @param menu The context menu to populate
12337      */
12338     public void createContextMenu(ContextMenu menu) {
12339         ContextMenuInfo menuInfo = getContextMenuInfo();
12340
12341         // Sets the current menu info so all items added to menu will have
12342         // my extra info set.
12343         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12344
12345         onCreateContextMenu(menu);
12346         ListenerInfo li = mListenerInfo;
12347         if (li != null && li.mOnCreateContextMenuListener != null) {
12348             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12349         }
12350
12351         // Clear the extra information so subsequent items that aren't mine don't
12352         // have my extra info.
12353         ((MenuBuilder)menu).setCurrentMenuInfo(null);
12354
12355         if (mParent != null) {
12356             mParent.createContextMenu(menu);
12357         }
12358     }
12359
12360     /**
12361      * Views should implement this if they have extra information to associate
12362      * with the context menu. The return result is supplied as a parameter to
12363      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12364      * callback.
12365      *
12366      * @return Extra information about the item for which the context menu
12367      *         should be shown. This information will vary across different
12368      *         subclasses of View.
12369      */
12370     protected ContextMenuInfo getContextMenuInfo() {
12371         return null;
12372     }
12373
12374     /**
12375      * Views should implement this if the view itself is going to add items to
12376      * the context menu.
12377      *
12378      * @param menu the context menu to populate
12379      */
12380     protected void onCreateContextMenu(ContextMenu menu) {
12381     }
12382
12383     /**
12384      * Implement this method to handle trackball motion events.  The
12385      * <em>relative</em> movement of the trackball since the last event
12386      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12387      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12388      * that a movement of 1 corresponds to the user pressing one DPAD key (so
12389      * they will often be fractional values, representing the more fine-grained
12390      * movement information available from a trackball).
12391      *
12392      * @param event The motion event.
12393      * @return True if the event was handled, false otherwise.
12394      */
12395     public boolean onTrackballEvent(MotionEvent event) {
12396         return false;
12397     }
12398
12399     /**
12400      * Implement this method to handle generic motion events.
12401      * <p>
12402      * Generic motion events describe joystick movements, mouse hovers, track pad
12403      * touches, scroll wheel movements and other input events.  The
12404      * {@link MotionEvent#getSource() source} of the motion event specifies
12405      * the class of input that was received.  Implementations of this method
12406      * must examine the bits in the source before processing the event.
12407      * The following code example shows how this is done.
12408      * </p><p>
12409      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12410      * are delivered to the view under the pointer.  All other generic motion events are
12411      * delivered to the focused view.
12412      * </p>
12413      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12414      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12415      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12416      *             // process the joystick movement...
12417      *             return true;
12418      *         }
12419      *     }
12420      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12421      *         switch (event.getAction()) {
12422      *             case MotionEvent.ACTION_HOVER_MOVE:
12423      *                 // process the mouse hover movement...
12424      *                 return true;
12425      *             case MotionEvent.ACTION_SCROLL:
12426      *                 // process the scroll wheel movement...
12427      *                 return true;
12428      *         }
12429      *     }
12430      *     return super.onGenericMotionEvent(event);
12431      * }</pre>
12432      *
12433      * @param event The generic motion event being processed.
12434      * @return True if the event was handled, false otherwise.
12435      */
12436     public boolean onGenericMotionEvent(MotionEvent event) {
12437         return false;
12438     }
12439
12440     /**
12441      * Implement this method to handle hover events.
12442      * <p>
12443      * This method is called whenever a pointer is hovering into, over, or out of the
12444      * bounds of a view and the view is not currently being touched.
12445      * Hover events are represented as pointer events with action
12446      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12447      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12448      * </p>
12449      * <ul>
12450      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12451      * when the pointer enters the bounds of the view.</li>
12452      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12453      * when the pointer has already entered the bounds of the view and has moved.</li>
12454      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12455      * when the pointer has exited the bounds of the view or when the pointer is
12456      * about to go down due to a button click, tap, or similar user action that
12457      * causes the view to be touched.</li>
12458      * </ul>
12459      * <p>
12460      * The view should implement this method to return true to indicate that it is
12461      * handling the hover event, such as by changing its drawable state.
12462      * </p><p>
12463      * The default implementation calls {@link #setHovered} to update the hovered state
12464      * of the view when a hover enter or hover exit event is received, if the view
12465      * is enabled and is clickable.  The default implementation also sends hover
12466      * accessibility events.
12467      * </p>
12468      *
12469      * @param event The motion event that describes the hover.
12470      * @return True if the view handled the hover event.
12471      *
12472      * @see #isHovered
12473      * @see #setHovered
12474      * @see #onHoverChanged
12475      */
12476     public boolean onHoverEvent(MotionEvent event) {
12477         // The root view may receive hover (or touch) events that are outside the bounds of
12478         // the window.  This code ensures that we only send accessibility events for
12479         // hovers that are actually within the bounds of the root view.
12480         final int action = event.getActionMasked();
12481         if (!mSendingHoverAccessibilityEvents) {
12482             if ((action == MotionEvent.ACTION_HOVER_ENTER
12483                     || action == MotionEvent.ACTION_HOVER_MOVE)
12484                     && !hasHoveredChild()
12485                     && pointInView(event.getX(), event.getY())) {
12486                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12487                 mSendingHoverAccessibilityEvents = true;
12488             }
12489         } else {
12490             if (action == MotionEvent.ACTION_HOVER_EXIT
12491                     || (action == MotionEvent.ACTION_MOVE
12492                             && !pointInView(event.getX(), event.getY()))) {
12493                 mSendingHoverAccessibilityEvents = false;
12494                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12495             }
12496         }
12497
12498         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12499                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
12500                 && isOnScrollbar(event.getX(), event.getY())) {
12501             awakenScrollBars();
12502         }
12503
12504         // If we consider ourself hoverable, or if we we're already hovered,
12505         // handle changing state in response to ENTER and EXIT events.
12506         if (isHoverable() || isHovered()) {
12507             switch (action) {
12508                 case MotionEvent.ACTION_HOVER_ENTER:
12509                     setHovered(true);
12510                     break;
12511                 case MotionEvent.ACTION_HOVER_EXIT:
12512                     setHovered(false);
12513                     break;
12514             }
12515
12516             // Dispatch the event to onGenericMotionEvent before returning true.
12517             // This is to provide compatibility with existing applications that
12518             // handled HOVER_MOVE events in onGenericMotionEvent and that would
12519             // break because of the new default handling for hoverable views
12520             // in onHoverEvent.
12521             // Note that onGenericMotionEvent will be called by default when
12522             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12523             dispatchGenericMotionEventInternal(event);
12524             // The event was already handled by calling setHovered(), so always
12525             // return true.
12526             return true;
12527         }
12528
12529         return false;
12530     }
12531
12532     /**
12533      * Returns true if the view should handle {@link #onHoverEvent}
12534      * by calling {@link #setHovered} to change its hovered state.
12535      *
12536      * @return True if the view is hoverable.
12537      */
12538     private boolean isHoverable() {
12539         final int viewFlags = mViewFlags;
12540         if ((viewFlags & ENABLED_MASK) == DISABLED) {
12541             return false;
12542         }
12543
12544         return (viewFlags & CLICKABLE) == CLICKABLE
12545                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12546                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12547     }
12548
12549     /**
12550      * Returns true if the view is currently hovered.
12551      *
12552      * @return True if the view is currently hovered.
12553      *
12554      * @see #setHovered
12555      * @see #onHoverChanged
12556      */
12557     @ViewDebug.ExportedProperty
12558     public boolean isHovered() {
12559         return (mPrivateFlags & PFLAG_HOVERED) != 0;
12560     }
12561
12562     /**
12563      * Sets whether the view is currently hovered.
12564      * <p>
12565      * Calling this method also changes the drawable state of the view.  This
12566      * enables the view to react to hover by using different drawable resources
12567      * to change its appearance.
12568      * </p><p>
12569      * The {@link #onHoverChanged} method is called when the hovered state changes.
12570      * </p>
12571      *
12572      * @param hovered True if the view is hovered.
12573      *
12574      * @see #isHovered
12575      * @see #onHoverChanged
12576      */
12577     public void setHovered(boolean hovered) {
12578         if (hovered) {
12579             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12580                 mPrivateFlags |= PFLAG_HOVERED;
12581                 refreshDrawableState();
12582                 onHoverChanged(true);
12583             }
12584         } else {
12585             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12586                 mPrivateFlags &= ~PFLAG_HOVERED;
12587                 refreshDrawableState();
12588                 onHoverChanged(false);
12589             }
12590         }
12591     }
12592
12593     /**
12594      * Implement this method to handle hover state changes.
12595      * <p>
12596      * This method is called whenever the hover state changes as a result of a
12597      * call to {@link #setHovered}.
12598      * </p>
12599      *
12600      * @param hovered The current hover state, as returned by {@link #isHovered}.
12601      *
12602      * @see #isHovered
12603      * @see #setHovered
12604      */
12605     public void onHoverChanged(boolean hovered) {
12606     }
12607
12608     /**
12609      * Handles scroll bar dragging by mouse input.
12610      *
12611      * @hide
12612      * @param event The motion event.
12613      *
12614      * @return true if the event was handled as a scroll bar dragging, false otherwise.
12615      */
12616     protected boolean handleScrollBarDragging(MotionEvent event) {
12617         if (mScrollCache == null) {
12618             return false;
12619         }
12620         final float x = event.getX();
12621         final float y = event.getY();
12622         final int action = event.getAction();
12623         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12624                 && action != MotionEvent.ACTION_DOWN)
12625                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12626                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12627             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12628             return false;
12629         }
12630
12631         switch (action) {
12632             case MotionEvent.ACTION_MOVE:
12633                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12634                     return false;
12635                 }
12636                 if (mScrollCache.mScrollBarDraggingState
12637                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12638                     final Rect bounds = mScrollCache.mScrollBarBounds;
12639                     getVerticalScrollBarBounds(bounds, null);
12640                     final int range = computeVerticalScrollRange();
12641                     final int offset = computeVerticalScrollOffset();
12642                     final int extent = computeVerticalScrollExtent();
12643
12644                     final int thumbLength = ScrollBarUtils.getThumbLength(
12645                             bounds.height(), bounds.width(), extent, range);
12646                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
12647                             bounds.height(), thumbLength, extent, range, offset);
12648
12649                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
12650                     final float maxThumbOffset = bounds.height() - thumbLength;
12651                     final float newThumbOffset =
12652                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12653                     final int height = getHeight();
12654                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12655                             && height > 0 && extent > 0) {
12656                         final int newY = Math.round((range - extent)
12657                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12658                         if (newY != getScrollY()) {
12659                             mScrollCache.mScrollBarDraggingPos = y;
12660                             setScrollY(newY);
12661                         }
12662                     }
12663                     return true;
12664                 }
12665                 if (mScrollCache.mScrollBarDraggingState
12666                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12667                     final Rect bounds = mScrollCache.mScrollBarBounds;
12668                     getHorizontalScrollBarBounds(bounds, null);
12669                     final int range = computeHorizontalScrollRange();
12670                     final int offset = computeHorizontalScrollOffset();
12671                     final int extent = computeHorizontalScrollExtent();
12672
12673                     final int thumbLength = ScrollBarUtils.getThumbLength(
12674                             bounds.width(), bounds.height(), extent, range);
12675                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
12676                             bounds.width(), thumbLength, extent, range, offset);
12677
12678                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
12679                     final float maxThumbOffset = bounds.width() - thumbLength;
12680                     final float newThumbOffset =
12681                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12682                     final int width = getWidth();
12683                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12684                             && width > 0 && extent > 0) {
12685                         final int newX = Math.round((range - extent)
12686                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12687                         if (newX != getScrollX()) {
12688                             mScrollCache.mScrollBarDraggingPos = x;
12689                             setScrollX(newX);
12690                         }
12691                     }
12692                     return true;
12693                 }
12694             case MotionEvent.ACTION_DOWN:
12695                 if (mScrollCache.state == ScrollabilityCache.OFF) {
12696                     return false;
12697                 }
12698                 if (isOnVerticalScrollbarThumb(x, y)) {
12699                     mScrollCache.mScrollBarDraggingState =
12700                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12701                     mScrollCache.mScrollBarDraggingPos = y;
12702                     return true;
12703                 }
12704                 if (isOnHorizontalScrollbarThumb(x, y)) {
12705                     mScrollCache.mScrollBarDraggingState =
12706                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12707                     mScrollCache.mScrollBarDraggingPos = x;
12708                     return true;
12709                 }
12710         }
12711         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12712         return false;
12713     }
12714
12715     /**
12716      * Implement this method to handle touch screen motion events.
12717      * <p>
12718      * If this method is used to detect click actions, it is recommended that
12719      * the actions be performed by implementing and calling
12720      * {@link #performClick()}. This will ensure consistent system behavior,
12721      * including:
12722      * <ul>
12723      * <li>obeying click sound preferences
12724      * <li>dispatching OnClickListener calls
12725      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12726      * accessibility features are enabled
12727      * </ul>
12728      *
12729      * @param event The motion event.
12730      * @return True if the event was handled, false otherwise.
12731      */
12732     public boolean onTouchEvent(MotionEvent event) {
12733         final float x = event.getX();
12734         final float y = event.getY();
12735         final int viewFlags = mViewFlags;
12736         final int action = event.getAction();
12737
12738         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12739                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12740                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12741
12742         if ((viewFlags & ENABLED_MASK) == DISABLED) {
12743             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12744                 setPressed(false);
12745             }
12746             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12747             // A disabled view that is clickable still consumes the touch
12748             // events, it just doesn't respond to them.
12749             return clickable;
12750         }
12751         if (mTouchDelegate != null) {
12752             if (mTouchDelegate.onTouchEvent(event)) {
12753                 return true;
12754             }
12755         }
12756
12757         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12758             switch (action) {
12759                 case MotionEvent.ACTION_UP:
12760                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12761                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
12762                         handleTooltipUp();
12763                     }
12764                     if (!clickable) {
12765                         removeTapCallback();
12766                         removeLongPressCallback();
12767                         mInContextButtonPress = false;
12768                         mHasPerformedLongPress = false;
12769                         mIgnoreNextUpEvent = false;
12770                         break;
12771                     }
12772                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12773                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12774                         // take focus if we don't have it already and we should in
12775                         // touch mode.
12776                         boolean focusTaken = false;
12777                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12778                             focusTaken = requestFocus();
12779                         }
12780
12781                         if (prepressed) {
12782                             // The button is being released before we actually
12783                             // showed it as pressed.  Make it show the pressed
12784                             // state now (before scheduling the click) to ensure
12785                             // the user sees it.
12786                             setPressed(true, x, y);
12787                         }
12788
12789                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12790                             // This is a tap, so remove the longpress check
12791                             removeLongPressCallback();
12792
12793                             // Only perform take click actions if we were in the pressed state
12794                             if (!focusTaken) {
12795                                 // Use a Runnable and post this rather than calling
12796                                 // performClick directly. This lets other visual state
12797                                 // of the view update before click actions start.
12798                                 if (mPerformClick == null) {
12799                                     mPerformClick = new PerformClick();
12800                                 }
12801                                 if (!post(mPerformClick)) {
12802                                     performClick();
12803                                 }
12804                             }
12805                         }
12806
12807                         if (mUnsetPressedState == null) {
12808                             mUnsetPressedState = new UnsetPressedState();
12809                         }
12810
12811                         if (prepressed) {
12812                             postDelayed(mUnsetPressedState,
12813                                     ViewConfiguration.getPressedStateDuration());
12814                         } else if (!post(mUnsetPressedState)) {
12815                             // If the post failed, unpress right now
12816                             mUnsetPressedState.run();
12817                         }
12818
12819                         removeTapCallback();
12820                     }
12821                     mIgnoreNextUpEvent = false;
12822                     break;
12823
12824                 case MotionEvent.ACTION_DOWN:
12825                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12826                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12827                     }
12828                     mHasPerformedLongPress = false;
12829
12830                     if (!clickable) {
12831                         checkForLongClick(0, x, y);
12832                         break;
12833                     }
12834
12835                     if (performButtonActionOnTouchDown(event)) {
12836                         break;
12837                     }
12838
12839                     // Walk up the hierarchy to determine if we're inside a scrolling container.
12840                     boolean isInScrollingContainer = isInScrollingContainer();
12841
12842                     // For views inside a scrolling container, delay the pressed feedback for
12843                     // a short period in case this is a scroll.
12844                     if (isInScrollingContainer) {
12845                         mPrivateFlags |= PFLAG_PREPRESSED;
12846                         if (mPendingCheckForTap == null) {
12847                             mPendingCheckForTap = new CheckForTap();
12848                         }
12849                         mPendingCheckForTap.x = event.getX();
12850                         mPendingCheckForTap.y = event.getY();
12851                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12852                     } else {
12853                         // Not inside a scrolling container, so show the feedback right away
12854                         setPressed(true, x, y);
12855                         checkForLongClick(0, x, y);
12856                     }
12857                     break;
12858
12859                 case MotionEvent.ACTION_CANCEL:
12860                     if (clickable) {
12861                         setPressed(false);
12862                     }
12863                     removeTapCallback();
12864                     removeLongPressCallback();
12865                     mInContextButtonPress = false;
12866                     mHasPerformedLongPress = false;
12867                     mIgnoreNextUpEvent = false;
12868                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12869                     break;
12870
12871                 case MotionEvent.ACTION_MOVE:
12872                     if (clickable) {
12873                         drawableHotspotChanged(x, y);
12874                     }
12875
12876                     // Be lenient about moving outside of buttons
12877                     if (!pointInView(x, y, mTouchSlop)) {
12878                         // Outside button
12879                         // Remove any future long press/tap checks
12880                         removeTapCallback();
12881                         removeLongPressCallback();
12882                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12883                             setPressed(false);
12884                         }
12885                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12886                     }
12887                     break;
12888             }
12889
12890             return true;
12891         }
12892
12893         return false;
12894     }
12895
12896     /**
12897      * @hide
12898      */
12899     public boolean isInScrollingContainer() {
12900         ViewParent p = getParent();
12901         while (p != null && p instanceof ViewGroup) {
12902             if (((ViewGroup) p).shouldDelayChildPressedState()) {
12903                 return true;
12904             }
12905             p = p.getParent();
12906         }
12907         return false;
12908     }
12909
12910     /**
12911      * Remove the longpress detection timer.
12912      */
12913     private void removeLongPressCallback() {
12914         if (mPendingCheckForLongPress != null) {
12915             removeCallbacks(mPendingCheckForLongPress);
12916         }
12917     }
12918
12919     /**
12920      * Remove the pending click action
12921      */
12922     private void removePerformClickCallback() {
12923         if (mPerformClick != null) {
12924             removeCallbacks(mPerformClick);
12925         }
12926     }
12927
12928     /**
12929      * Remove the prepress detection timer.
12930      */
12931     private void removeUnsetPressCallback() {
12932         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12933             setPressed(false);
12934             removeCallbacks(mUnsetPressedState);
12935         }
12936     }
12937
12938     /**
12939      * Remove the tap detection timer.
12940      */
12941     private void removeTapCallback() {
12942         if (mPendingCheckForTap != null) {
12943             mPrivateFlags &= ~PFLAG_PREPRESSED;
12944             removeCallbacks(mPendingCheckForTap);
12945         }
12946     }
12947
12948     /**
12949      * Cancels a pending long press.  Your subclass can use this if you
12950      * want the context menu to come up if the user presses and holds
12951      * at the same place, but you don't want it to come up if they press
12952      * and then move around enough to cause scrolling.
12953      */
12954     public void cancelLongPress() {
12955         removeLongPressCallback();
12956
12957         /*
12958          * The prepressed state handled by the tap callback is a display
12959          * construct, but the tap callback will post a long press callback
12960          * less its own timeout. Remove it here.
12961          */
12962         removeTapCallback();
12963     }
12964
12965     /**
12966      * Remove the pending callback for sending a
12967      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12968      */
12969     private void removeSendViewScrolledAccessibilityEventCallback() {
12970         if (mSendViewScrolledAccessibilityEvent != null) {
12971             removeCallbacks(mSendViewScrolledAccessibilityEvent);
12972             mSendViewScrolledAccessibilityEvent.mIsPending = false;
12973         }
12974     }
12975
12976     /**
12977      * Sets the TouchDelegate for this View.
12978      */
12979     public void setTouchDelegate(TouchDelegate delegate) {
12980         mTouchDelegate = delegate;
12981     }
12982
12983     /**
12984      * Gets the TouchDelegate for this View.
12985      */
12986     public TouchDelegate getTouchDelegate() {
12987         return mTouchDelegate;
12988     }
12989
12990     /**
12991      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12992      *
12993      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12994      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12995      * available. This method should only be called for touch events.
12996      *
12997      * <p class="note">This api is not intended for most applications. Buffered dispatch
12998      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12999      * streams will not improve your input latency. Side effects include: increased latency,
13000      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
13001      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
13002      * you.</p>
13003      */
13004     public final void requestUnbufferedDispatch(MotionEvent event) {
13005         final int action = event.getAction();
13006         if (mAttachInfo == null
13007                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
13008                 || !event.isTouchEvent()) {
13009             return;
13010         }
13011         mAttachInfo.mUnbufferedDispatchRequested = true;
13012     }
13013
13014     /**
13015      * Set flags controlling behavior of this view.
13016      *
13017      * @param flags Constant indicating the value which should be set
13018      * @param mask Constant indicating the bit range that should be changed
13019      */
13020     void setFlags(int flags, int mask) {
13021         final boolean accessibilityEnabled =
13022                 AccessibilityManager.getInstance(mContext).isEnabled();
13023         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
13024
13025         int old = mViewFlags;
13026         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
13027
13028         int changed = mViewFlags ^ old;
13029         if (changed == 0) {
13030             return;
13031         }
13032         int privateFlags = mPrivateFlags;
13033
13034         // If focusable is auto, update the FOCUSABLE bit.
13035         int focusableChangedByAuto = 0;
13036         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
13037                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
13038             // Heuristic only takes into account whether view is clickable.
13039             final int newFocus;
13040             if ((mViewFlags & CLICKABLE) != 0) {
13041                 newFocus = FOCUSABLE;
13042             } else {
13043                 newFocus = NOT_FOCUSABLE;
13044             }
13045             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
13046             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
13047             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
13048         }
13049
13050         /* Check if the FOCUSABLE bit has changed */
13051         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
13052             if (((old & FOCUSABLE) == FOCUSABLE)
13053                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
13054                 /* Give up focus if we are no longer focusable */
13055                 clearFocus();
13056             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
13057                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
13058                 /*
13059                  * Tell the view system that we are now available to take focus
13060                  * if no one else already has it.
13061                  */
13062                 if (mParent != null) {
13063                     ViewRootImpl viewRootImpl = getViewRootImpl();
13064                     if (!sAutoFocusableOffUIThreadWontNotifyParents
13065                             || focusableChangedByAuto == 0
13066                             || viewRootImpl == null
13067                             || viewRootImpl.mThread == Thread.currentThread()) {
13068                         mParent.focusableViewAvailable(this);
13069                     }
13070                 }
13071             }
13072         }
13073
13074         final int newVisibility = flags & VISIBILITY_MASK;
13075         if (newVisibility == VISIBLE) {
13076             if ((changed & VISIBILITY_MASK) != 0) {
13077                 /*
13078                  * If this view is becoming visible, invalidate it in case it changed while
13079                  * it was not visible. Marking it drawn ensures that the invalidation will
13080                  * go through.
13081                  */
13082                 mPrivateFlags |= PFLAG_DRAWN;
13083                 invalidate(true);
13084
13085                 needGlobalAttributesUpdate(true);
13086
13087                 // a view becoming visible is worth notifying the parent
13088                 // about in case nothing has focus.  even if this specific view
13089                 // isn't focusable, it may contain something that is, so let
13090                 // the root view try to give this focus if nothing else does.
13091                 if ((mParent != null)) {
13092                     mParent.focusableViewAvailable(this);
13093                 }
13094             }
13095         }
13096
13097         /* Check if the GONE bit has changed */
13098         if ((changed & GONE) != 0) {
13099             needGlobalAttributesUpdate(false);
13100             requestLayout();
13101
13102             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
13103                 if (hasFocus()) clearFocus();
13104                 clearAccessibilityFocus();
13105                 destroyDrawingCache();
13106                 if (mParent instanceof View) {
13107                     // GONE views noop invalidation, so invalidate the parent
13108                     ((View) mParent).invalidate(true);
13109                 }
13110                 // Mark the view drawn to ensure that it gets invalidated properly the next
13111                 // time it is visible and gets invalidated
13112                 mPrivateFlags |= PFLAG_DRAWN;
13113             }
13114             if (mAttachInfo != null) {
13115                 mAttachInfo.mViewVisibilityChanged = true;
13116             }
13117         }
13118
13119         /* Check if the VISIBLE bit has changed */
13120         if ((changed & INVISIBLE) != 0) {
13121             needGlobalAttributesUpdate(false);
13122             /*
13123              * If this view is becoming invisible, set the DRAWN flag so that
13124              * the next invalidate() will not be skipped.
13125              */
13126             mPrivateFlags |= PFLAG_DRAWN;
13127
13128             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
13129                 // root view becoming invisible shouldn't clear focus and accessibility focus
13130                 if (getRootView() != this) {
13131                     if (hasFocus()) clearFocus();
13132                     clearAccessibilityFocus();
13133                 }
13134             }
13135             if (mAttachInfo != null) {
13136                 mAttachInfo.mViewVisibilityChanged = true;
13137             }
13138         }
13139
13140         if ((changed & VISIBILITY_MASK) != 0) {
13141             // If the view is invisible, cleanup its display list to free up resources
13142             if (newVisibility != VISIBLE && mAttachInfo != null) {
13143                 cleanupDraw();
13144             }
13145
13146             if (mParent instanceof ViewGroup) {
13147                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
13148                         (changed & VISIBILITY_MASK), newVisibility);
13149                 ((View) mParent).invalidate(true);
13150             } else if (mParent != null) {
13151                 mParent.invalidateChild(this, null);
13152             }
13153
13154             if (mAttachInfo != null) {
13155                 dispatchVisibilityChanged(this, newVisibility);
13156
13157                 // Aggregated visibility changes are dispatched to attached views
13158                 // in visible windows where the parent is currently shown/drawn
13159                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
13160                 // discounting clipping or overlapping. This makes it a good place
13161                 // to change animation states.
13162                 if (mParent != null && getWindowVisibility() == VISIBLE &&
13163                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
13164                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
13165                 }
13166                 notifySubtreeAccessibilityStateChangedIfNeeded();
13167             }
13168         }
13169
13170         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
13171             destroyDrawingCache();
13172         }
13173
13174         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
13175             destroyDrawingCache();
13176             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13177             invalidateParentCaches();
13178         }
13179
13180         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
13181             destroyDrawingCache();
13182             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13183         }
13184
13185         if ((changed & DRAW_MASK) != 0) {
13186             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13187                 if (mBackground != null
13188                         || mDefaultFocusHighlight != null
13189                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13190                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13191                 } else {
13192                     mPrivateFlags |= PFLAG_SKIP_DRAW;
13193                 }
13194             } else {
13195                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13196             }
13197             requestLayout();
13198             invalidate(true);
13199         }
13200
13201         if ((changed & KEEP_SCREEN_ON) != 0) {
13202             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13203                 mParent.recomputeViewAttributes(this);
13204             }
13205         }
13206
13207         if (accessibilityEnabled) {
13208             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13209                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13210                     || (changed & CONTEXT_CLICKABLE) != 0) {
13211                 if (oldIncludeForAccessibility != includeForAccessibility()) {
13212                     notifySubtreeAccessibilityStateChangedIfNeeded();
13213                 } else {
13214                     notifyViewAccessibilityStateChangedIfNeeded(
13215                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13216                 }
13217             } else if ((changed & ENABLED_MASK) != 0) {
13218                 notifyViewAccessibilityStateChangedIfNeeded(
13219                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13220             }
13221         }
13222     }
13223
13224     /**
13225      * Change the view's z order in the tree, so it's on top of other sibling
13226      * views. This ordering change may affect layout, if the parent container
13227      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13228      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13229      * method should be followed by calls to {@link #requestLayout()} and
13230      * {@link View#invalidate()} on the view's parent to force the parent to redraw
13231      * with the new child ordering.
13232      *
13233      * @see ViewGroup#bringChildToFront(View)
13234      */
13235     public void bringToFront() {
13236         if (mParent != null) {
13237             mParent.bringChildToFront(this);
13238         }
13239     }
13240
13241     /**
13242      * This is called in response to an internal scroll in this view (i.e., the
13243      * view scrolled its own contents). This is typically as a result of
13244      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13245      * called.
13246      *
13247      * @param l Current horizontal scroll origin.
13248      * @param t Current vertical scroll origin.
13249      * @param oldl Previous horizontal scroll origin.
13250      * @param oldt Previous vertical scroll origin.
13251      */
13252     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13253         notifySubtreeAccessibilityStateChangedIfNeeded();
13254
13255         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13256             postSendViewScrolledAccessibilityEventCallback();
13257         }
13258
13259         mBackgroundSizeChanged = true;
13260         mDefaultFocusHighlightSizeChanged = true;
13261         if (mForegroundInfo != null) {
13262             mForegroundInfo.mBoundsChanged = true;
13263         }
13264
13265         final AttachInfo ai = mAttachInfo;
13266         if (ai != null) {
13267             ai.mViewScrollChanged = true;
13268         }
13269
13270         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13271             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13272         }
13273     }
13274
13275     /**
13276      * Interface definition for a callback to be invoked when the scroll
13277      * X or Y positions of a view change.
13278      * <p>
13279      * <b>Note:</b> Some views handle scrolling independently from View and may
13280      * have their own separate listeners for scroll-type events. For example,
13281      * {@link android.widget.ListView ListView} allows clients to register an
13282      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13283      * to listen for changes in list scroll position.
13284      *
13285      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13286      */
13287     public interface OnScrollChangeListener {
13288         /**
13289          * Called when the scroll position of a view changes.
13290          *
13291          * @param v The view whose scroll position has changed.
13292          * @param scrollX Current horizontal scroll origin.
13293          * @param scrollY Current vertical scroll origin.
13294          * @param oldScrollX Previous horizontal scroll origin.
13295          * @param oldScrollY Previous vertical scroll origin.
13296          */
13297         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13298     }
13299
13300     /**
13301      * Interface definition for a callback to be invoked when the layout bounds of a view
13302      * changes due to layout processing.
13303      */
13304     public interface OnLayoutChangeListener {
13305         /**
13306          * Called when the layout bounds of a view changes due to layout processing.
13307          *
13308          * @param v The view whose bounds have changed.
13309          * @param left The new value of the view's left property.
13310          * @param top The new value of the view's top property.
13311          * @param right The new value of the view's right property.
13312          * @param bottom The new value of the view's bottom property.
13313          * @param oldLeft The previous value of the view's left property.
13314          * @param oldTop The previous value of the view's top property.
13315          * @param oldRight The previous value of the view's right property.
13316          * @param oldBottom The previous value of the view's bottom property.
13317          */
13318         void onLayoutChange(View v, int left, int top, int right, int bottom,
13319             int oldLeft, int oldTop, int oldRight, int oldBottom);
13320     }
13321
13322     /**
13323      * This is called during layout when the size of this view has changed. If
13324      * you were just added to the view hierarchy, you're called with the old
13325      * values of 0.
13326      *
13327      * @param w Current width of this view.
13328      * @param h Current height of this view.
13329      * @param oldw Old width of this view.
13330      * @param oldh Old height of this view.
13331      */
13332     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13333     }
13334
13335     /**
13336      * Called by draw to draw the child views. This may be overridden
13337      * by derived classes to gain control just before its children are drawn
13338      * (but after its own view has been drawn).
13339      * @param canvas the canvas on which to draw the view
13340      */
13341     protected void dispatchDraw(Canvas canvas) {
13342
13343     }
13344
13345     /**
13346      * Gets the parent of this view. Note that the parent is a
13347      * ViewParent and not necessarily a View.
13348      *
13349      * @return Parent of this view.
13350      */
13351     public final ViewParent getParent() {
13352         return mParent;
13353     }
13354
13355     /**
13356      * Set the horizontal scrolled position of your view. This will cause a call to
13357      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13358      * invalidated.
13359      * @param value the x position to scroll to
13360      */
13361     public void setScrollX(int value) {
13362         scrollTo(value, mScrollY);
13363     }
13364
13365     /**
13366      * Set the vertical scrolled position of your view. This will cause a call to
13367      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13368      * invalidated.
13369      * @param value the y position to scroll to
13370      */
13371     public void setScrollY(int value) {
13372         scrollTo(mScrollX, value);
13373     }
13374
13375     /**
13376      * Return the scrolled left position of this view. This is the left edge of
13377      * the displayed part of your view. You do not need to draw any pixels
13378      * farther left, since those are outside of the frame of your view on
13379      * screen.
13380      *
13381      * @return The left edge of the displayed part of your view, in pixels.
13382      */
13383     public final int getScrollX() {
13384         return mScrollX;
13385     }
13386
13387     /**
13388      * Return the scrolled top position of this view. This is the top edge of
13389      * the displayed part of your view. You do not need to draw any pixels above
13390      * it, since those are outside of the frame of your view on screen.
13391      *
13392      * @return The top edge of the displayed part of your view, in pixels.
13393      */
13394     public final int getScrollY() {
13395         return mScrollY;
13396     }
13397
13398     /**
13399      * Return the width of the your view.
13400      *
13401      * @return The width of your view, in pixels.
13402      */
13403     @ViewDebug.ExportedProperty(category = "layout")
13404     public final int getWidth() {
13405         return mRight - mLeft;
13406     }
13407
13408     /**
13409      * Return the height of your view.
13410      *
13411      * @return The height of your view, in pixels.
13412      */
13413     @ViewDebug.ExportedProperty(category = "layout")
13414     public final int getHeight() {
13415         return mBottom - mTop;
13416     }
13417
13418     /**
13419      * Return the visible drawing bounds of your view. Fills in the output
13420      * rectangle with the values from getScrollX(), getScrollY(),
13421      * getWidth(), and getHeight(). These bounds do not account for any
13422      * transformation properties currently set on the view, such as
13423      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13424      *
13425      * @param outRect The (scrolled) drawing bounds of the view.
13426      */
13427     public void getDrawingRect(Rect outRect) {
13428         outRect.left = mScrollX;
13429         outRect.top = mScrollY;
13430         outRect.right = mScrollX + (mRight - mLeft);
13431         outRect.bottom = mScrollY + (mBottom - mTop);
13432     }
13433
13434     /**
13435      * Like {@link #getMeasuredWidthAndState()}, but only returns the
13436      * raw width component (that is the result is masked by
13437      * {@link #MEASURED_SIZE_MASK}).
13438      *
13439      * @return The raw measured width of this view.
13440      */
13441     public final int getMeasuredWidth() {
13442         return mMeasuredWidth & MEASURED_SIZE_MASK;
13443     }
13444
13445     /**
13446      * Return the full width measurement information for this view as computed
13447      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13448      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13449      * This should be used during measurement and layout calculations only. Use
13450      * {@link #getWidth()} to see how wide a view is after layout.
13451      *
13452      * @return The measured width of this view as a bit mask.
13453      */
13454     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13455             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13456                     name = "MEASURED_STATE_TOO_SMALL"),
13457     })
13458     public final int getMeasuredWidthAndState() {
13459         return mMeasuredWidth;
13460     }
13461
13462     /**
13463      * Like {@link #getMeasuredHeightAndState()}, but only returns the
13464      * raw height component (that is the result is masked by
13465      * {@link #MEASURED_SIZE_MASK}).
13466      *
13467      * @return The raw measured height of this view.
13468      */
13469     public final int getMeasuredHeight() {
13470         return mMeasuredHeight & MEASURED_SIZE_MASK;
13471     }
13472
13473     /**
13474      * Return the full height measurement information for this view as computed
13475      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13476      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13477      * This should be used during measurement and layout calculations only. Use
13478      * {@link #getHeight()} to see how wide a view is after layout.
13479      *
13480      * @return The measured height of this view as a bit mask.
13481      */
13482     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13483             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13484                     name = "MEASURED_STATE_TOO_SMALL"),
13485     })
13486     public final int getMeasuredHeightAndState() {
13487         return mMeasuredHeight;
13488     }
13489
13490     /**
13491      * Return only the state bits of {@link #getMeasuredWidthAndState()}
13492      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13493      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13494      * and the height component is at the shifted bits
13495      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13496      */
13497     public final int getMeasuredState() {
13498         return (mMeasuredWidth&MEASURED_STATE_MASK)
13499                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13500                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13501     }
13502
13503     /**
13504      * The transform matrix of this view, which is calculated based on the current
13505      * rotation, scale, and pivot properties.
13506      *
13507      * @see #getRotation()
13508      * @see #getScaleX()
13509      * @see #getScaleY()
13510      * @see #getPivotX()
13511      * @see #getPivotY()
13512      * @return The current transform matrix for the view
13513      */
13514     public Matrix getMatrix() {
13515         ensureTransformationInfo();
13516         final Matrix matrix = mTransformationInfo.mMatrix;
13517         mRenderNode.getMatrix(matrix);
13518         return matrix;
13519     }
13520
13521     /**
13522      * Returns true if the transform matrix is the identity matrix.
13523      * Recomputes the matrix if necessary.
13524      *
13525      * @return True if the transform matrix is the identity matrix, false otherwise.
13526      */
13527     final boolean hasIdentityMatrix() {
13528         return mRenderNode.hasIdentityMatrix();
13529     }
13530
13531     void ensureTransformationInfo() {
13532         if (mTransformationInfo == null) {
13533             mTransformationInfo = new TransformationInfo();
13534         }
13535     }
13536
13537     /**
13538      * Utility method to retrieve the inverse of the current mMatrix property.
13539      * We cache the matrix to avoid recalculating it when transform properties
13540      * have not changed.
13541      *
13542      * @return The inverse of the current matrix of this view.
13543      * @hide
13544      */
13545     public final Matrix getInverseMatrix() {
13546         ensureTransformationInfo();
13547         if (mTransformationInfo.mInverseMatrix == null) {
13548             mTransformationInfo.mInverseMatrix = new Matrix();
13549         }
13550         final Matrix matrix = mTransformationInfo.mInverseMatrix;
13551         mRenderNode.getInverseMatrix(matrix);
13552         return matrix;
13553     }
13554
13555     /**
13556      * Gets the distance along the Z axis from the camera to this view.
13557      *
13558      * @see #setCameraDistance(float)
13559      *
13560      * @return The distance along the Z axis.
13561      */
13562     public float getCameraDistance() {
13563         final float dpi = mResources.getDisplayMetrics().densityDpi;
13564         return -(mRenderNode.getCameraDistance() * dpi);
13565     }
13566
13567     /**
13568      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13569      * views are drawn) from the camera to this view. The camera's distance
13570      * affects 3D transformations, for instance rotations around the X and Y
13571      * axis. If the rotationX or rotationY properties are changed and this view is
13572      * large (more than half the size of the screen), it is recommended to always
13573      * use a camera distance that's greater than the height (X axis rotation) or
13574      * the width (Y axis rotation) of this view.</p>
13575      *
13576      * <p>The distance of the camera from the view plane can have an affect on the
13577      * perspective distortion of the view when it is rotated around the x or y axis.
13578      * For example, a large distance will result in a large viewing angle, and there
13579      * will not be much perspective distortion of the view as it rotates. A short
13580      * distance may cause much more perspective distortion upon rotation, and can
13581      * also result in some drawing artifacts if the rotated view ends up partially
13582      * behind the camera (which is why the recommendation is to use a distance at
13583      * least as far as the size of the view, if the view is to be rotated.)</p>
13584      *
13585      * <p>The distance is expressed in "depth pixels." The default distance depends
13586      * on the screen density. For instance, on a medium density display, the
13587      * default distance is 1280. On a high density display, the default distance
13588      * is 1920.</p>
13589      *
13590      * <p>If you want to specify a distance that leads to visually consistent
13591      * results across various densities, use the following formula:</p>
13592      * <pre>
13593      * float scale = context.getResources().getDisplayMetrics().density;
13594      * view.setCameraDistance(distance * scale);
13595      * </pre>
13596      *
13597      * <p>The density scale factor of a high density display is 1.5,
13598      * and 1920 = 1280 * 1.5.</p>
13599      *
13600      * @param distance The distance in "depth pixels", if negative the opposite
13601      *        value is used
13602      *
13603      * @see #setRotationX(float)
13604      * @see #setRotationY(float)
13605      */
13606     public void setCameraDistance(float distance) {
13607         final float dpi = mResources.getDisplayMetrics().densityDpi;
13608
13609         invalidateViewProperty(true, false);
13610         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13611         invalidateViewProperty(false, false);
13612
13613         invalidateParentIfNeededAndWasQuickRejected();
13614     }
13615
13616     /**
13617      * The degrees that the view is rotated around the pivot point.
13618      *
13619      * @see #setRotation(float)
13620      * @see #getPivotX()
13621      * @see #getPivotY()
13622      *
13623      * @return The degrees of rotation.
13624      */
13625     @ViewDebug.ExportedProperty(category = "drawing")
13626     public float getRotation() {
13627         return mRenderNode.getRotation();
13628     }
13629
13630     /**
13631      * Sets the degrees that the view is rotated around the pivot point. Increasing values
13632      * result in clockwise rotation.
13633      *
13634      * @param rotation The degrees of rotation.
13635      *
13636      * @see #getRotation()
13637      * @see #getPivotX()
13638      * @see #getPivotY()
13639      * @see #setRotationX(float)
13640      * @see #setRotationY(float)
13641      *
13642      * @attr ref android.R.styleable#View_rotation
13643      */
13644     public void setRotation(float rotation) {
13645         if (rotation != getRotation()) {
13646             // Double-invalidation is necessary to capture view's old and new areas
13647             invalidateViewProperty(true, false);
13648             mRenderNode.setRotation(rotation);
13649             invalidateViewProperty(false, true);
13650
13651             invalidateParentIfNeededAndWasQuickRejected();
13652             notifySubtreeAccessibilityStateChangedIfNeeded();
13653         }
13654     }
13655
13656     /**
13657      * The degrees that the view is rotated around the vertical axis through the pivot point.
13658      *
13659      * @see #getPivotX()
13660      * @see #getPivotY()
13661      * @see #setRotationY(float)
13662      *
13663      * @return The degrees of Y rotation.
13664      */
13665     @ViewDebug.ExportedProperty(category = "drawing")
13666     public float getRotationY() {
13667         return mRenderNode.getRotationY();
13668     }
13669
13670     /**
13671      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13672      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13673      * down the y axis.
13674      *
13675      * When rotating large views, it is recommended to adjust the camera distance
13676      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13677      *
13678      * @param rotationY The degrees of Y rotation.
13679      *
13680      * @see #getRotationY()
13681      * @see #getPivotX()
13682      * @see #getPivotY()
13683      * @see #setRotation(float)
13684      * @see #setRotationX(float)
13685      * @see #setCameraDistance(float)
13686      *
13687      * @attr ref android.R.styleable#View_rotationY
13688      */
13689     public void setRotationY(float rotationY) {
13690         if (rotationY != getRotationY()) {
13691             invalidateViewProperty(true, false);
13692             mRenderNode.setRotationY(rotationY);
13693             invalidateViewProperty(false, true);
13694
13695             invalidateParentIfNeededAndWasQuickRejected();
13696             notifySubtreeAccessibilityStateChangedIfNeeded();
13697         }
13698     }
13699
13700     /**
13701      * The degrees that the view is rotated around the horizontal axis through the pivot point.
13702      *
13703      * @see #getPivotX()
13704      * @see #getPivotY()
13705      * @see #setRotationX(float)
13706      *
13707      * @return The degrees of X rotation.
13708      */
13709     @ViewDebug.ExportedProperty(category = "drawing")
13710     public float getRotationX() {
13711         return mRenderNode.getRotationX();
13712     }
13713
13714     /**
13715      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13716      * Increasing values result in clockwise rotation from the viewpoint of looking down the
13717      * x axis.
13718      *
13719      * When rotating large views, it is recommended to adjust the camera distance
13720      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13721      *
13722      * @param rotationX The degrees of X rotation.
13723      *
13724      * @see #getRotationX()
13725      * @see #getPivotX()
13726      * @see #getPivotY()
13727      * @see #setRotation(float)
13728      * @see #setRotationY(float)
13729      * @see #setCameraDistance(float)
13730      *
13731      * @attr ref android.R.styleable#View_rotationX
13732      */
13733     public void setRotationX(float rotationX) {
13734         if (rotationX != getRotationX()) {
13735             invalidateViewProperty(true, false);
13736             mRenderNode.setRotationX(rotationX);
13737             invalidateViewProperty(false, true);
13738
13739             invalidateParentIfNeededAndWasQuickRejected();
13740             notifySubtreeAccessibilityStateChangedIfNeeded();
13741         }
13742     }
13743
13744     /**
13745      * The amount that the view is scaled in x around the pivot point, as a proportion of
13746      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13747      *
13748      * <p>By default, this is 1.0f.
13749      *
13750      * @see #getPivotX()
13751      * @see #getPivotY()
13752      * @return The scaling factor.
13753      */
13754     @ViewDebug.ExportedProperty(category = "drawing")
13755     public float getScaleX() {
13756         return mRenderNode.getScaleX();
13757     }
13758
13759     /**
13760      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13761      * the view's unscaled width. A value of 1 means that no scaling is applied.
13762      *
13763      * @param scaleX The scaling factor.
13764      * @see #getPivotX()
13765      * @see #getPivotY()
13766      *
13767      * @attr ref android.R.styleable#View_scaleX
13768      */
13769     public void setScaleX(float scaleX) {
13770         if (scaleX != getScaleX()) {
13771             invalidateViewProperty(true, false);
13772             mRenderNode.setScaleX(scaleX);
13773             invalidateViewProperty(false, true);
13774
13775             invalidateParentIfNeededAndWasQuickRejected();
13776             notifySubtreeAccessibilityStateChangedIfNeeded();
13777         }
13778     }
13779
13780     /**
13781      * The amount that the view is scaled in y around the pivot point, as a proportion of
13782      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13783      *
13784      * <p>By default, this is 1.0f.
13785      *
13786      * @see #getPivotX()
13787      * @see #getPivotY()
13788      * @return The scaling factor.
13789      */
13790     @ViewDebug.ExportedProperty(category = "drawing")
13791     public float getScaleY() {
13792         return mRenderNode.getScaleY();
13793     }
13794
13795     /**
13796      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13797      * the view's unscaled width. A value of 1 means that no scaling is applied.
13798      *
13799      * @param scaleY The scaling factor.
13800      * @see #getPivotX()
13801      * @see #getPivotY()
13802      *
13803      * @attr ref android.R.styleable#View_scaleY
13804      */
13805     public void setScaleY(float scaleY) {
13806         if (scaleY != getScaleY()) {
13807             invalidateViewProperty(true, false);
13808             mRenderNode.setScaleY(scaleY);
13809             invalidateViewProperty(false, true);
13810
13811             invalidateParentIfNeededAndWasQuickRejected();
13812             notifySubtreeAccessibilityStateChangedIfNeeded();
13813         }
13814     }
13815
13816     /**
13817      * The x location of the point around which the view is {@link #setRotation(float) rotated}
13818      * and {@link #setScaleX(float) scaled}.
13819      *
13820      * @see #getRotation()
13821      * @see #getScaleX()
13822      * @see #getScaleY()
13823      * @see #getPivotY()
13824      * @return The x location of the pivot point.
13825      *
13826      * @attr ref android.R.styleable#View_transformPivotX
13827      */
13828     @ViewDebug.ExportedProperty(category = "drawing")
13829     public float getPivotX() {
13830         return mRenderNode.getPivotX();
13831     }
13832
13833     /**
13834      * Sets the x location of the point around which the view is
13835      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13836      * By default, the pivot point is centered on the object.
13837      * Setting this property disables this behavior and causes the view to use only the
13838      * explicitly set pivotX and pivotY values.
13839      *
13840      * @param pivotX The x location of the pivot point.
13841      * @see #getRotation()
13842      * @see #getScaleX()
13843      * @see #getScaleY()
13844      * @see #getPivotY()
13845      *
13846      * @attr ref android.R.styleable#View_transformPivotX
13847      */
13848     public void setPivotX(float pivotX) {
13849         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13850             invalidateViewProperty(true, false);
13851             mRenderNode.setPivotX(pivotX);
13852             invalidateViewProperty(false, true);
13853
13854             invalidateParentIfNeededAndWasQuickRejected();
13855         }
13856     }
13857
13858     /**
13859      * The y location of the point around which the view is {@link #setRotation(float) rotated}
13860      * and {@link #setScaleY(float) scaled}.
13861      *
13862      * @see #getRotation()
13863      * @see #getScaleX()
13864      * @see #getScaleY()
13865      * @see #getPivotY()
13866      * @return The y location of the pivot point.
13867      *
13868      * @attr ref android.R.styleable#View_transformPivotY
13869      */
13870     @ViewDebug.ExportedProperty(category = "drawing")
13871     public float getPivotY() {
13872         return mRenderNode.getPivotY();
13873     }
13874
13875     /**
13876      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13877      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13878      * Setting this property disables this behavior and causes the view to use only the
13879      * explicitly set pivotX and pivotY values.
13880      *
13881      * @param pivotY The y location of the pivot point.
13882      * @see #getRotation()
13883      * @see #getScaleX()
13884      * @see #getScaleY()
13885      * @see #getPivotY()
13886      *
13887      * @attr ref android.R.styleable#View_transformPivotY
13888      */
13889     public void setPivotY(float pivotY) {
13890         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13891             invalidateViewProperty(true, false);
13892             mRenderNode.setPivotY(pivotY);
13893             invalidateViewProperty(false, true);
13894
13895             invalidateParentIfNeededAndWasQuickRejected();
13896         }
13897     }
13898
13899     /**
13900      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13901      * completely transparent and 1 means the view is completely opaque.
13902      *
13903      * <p>By default this is 1.0f.
13904      * @return The opacity of the view.
13905      */
13906     @ViewDebug.ExportedProperty(category = "drawing")
13907     public float getAlpha() {
13908         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13909     }
13910
13911     /**
13912      * Sets the behavior for overlapping rendering for this view (see {@link
13913      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13914      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13915      * providing the value which is then used internally. That is, when {@link
13916      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13917      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13918      * instead.
13919      *
13920      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13921      * instead of that returned by {@link #hasOverlappingRendering()}.
13922      *
13923      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13924      */
13925     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13926         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13927         if (hasOverlappingRendering) {
13928             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13929         } else {
13930             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13931         }
13932     }
13933
13934     /**
13935      * Returns the value for overlapping rendering that is used internally. This is either
13936      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13937      * the return value of {@link #hasOverlappingRendering()}, otherwise.
13938      *
13939      * @return The value for overlapping rendering being used internally.
13940      */
13941     public final boolean getHasOverlappingRendering() {
13942         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13943                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13944                 hasOverlappingRendering();
13945     }
13946
13947     /**
13948      * Returns whether this View has content which overlaps.
13949      *
13950      * <p>This function, intended to be overridden by specific View types, is an optimization when
13951      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13952      * an offscreen buffer and then composited into place, which can be expensive. If the view has
13953      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13954      * directly. An example of overlapping rendering is a TextView with a background image, such as
13955      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13956      * ImageView with only the foreground image. The default implementation returns true; subclasses
13957      * should override if they have cases which can be optimized.</p>
13958      *
13959      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13960      * necessitates that a View return true if it uses the methods internally without passing the
13961      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13962      *
13963      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13964      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13965      *
13966      * @return true if the content in this view might overlap, false otherwise.
13967      */
13968     @ViewDebug.ExportedProperty(category = "drawing")
13969     public boolean hasOverlappingRendering() {
13970         return true;
13971     }
13972
13973     /**
13974      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13975      * completely transparent and 1 means the view is completely opaque.
13976      *
13977      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13978      * can have significant performance implications, especially for large views. It is best to use
13979      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13980      *
13981      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13982      * strongly recommended for performance reasons to either override
13983      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13984      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13985      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13986      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13987      * of rendering cost, even for simple or small views. Starting with
13988      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13989      * applied to the view at the rendering level.</p>
13990      *
13991      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13992      * responsible for applying the opacity itself.</p>
13993      *
13994      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13995      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13996      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13997      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13998      *
13999      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
14000      * value will clip a View to its bounds, unless the View returns <code>false</code> from
14001      * {@link #hasOverlappingRendering}.</p>
14002      *
14003      * @param alpha The opacity of the view.
14004      *
14005      * @see #hasOverlappingRendering()
14006      * @see #setLayerType(int, android.graphics.Paint)
14007      *
14008      * @attr ref android.R.styleable#View_alpha
14009      */
14010     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
14011         ensureTransformationInfo();
14012         if (mTransformationInfo.mAlpha != alpha) {
14013             // Report visibility changes, which can affect children, to accessibility
14014             if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
14015                 notifySubtreeAccessibilityStateChangedIfNeeded();
14016             }
14017             mTransformationInfo.mAlpha = alpha;
14018             if (onSetAlpha((int) (alpha * 255))) {
14019                 mPrivateFlags |= PFLAG_ALPHA_SET;
14020                 // subclass is handling alpha - don't optimize rendering cache invalidation
14021                 invalidateParentCaches();
14022                 invalidate(true);
14023             } else {
14024                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
14025                 invalidateViewProperty(true, false);
14026                 mRenderNode.setAlpha(getFinalAlpha());
14027             }
14028         }
14029     }
14030
14031     /**
14032      * Faster version of setAlpha() which performs the same steps except there are
14033      * no calls to invalidate(). The caller of this function should perform proper invalidation
14034      * on the parent and this object. The return value indicates whether the subclass handles
14035      * alpha (the return value for onSetAlpha()).
14036      *
14037      * @param alpha The new value for the alpha property
14038      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
14039      *         the new value for the alpha property is different from the old value
14040      */
14041     boolean setAlphaNoInvalidation(float alpha) {
14042         ensureTransformationInfo();
14043         if (mTransformationInfo.mAlpha != alpha) {
14044             mTransformationInfo.mAlpha = alpha;
14045             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
14046             if (subclassHandlesAlpha) {
14047                 mPrivateFlags |= PFLAG_ALPHA_SET;
14048                 return true;
14049             } else {
14050                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
14051                 mRenderNode.setAlpha(getFinalAlpha());
14052             }
14053         }
14054         return false;
14055     }
14056
14057     /**
14058      * This property is hidden and intended only for use by the Fade transition, which
14059      * animates it to produce a visual translucency that does not side-effect (or get
14060      * affected by) the real alpha property. This value is composited with the other
14061      * alpha value (and the AlphaAnimation value, when that is present) to produce
14062      * a final visual translucency result, which is what is passed into the DisplayList.
14063      *
14064      * @hide
14065      */
14066     public void setTransitionAlpha(float alpha) {
14067         ensureTransformationInfo();
14068         if (mTransformationInfo.mTransitionAlpha != alpha) {
14069             mTransformationInfo.mTransitionAlpha = alpha;
14070             mPrivateFlags &= ~PFLAG_ALPHA_SET;
14071             invalidateViewProperty(true, false);
14072             mRenderNode.setAlpha(getFinalAlpha());
14073         }
14074     }
14075
14076     /**
14077      * Calculates the visual alpha of this view, which is a combination of the actual
14078      * alpha value and the transitionAlpha value (if set).
14079      */
14080     private float getFinalAlpha() {
14081         if (mTransformationInfo != null) {
14082             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
14083         }
14084         return 1;
14085     }
14086
14087     /**
14088      * This property is hidden and intended only for use by the Fade transition, which
14089      * animates it to produce a visual translucency that does not side-effect (or get
14090      * affected by) the real alpha property. This value is composited with the other
14091      * alpha value (and the AlphaAnimation value, when that is present) to produce
14092      * a final visual translucency result, which is what is passed into the DisplayList.
14093      *
14094      * @hide
14095      */
14096     @ViewDebug.ExportedProperty(category = "drawing")
14097     public float getTransitionAlpha() {
14098         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
14099     }
14100
14101     /**
14102      * Top position of this view relative to its parent.
14103      *
14104      * @return The top of this view, in pixels.
14105      */
14106     @ViewDebug.CapturedViewProperty
14107     public final int getTop() {
14108         return mTop;
14109     }
14110
14111     /**
14112      * Sets the top position of this view relative to its parent. This method is meant to be called
14113      * by the layout system and should not generally be called otherwise, because the property
14114      * may be changed at any time by the layout.
14115      *
14116      * @param top The top of this view, in pixels.
14117      */
14118     public final void setTop(int top) {
14119         if (top != mTop) {
14120             final boolean matrixIsIdentity = hasIdentityMatrix();
14121             if (matrixIsIdentity) {
14122                 if (mAttachInfo != null) {
14123                     int minTop;
14124                     int yLoc;
14125                     if (top < mTop) {
14126                         minTop = top;
14127                         yLoc = top - mTop;
14128                     } else {
14129                         minTop = mTop;
14130                         yLoc = 0;
14131                     }
14132                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
14133                 }
14134             } else {
14135                 // Double-invalidation is necessary to capture view's old and new areas
14136                 invalidate(true);
14137             }
14138
14139             int width = mRight - mLeft;
14140             int oldHeight = mBottom - mTop;
14141
14142             mTop = top;
14143             mRenderNode.setTop(mTop);
14144
14145             sizeChange(width, mBottom - mTop, width, oldHeight);
14146
14147             if (!matrixIsIdentity) {
14148                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14149                 invalidate(true);
14150             }
14151             mBackgroundSizeChanged = true;
14152             mDefaultFocusHighlightSizeChanged = true;
14153             if (mForegroundInfo != null) {
14154                 mForegroundInfo.mBoundsChanged = true;
14155             }
14156             invalidateParentIfNeeded();
14157             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14158                 // View was rejected last time it was drawn by its parent; this may have changed
14159                 invalidateParentIfNeeded();
14160             }
14161         }
14162     }
14163
14164     /**
14165      * Bottom position of this view relative to its parent.
14166      *
14167      * @return The bottom of this view, in pixels.
14168      */
14169     @ViewDebug.CapturedViewProperty
14170     public final int getBottom() {
14171         return mBottom;
14172     }
14173
14174     /**
14175      * True if this view has changed since the last time being drawn.
14176      *
14177      * @return The dirty state of this view.
14178      */
14179     public boolean isDirty() {
14180         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
14181     }
14182
14183     /**
14184      * Sets the bottom position of this view relative to its parent. This method is meant to be
14185      * called by the layout system and should not generally be called otherwise, because the
14186      * property may be changed at any time by the layout.
14187      *
14188      * @param bottom The bottom of this view, in pixels.
14189      */
14190     public final void setBottom(int bottom) {
14191         if (bottom != mBottom) {
14192             final boolean matrixIsIdentity = hasIdentityMatrix();
14193             if (matrixIsIdentity) {
14194                 if (mAttachInfo != null) {
14195                     int maxBottom;
14196                     if (bottom < mBottom) {
14197                         maxBottom = mBottom;
14198                     } else {
14199                         maxBottom = bottom;
14200                     }
14201                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14202                 }
14203             } else {
14204                 // Double-invalidation is necessary to capture view's old and new areas
14205                 invalidate(true);
14206             }
14207
14208             int width = mRight - mLeft;
14209             int oldHeight = mBottom - mTop;
14210
14211             mBottom = bottom;
14212             mRenderNode.setBottom(mBottom);
14213
14214             sizeChange(width, mBottom - mTop, width, oldHeight);
14215
14216             if (!matrixIsIdentity) {
14217                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14218                 invalidate(true);
14219             }
14220             mBackgroundSizeChanged = true;
14221             mDefaultFocusHighlightSizeChanged = true;
14222             if (mForegroundInfo != null) {
14223                 mForegroundInfo.mBoundsChanged = true;
14224             }
14225             invalidateParentIfNeeded();
14226             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14227                 // View was rejected last time it was drawn by its parent; this may have changed
14228                 invalidateParentIfNeeded();
14229             }
14230         }
14231     }
14232
14233     /**
14234      * Left position of this view relative to its parent.
14235      *
14236      * @return The left edge of this view, in pixels.
14237      */
14238     @ViewDebug.CapturedViewProperty
14239     public final int getLeft() {
14240         return mLeft;
14241     }
14242
14243     /**
14244      * Sets the left position of this view relative to its parent. This method is meant to be called
14245      * by the layout system and should not generally be called otherwise, because the property
14246      * may be changed at any time by the layout.
14247      *
14248      * @param left The left of this view, in pixels.
14249      */
14250     public final void setLeft(int left) {
14251         if (left != mLeft) {
14252             final boolean matrixIsIdentity = hasIdentityMatrix();
14253             if (matrixIsIdentity) {
14254                 if (mAttachInfo != null) {
14255                     int minLeft;
14256                     int xLoc;
14257                     if (left < mLeft) {
14258                         minLeft = left;
14259                         xLoc = left - mLeft;
14260                     } else {
14261                         minLeft = mLeft;
14262                         xLoc = 0;
14263                     }
14264                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14265                 }
14266             } else {
14267                 // Double-invalidation is necessary to capture view's old and new areas
14268                 invalidate(true);
14269             }
14270
14271             int oldWidth = mRight - mLeft;
14272             int height = mBottom - mTop;
14273
14274             mLeft = left;
14275             mRenderNode.setLeft(left);
14276
14277             sizeChange(mRight - mLeft, height, oldWidth, height);
14278
14279             if (!matrixIsIdentity) {
14280                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14281                 invalidate(true);
14282             }
14283             mBackgroundSizeChanged = true;
14284             mDefaultFocusHighlightSizeChanged = true;
14285             if (mForegroundInfo != null) {
14286                 mForegroundInfo.mBoundsChanged = true;
14287             }
14288             invalidateParentIfNeeded();
14289             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14290                 // View was rejected last time it was drawn by its parent; this may have changed
14291                 invalidateParentIfNeeded();
14292             }
14293         }
14294     }
14295
14296     /**
14297      * Right position of this view relative to its parent.
14298      *
14299      * @return The right edge of this view, in pixels.
14300      */
14301     @ViewDebug.CapturedViewProperty
14302     public final int getRight() {
14303         return mRight;
14304     }
14305
14306     /**
14307      * Sets the right position of this view relative to its parent. This method is meant to be called
14308      * by the layout system and should not generally be called otherwise, because the property
14309      * may be changed at any time by the layout.
14310      *
14311      * @param right The right of this view, in pixels.
14312      */
14313     public final void setRight(int right) {
14314         if (right != mRight) {
14315             final boolean matrixIsIdentity = hasIdentityMatrix();
14316             if (matrixIsIdentity) {
14317                 if (mAttachInfo != null) {
14318                     int maxRight;
14319                     if (right < mRight) {
14320                         maxRight = mRight;
14321                     } else {
14322                         maxRight = right;
14323                     }
14324                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14325                 }
14326             } else {
14327                 // Double-invalidation is necessary to capture view's old and new areas
14328                 invalidate(true);
14329             }
14330
14331             int oldWidth = mRight - mLeft;
14332             int height = mBottom - mTop;
14333
14334             mRight = right;
14335             mRenderNode.setRight(mRight);
14336
14337             sizeChange(mRight - mLeft, height, oldWidth, height);
14338
14339             if (!matrixIsIdentity) {
14340                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14341                 invalidate(true);
14342             }
14343             mBackgroundSizeChanged = true;
14344             mDefaultFocusHighlightSizeChanged = true;
14345             if (mForegroundInfo != null) {
14346                 mForegroundInfo.mBoundsChanged = true;
14347             }
14348             invalidateParentIfNeeded();
14349             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14350                 // View was rejected last time it was drawn by its parent; this may have changed
14351                 invalidateParentIfNeeded();
14352             }
14353         }
14354     }
14355
14356     /**
14357      * The visual x position of this view, in pixels. This is equivalent to the
14358      * {@link #setTranslationX(float) translationX} property plus the current
14359      * {@link #getLeft() left} property.
14360      *
14361      * @return The visual x position of this view, in pixels.
14362      */
14363     @ViewDebug.ExportedProperty(category = "drawing")
14364     public float getX() {
14365         return mLeft + getTranslationX();
14366     }
14367
14368     /**
14369      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14370      * {@link #setTranslationX(float) translationX} property to be the difference between
14371      * the x value passed in and the current {@link #getLeft() left} property.
14372      *
14373      * @param x The visual x position of this view, in pixels.
14374      */
14375     public void setX(float x) {
14376         setTranslationX(x - mLeft);
14377     }
14378
14379     /**
14380      * The visual y position of this view, in pixels. This is equivalent to the
14381      * {@link #setTranslationY(float) translationY} property plus the current
14382      * {@link #getTop() top} property.
14383      *
14384      * @return The visual y position of this view, in pixels.
14385      */
14386     @ViewDebug.ExportedProperty(category = "drawing")
14387     public float getY() {
14388         return mTop + getTranslationY();
14389     }
14390
14391     /**
14392      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14393      * {@link #setTranslationY(float) translationY} property to be the difference between
14394      * the y value passed in and the current {@link #getTop() top} property.
14395      *
14396      * @param y The visual y position of this view, in pixels.
14397      */
14398     public void setY(float y) {
14399         setTranslationY(y - mTop);
14400     }
14401
14402     /**
14403      * The visual z position of this view, in pixels. This is equivalent to the
14404      * {@link #setTranslationZ(float) translationZ} property plus the current
14405      * {@link #getElevation() elevation} property.
14406      *
14407      * @return The visual z position of this view, in pixels.
14408      */
14409     @ViewDebug.ExportedProperty(category = "drawing")
14410     public float getZ() {
14411         return getElevation() + getTranslationZ();
14412     }
14413
14414     /**
14415      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14416      * {@link #setTranslationZ(float) translationZ} property to be the difference between
14417      * the x value passed in and the current {@link #getElevation() elevation} property.
14418      *
14419      * @param z The visual z position of this view, in pixels.
14420      */
14421     public void setZ(float z) {
14422         setTranslationZ(z - getElevation());
14423     }
14424
14425     /**
14426      * The base elevation of this view relative to its parent, in pixels.
14427      *
14428      * @return The base depth position of the view, in pixels.
14429      */
14430     @ViewDebug.ExportedProperty(category = "drawing")
14431     public float getElevation() {
14432         return mRenderNode.getElevation();
14433     }
14434
14435     /**
14436      * Sets the base elevation of this view, in pixels.
14437      *
14438      * @attr ref android.R.styleable#View_elevation
14439      */
14440     public void setElevation(float elevation) {
14441         if (elevation != getElevation()) {
14442             invalidateViewProperty(true, false);
14443             mRenderNode.setElevation(elevation);
14444             invalidateViewProperty(false, true);
14445
14446             invalidateParentIfNeededAndWasQuickRejected();
14447         }
14448     }
14449
14450     /**
14451      * The horizontal location of this view relative to its {@link #getLeft() left} position.
14452      * This position is post-layout, in addition to wherever the object's
14453      * layout placed it.
14454      *
14455      * @return The horizontal position of this view relative to its left position, in pixels.
14456      */
14457     @ViewDebug.ExportedProperty(category = "drawing")
14458     public float getTranslationX() {
14459         return mRenderNode.getTranslationX();
14460     }
14461
14462     /**
14463      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14464      * This effectively positions the object post-layout, in addition to wherever the object's
14465      * layout placed it.
14466      *
14467      * @param translationX The horizontal position of this view relative to its left position,
14468      * in pixels.
14469      *
14470      * @attr ref android.R.styleable#View_translationX
14471      */
14472     public void setTranslationX(float translationX) {
14473         if (translationX != getTranslationX()) {
14474             invalidateViewProperty(true, false);
14475             mRenderNode.setTranslationX(translationX);
14476             invalidateViewProperty(false, true);
14477
14478             invalidateParentIfNeededAndWasQuickRejected();
14479             notifySubtreeAccessibilityStateChangedIfNeeded();
14480         }
14481     }
14482
14483     /**
14484      * The vertical location of this view relative to its {@link #getTop() top} position.
14485      * This position is post-layout, in addition to wherever the object's
14486      * layout placed it.
14487      *
14488      * @return The vertical position of this view relative to its top position,
14489      * in pixels.
14490      */
14491     @ViewDebug.ExportedProperty(category = "drawing")
14492     public float getTranslationY() {
14493         return mRenderNode.getTranslationY();
14494     }
14495
14496     /**
14497      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14498      * This effectively positions the object post-layout, in addition to wherever the object's
14499      * layout placed it.
14500      *
14501      * @param translationY The vertical position of this view relative to its top position,
14502      * in pixels.
14503      *
14504      * @attr ref android.R.styleable#View_translationY
14505      */
14506     public void setTranslationY(float translationY) {
14507         if (translationY != getTranslationY()) {
14508             invalidateViewProperty(true, false);
14509             mRenderNode.setTranslationY(translationY);
14510             invalidateViewProperty(false, true);
14511
14512             invalidateParentIfNeededAndWasQuickRejected();
14513             notifySubtreeAccessibilityStateChangedIfNeeded();
14514         }
14515     }
14516
14517     /**
14518      * The depth location of this view relative to its {@link #getElevation() elevation}.
14519      *
14520      * @return The depth of this view relative to its elevation.
14521      */
14522     @ViewDebug.ExportedProperty(category = "drawing")
14523     public float getTranslationZ() {
14524         return mRenderNode.getTranslationZ();
14525     }
14526
14527     /**
14528      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14529      *
14530      * @attr ref android.R.styleable#View_translationZ
14531      */
14532     public void setTranslationZ(float translationZ) {
14533         if (translationZ != getTranslationZ()) {
14534             invalidateViewProperty(true, false);
14535             mRenderNode.setTranslationZ(translationZ);
14536             invalidateViewProperty(false, true);
14537
14538             invalidateParentIfNeededAndWasQuickRejected();
14539         }
14540     }
14541
14542     /** @hide */
14543     public void setAnimationMatrix(Matrix matrix) {
14544         invalidateViewProperty(true, false);
14545         mRenderNode.setAnimationMatrix(matrix);
14546         invalidateViewProperty(false, true);
14547
14548         invalidateParentIfNeededAndWasQuickRejected();
14549     }
14550
14551     /**
14552      * Returns the current StateListAnimator if exists.
14553      *
14554      * @return StateListAnimator or null if it does not exists
14555      * @see    #setStateListAnimator(android.animation.StateListAnimator)
14556      */
14557     public StateListAnimator getStateListAnimator() {
14558         return mStateListAnimator;
14559     }
14560
14561     /**
14562      * Attaches the provided StateListAnimator to this View.
14563      * <p>
14564      * Any previously attached StateListAnimator will be detached.
14565      *
14566      * @param stateListAnimator The StateListAnimator to update the view
14567      * @see android.animation.StateListAnimator
14568      */
14569     public void setStateListAnimator(StateListAnimator stateListAnimator) {
14570         if (mStateListAnimator == stateListAnimator) {
14571             return;
14572         }
14573         if (mStateListAnimator != null) {
14574             mStateListAnimator.setTarget(null);
14575         }
14576         mStateListAnimator = stateListAnimator;
14577         if (stateListAnimator != null) {
14578             stateListAnimator.setTarget(this);
14579             if (isAttachedToWindow()) {
14580                 stateListAnimator.setState(getDrawableState());
14581             }
14582         }
14583     }
14584
14585     /**
14586      * Returns whether the Outline should be used to clip the contents of the View.
14587      * <p>
14588      * Note that this flag will only be respected if the View's Outline returns true from
14589      * {@link Outline#canClip()}.
14590      *
14591      * @see #setOutlineProvider(ViewOutlineProvider)
14592      * @see #setClipToOutline(boolean)
14593      */
14594     public final boolean getClipToOutline() {
14595         return mRenderNode.getClipToOutline();
14596     }
14597
14598     /**
14599      * Sets whether the View's Outline should be used to clip the contents of the View.
14600      * <p>
14601      * Only a single non-rectangular clip can be applied on a View at any time.
14602      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14603      * circular reveal} animation take priority over Outline clipping, and
14604      * child Outline clipping takes priority over Outline clipping done by a
14605      * parent.
14606      * <p>
14607      * Note that this flag will only be respected if the View's Outline returns true from
14608      * {@link Outline#canClip()}.
14609      *
14610      * @see #setOutlineProvider(ViewOutlineProvider)
14611      * @see #getClipToOutline()
14612      */
14613     public void setClipToOutline(boolean clipToOutline) {
14614         damageInParent();
14615         if (getClipToOutline() != clipToOutline) {
14616             mRenderNode.setClipToOutline(clipToOutline);
14617         }
14618     }
14619
14620     // correspond to the enum values of View_outlineProvider
14621     private static final int PROVIDER_BACKGROUND = 0;
14622     private static final int PROVIDER_NONE = 1;
14623     private static final int PROVIDER_BOUNDS = 2;
14624     private static final int PROVIDER_PADDED_BOUNDS = 3;
14625     private void setOutlineProviderFromAttribute(int providerInt) {
14626         switch (providerInt) {
14627             case PROVIDER_BACKGROUND:
14628                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14629                 break;
14630             case PROVIDER_NONE:
14631                 setOutlineProvider(null);
14632                 break;
14633             case PROVIDER_BOUNDS:
14634                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
14635                 break;
14636             case PROVIDER_PADDED_BOUNDS:
14637                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14638                 break;
14639         }
14640     }
14641
14642     /**
14643      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14644      * the shape of the shadow it casts, and enables outline clipping.
14645      * <p>
14646      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14647      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14648      * outline provider with this method allows this behavior to be overridden.
14649      * <p>
14650      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14651      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14652      * <p>
14653      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14654      *
14655      * @see #setClipToOutline(boolean)
14656      * @see #getClipToOutline()
14657      * @see #getOutlineProvider()
14658      */
14659     public void setOutlineProvider(ViewOutlineProvider provider) {
14660         mOutlineProvider = provider;
14661         invalidateOutline();
14662     }
14663
14664     /**
14665      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14666      * that defines the shape of the shadow it casts, and enables outline clipping.
14667      *
14668      * @see #setOutlineProvider(ViewOutlineProvider)
14669      */
14670     public ViewOutlineProvider getOutlineProvider() {
14671         return mOutlineProvider;
14672     }
14673
14674     /**
14675      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14676      *
14677      * @see #setOutlineProvider(ViewOutlineProvider)
14678      */
14679     public void invalidateOutline() {
14680         rebuildOutline();
14681
14682         notifySubtreeAccessibilityStateChangedIfNeeded();
14683         invalidateViewProperty(false, false);
14684     }
14685
14686     /**
14687      * Internal version of {@link #invalidateOutline()} which invalidates the
14688      * outline without invalidating the view itself. This is intended to be called from
14689      * within methods in the View class itself which are the result of the view being
14690      * invalidated already. For example, when we are drawing the background of a View,
14691      * we invalidate the outline in case it changed in the meantime, but we do not
14692      * need to invalidate the view because we're already drawing the background as part
14693      * of drawing the view in response to an earlier invalidation of the view.
14694      */
14695     private void rebuildOutline() {
14696         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14697         if (mAttachInfo == null) return;
14698
14699         if (mOutlineProvider == null) {
14700             // no provider, remove outline
14701             mRenderNode.setOutline(null);
14702         } else {
14703             final Outline outline = mAttachInfo.mTmpOutline;
14704             outline.setEmpty();
14705             outline.setAlpha(1.0f);
14706
14707             mOutlineProvider.getOutline(this, outline);
14708             mRenderNode.setOutline(outline);
14709         }
14710     }
14711
14712     /**
14713      * HierarchyViewer only
14714      *
14715      * @hide
14716      */
14717     @ViewDebug.ExportedProperty(category = "drawing")
14718     public boolean hasShadow() {
14719         return mRenderNode.hasShadow();
14720     }
14721
14722
14723     /** @hide */
14724     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14725         mRenderNode.setRevealClip(shouldClip, x, y, radius);
14726         invalidateViewProperty(false, false);
14727     }
14728
14729     /**
14730      * Hit rectangle in parent's coordinates
14731      *
14732      * @param outRect The hit rectangle of the view.
14733      */
14734     public void getHitRect(Rect outRect) {
14735         if (hasIdentityMatrix() || mAttachInfo == null) {
14736             outRect.set(mLeft, mTop, mRight, mBottom);
14737         } else {
14738             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14739             tmpRect.set(0, 0, getWidth(), getHeight());
14740             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14741             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14742                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14743         }
14744     }
14745
14746     /**
14747      * Determines whether the given point, in local coordinates is inside the view.
14748      */
14749     /*package*/ final boolean pointInView(float localX, float localY) {
14750         return pointInView(localX, localY, 0);
14751     }
14752
14753     /**
14754      * Utility method to determine whether the given point, in local coordinates,
14755      * is inside the view, where the area of the view is expanded by the slop factor.
14756      * This method is called while processing touch-move events to determine if the event
14757      * is still within the view.
14758      *
14759      * @hide
14760      */
14761     public boolean pointInView(float localX, float localY, float slop) {
14762         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14763                 localY < ((mBottom - mTop) + slop);
14764     }
14765
14766     /**
14767      * When a view has focus and the user navigates away from it, the next view is searched for
14768      * starting from the rectangle filled in by this method.
14769      *
14770      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14771      * of the view.  However, if your view maintains some idea of internal selection,
14772      * such as a cursor, or a selected row or column, you should override this method and
14773      * fill in a more specific rectangle.
14774      *
14775      * @param r The rectangle to fill in, in this view's coordinates.
14776      */
14777     public void getFocusedRect(Rect r) {
14778         getDrawingRect(r);
14779     }
14780
14781     /**
14782      * If some part of this view is not clipped by any of its parents, then
14783      * return that area in r in global (root) coordinates. To convert r to local
14784      * coordinates (without taking possible View rotations into account), offset
14785      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14786      * If the view is completely clipped or translated out, return false.
14787      *
14788      * @param r If true is returned, r holds the global coordinates of the
14789      *        visible portion of this view.
14790      * @param globalOffset If true is returned, globalOffset holds the dx,dy
14791      *        between this view and its root. globalOffet may be null.
14792      * @return true if r is non-empty (i.e. part of the view is visible at the
14793      *         root level.
14794      */
14795     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14796         int width = mRight - mLeft;
14797         int height = mBottom - mTop;
14798         if (width > 0 && height > 0) {
14799             r.set(0, 0, width, height);
14800             if (globalOffset != null) {
14801                 globalOffset.set(-mScrollX, -mScrollY);
14802             }
14803             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14804         }
14805         return false;
14806     }
14807
14808     public final boolean getGlobalVisibleRect(Rect r) {
14809         return getGlobalVisibleRect(r, null);
14810     }
14811
14812     public final boolean getLocalVisibleRect(Rect r) {
14813         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14814         if (getGlobalVisibleRect(r, offset)) {
14815             r.offset(-offset.x, -offset.y); // make r local
14816             return true;
14817         }
14818         return false;
14819     }
14820
14821     /**
14822      * Offset this view's vertical location by the specified number of pixels.
14823      *
14824      * @param offset the number of pixels to offset the view by
14825      */
14826     public void offsetTopAndBottom(int offset) {
14827         if (offset != 0) {
14828             final boolean matrixIsIdentity = hasIdentityMatrix();
14829             if (matrixIsIdentity) {
14830                 if (isHardwareAccelerated()) {
14831                     invalidateViewProperty(false, false);
14832                 } else {
14833                     final ViewParent p = mParent;
14834                     if (p != null && mAttachInfo != null) {
14835                         final Rect r = mAttachInfo.mTmpInvalRect;
14836                         int minTop;
14837                         int maxBottom;
14838                         int yLoc;
14839                         if (offset < 0) {
14840                             minTop = mTop + offset;
14841                             maxBottom = mBottom;
14842                             yLoc = offset;
14843                         } else {
14844                             minTop = mTop;
14845                             maxBottom = mBottom + offset;
14846                             yLoc = 0;
14847                         }
14848                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14849                         p.invalidateChild(this, r);
14850                     }
14851                 }
14852             } else {
14853                 invalidateViewProperty(false, false);
14854             }
14855
14856             mTop += offset;
14857             mBottom += offset;
14858             mRenderNode.offsetTopAndBottom(offset);
14859             if (isHardwareAccelerated()) {
14860                 invalidateViewProperty(false, false);
14861                 invalidateParentIfNeededAndWasQuickRejected();
14862             } else {
14863                 if (!matrixIsIdentity) {
14864                     invalidateViewProperty(false, true);
14865                 }
14866                 invalidateParentIfNeeded();
14867             }
14868             notifySubtreeAccessibilityStateChangedIfNeeded();
14869         }
14870     }
14871
14872     /**
14873      * Offset this view's horizontal location by the specified amount of pixels.
14874      *
14875      * @param offset the number of pixels to offset the view by
14876      */
14877     public void offsetLeftAndRight(int offset) {
14878         if (offset != 0) {
14879             final boolean matrixIsIdentity = hasIdentityMatrix();
14880             if (matrixIsIdentity) {
14881                 if (isHardwareAccelerated()) {
14882                     invalidateViewProperty(false, false);
14883                 } else {
14884                     final ViewParent p = mParent;
14885                     if (p != null && mAttachInfo != null) {
14886                         final Rect r = mAttachInfo.mTmpInvalRect;
14887                         int minLeft;
14888                         int maxRight;
14889                         if (offset < 0) {
14890                             minLeft = mLeft + offset;
14891                             maxRight = mRight;
14892                         } else {
14893                             minLeft = mLeft;
14894                             maxRight = mRight + offset;
14895                         }
14896                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14897                         p.invalidateChild(this, r);
14898                     }
14899                 }
14900             } else {
14901                 invalidateViewProperty(false, false);
14902             }
14903
14904             mLeft += offset;
14905             mRight += offset;
14906             mRenderNode.offsetLeftAndRight(offset);
14907             if (isHardwareAccelerated()) {
14908                 invalidateViewProperty(false, false);
14909                 invalidateParentIfNeededAndWasQuickRejected();
14910             } else {
14911                 if (!matrixIsIdentity) {
14912                     invalidateViewProperty(false, true);
14913                 }
14914                 invalidateParentIfNeeded();
14915             }
14916             notifySubtreeAccessibilityStateChangedIfNeeded();
14917         }
14918     }
14919
14920     /**
14921      * Get the LayoutParams associated with this view. All views should have
14922      * layout parameters. These supply parameters to the <i>parent</i> of this
14923      * view specifying how it should be arranged. There are many subclasses of
14924      * ViewGroup.LayoutParams, and these correspond to the different subclasses
14925      * of ViewGroup that are responsible for arranging their children.
14926      *
14927      * This method may return null if this View is not attached to a parent
14928      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14929      * was not invoked successfully. When a View is attached to a parent
14930      * ViewGroup, this method must not return null.
14931      *
14932      * @return The LayoutParams associated with this view, or null if no
14933      *         parameters have been set yet
14934      */
14935     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14936     public ViewGroup.LayoutParams getLayoutParams() {
14937         return mLayoutParams;
14938     }
14939
14940     /**
14941      * Set the layout parameters associated with this view. These supply
14942      * parameters to the <i>parent</i> of this view specifying how it should be
14943      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14944      * correspond to the different subclasses of ViewGroup that are responsible
14945      * for arranging their children.
14946      *
14947      * @param params The layout parameters for this view, cannot be null
14948      */
14949     public void setLayoutParams(ViewGroup.LayoutParams params) {
14950         if (params == null) {
14951             throw new NullPointerException("Layout parameters cannot be null");
14952         }
14953         mLayoutParams = params;
14954         resolveLayoutParams();
14955         if (mParent instanceof ViewGroup) {
14956             ((ViewGroup) mParent).onSetLayoutParams(this, params);
14957         }
14958         requestLayout();
14959     }
14960
14961     /**
14962      * Resolve the layout parameters depending on the resolved layout direction
14963      *
14964      * @hide
14965      */
14966     public void resolveLayoutParams() {
14967         if (mLayoutParams != null) {
14968             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14969         }
14970     }
14971
14972     /**
14973      * Set the scrolled position of your view. This will cause a call to
14974      * {@link #onScrollChanged(int, int, int, int)} and the view will be
14975      * invalidated.
14976      * @param x the x position to scroll to
14977      * @param y the y position to scroll to
14978      */
14979     public void scrollTo(int x, int y) {
14980         if (mScrollX != x || mScrollY != y) {
14981             int oldX = mScrollX;
14982             int oldY = mScrollY;
14983             mScrollX = x;
14984             mScrollY = y;
14985             invalidateParentCaches();
14986             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14987             if (!awakenScrollBars()) {
14988                 postInvalidateOnAnimation();
14989             }
14990         }
14991     }
14992
14993     /**
14994      * Move the scrolled position of your view. This will cause a call to
14995      * {@link #onScrollChanged(int, int, int, int)} and the view will be
14996      * invalidated.
14997      * @param x the amount of pixels to scroll by horizontally
14998      * @param y the amount of pixels to scroll by vertically
14999      */
15000     public void scrollBy(int x, int y) {
15001         scrollTo(mScrollX + x, mScrollY + y);
15002     }
15003
15004     /**
15005      * <p>Trigger the scrollbars to draw. When invoked this method starts an
15006      * animation to fade the scrollbars out after a default delay. If a subclass
15007      * provides animated scrolling, the start delay should equal the duration
15008      * of the scrolling animation.</p>
15009      *
15010      * <p>The animation starts only if at least one of the scrollbars is
15011      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
15012      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15013      * this method returns true, and false otherwise. If the animation is
15014      * started, this method calls {@link #invalidate()}; in that case the
15015      * caller should not call {@link #invalidate()}.</p>
15016      *
15017      * <p>This method should be invoked every time a subclass directly updates
15018      * the scroll parameters.</p>
15019      *
15020      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
15021      * and {@link #scrollTo(int, int)}.</p>
15022      *
15023      * @return true if the animation is played, false otherwise
15024      *
15025      * @see #awakenScrollBars(int)
15026      * @see #scrollBy(int, int)
15027      * @see #scrollTo(int, int)
15028      * @see #isHorizontalScrollBarEnabled()
15029      * @see #isVerticalScrollBarEnabled()
15030      * @see #setHorizontalScrollBarEnabled(boolean)
15031      * @see #setVerticalScrollBarEnabled(boolean)
15032      */
15033     protected boolean awakenScrollBars() {
15034         return mScrollCache != null &&
15035                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
15036     }
15037
15038     /**
15039      * Trigger the scrollbars to draw.
15040      * This method differs from awakenScrollBars() only in its default duration.
15041      * initialAwakenScrollBars() will show the scroll bars for longer than
15042      * usual to give the user more of a chance to notice them.
15043      *
15044      * @return true if the animation is played, false otherwise.
15045      */
15046     private boolean initialAwakenScrollBars() {
15047         return mScrollCache != null &&
15048                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
15049     }
15050
15051     /**
15052      * <p>
15053      * Trigger the scrollbars to draw. When invoked this method starts an
15054      * animation to fade the scrollbars out after a fixed delay. If a subclass
15055      * provides animated scrolling, the start delay should equal the duration of
15056      * the scrolling animation.
15057      * </p>
15058      *
15059      * <p>
15060      * The animation starts only if at least one of the scrollbars is enabled,
15061      * as specified by {@link #isHorizontalScrollBarEnabled()} and
15062      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15063      * this method returns true, and false otherwise. If the animation is
15064      * started, this method calls {@link #invalidate()}; in that case the caller
15065      * should not call {@link #invalidate()}.
15066      * </p>
15067      *
15068      * <p>
15069      * This method should be invoked every time a subclass directly updates the
15070      * scroll parameters.
15071      * </p>
15072      *
15073      * @param startDelay the delay, in milliseconds, after which the animation
15074      *        should start; when the delay is 0, the animation starts
15075      *        immediately
15076      * @return true if the animation is played, false otherwise
15077      *
15078      * @see #scrollBy(int, int)
15079      * @see #scrollTo(int, int)
15080      * @see #isHorizontalScrollBarEnabled()
15081      * @see #isVerticalScrollBarEnabled()
15082      * @see #setHorizontalScrollBarEnabled(boolean)
15083      * @see #setVerticalScrollBarEnabled(boolean)
15084      */
15085     protected boolean awakenScrollBars(int startDelay) {
15086         return awakenScrollBars(startDelay, true);
15087     }
15088
15089     /**
15090      * <p>
15091      * Trigger the scrollbars to draw. When invoked this method starts an
15092      * animation to fade the scrollbars out after a fixed delay. If a subclass
15093      * provides animated scrolling, the start delay should equal the duration of
15094      * the scrolling animation.
15095      * </p>
15096      *
15097      * <p>
15098      * The animation starts only if at least one of the scrollbars is enabled,
15099      * as specified by {@link #isHorizontalScrollBarEnabled()} and
15100      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15101      * this method returns true, and false otherwise. If the animation is
15102      * started, this method calls {@link #invalidate()} if the invalidate parameter
15103      * is set to true; in that case the caller
15104      * should not call {@link #invalidate()}.
15105      * </p>
15106      *
15107      * <p>
15108      * This method should be invoked every time a subclass directly updates the
15109      * scroll parameters.
15110      * </p>
15111      *
15112      * @param startDelay the delay, in milliseconds, after which the animation
15113      *        should start; when the delay is 0, the animation starts
15114      *        immediately
15115      *
15116      * @param invalidate Whether this method should call invalidate
15117      *
15118      * @return true if the animation is played, false otherwise
15119      *
15120      * @see #scrollBy(int, int)
15121      * @see #scrollTo(int, int)
15122      * @see #isHorizontalScrollBarEnabled()
15123      * @see #isVerticalScrollBarEnabled()
15124      * @see #setHorizontalScrollBarEnabled(boolean)
15125      * @see #setVerticalScrollBarEnabled(boolean)
15126      */
15127     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
15128         final ScrollabilityCache scrollCache = mScrollCache;
15129
15130         if (scrollCache == null || !scrollCache.fadeScrollBars) {
15131             return false;
15132         }
15133
15134         if (scrollCache.scrollBar == null) {
15135             scrollCache.scrollBar = new ScrollBarDrawable();
15136             scrollCache.scrollBar.setState(getDrawableState());
15137             scrollCache.scrollBar.setCallback(this);
15138         }
15139
15140         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
15141
15142             if (invalidate) {
15143                 // Invalidate to show the scrollbars
15144                 postInvalidateOnAnimation();
15145             }
15146
15147             if (scrollCache.state == ScrollabilityCache.OFF) {
15148                 // FIXME: this is copied from WindowManagerService.
15149                 // We should get this value from the system when it
15150                 // is possible to do so.
15151                 final int KEY_REPEAT_FIRST_DELAY = 750;
15152                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
15153             }
15154
15155             // Tell mScrollCache when we should start fading. This may
15156             // extend the fade start time if one was already scheduled
15157             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
15158             scrollCache.fadeStartTime = fadeStartTime;
15159             scrollCache.state = ScrollabilityCache.ON;
15160
15161             // Schedule our fader to run, unscheduling any old ones first
15162             if (mAttachInfo != null) {
15163                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
15164                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
15165             }
15166
15167             return true;
15168         }
15169
15170         return false;
15171     }
15172
15173     /**
15174      * Do not invalidate views which are not visible and which are not running an animation. They
15175      * will not get drawn and they should not set dirty flags as if they will be drawn
15176      */
15177     private boolean skipInvalidate() {
15178         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
15179                 (!(mParent instanceof ViewGroup) ||
15180                         !((ViewGroup) mParent).isViewTransitioning(this));
15181     }
15182
15183     /**
15184      * Mark the area defined by dirty as needing to be drawn. If the view is
15185      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15186      * point in the future.
15187      * <p>
15188      * This must be called from a UI thread. To call from a non-UI thread, call
15189      * {@link #postInvalidate()}.
15190      * <p>
15191      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15192      * {@code dirty}.
15193      *
15194      * @param dirty the rectangle representing the bounds of the dirty region
15195      */
15196     public void invalidate(Rect dirty) {
15197         final int scrollX = mScrollX;
15198         final int scrollY = mScrollY;
15199         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15200                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15201     }
15202
15203     /**
15204      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15205      * coordinates of the dirty rect are relative to the view. If the view is
15206      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15207      * point in the future.
15208      * <p>
15209      * This must be called from a UI thread. To call from a non-UI thread, call
15210      * {@link #postInvalidate()}.
15211      *
15212      * @param l the left position of the dirty region
15213      * @param t the top position of the dirty region
15214      * @param r the right position of the dirty region
15215      * @param b the bottom position of the dirty region
15216      */
15217     public void invalidate(int l, int t, int r, int b) {
15218         final int scrollX = mScrollX;
15219         final int scrollY = mScrollY;
15220         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15221     }
15222
15223     /**
15224      * Invalidate the whole view. If the view is visible,
15225      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15226      * the future.
15227      * <p>
15228      * This must be called from a UI thread. To call from a non-UI thread, call
15229      * {@link #postInvalidate()}.
15230      */
15231     public void invalidate() {
15232         invalidate(true);
15233     }
15234
15235     /**
15236      * This is where the invalidate() work actually happens. A full invalidate()
15237      * causes the drawing cache to be invalidated, but this function can be
15238      * called with invalidateCache set to false to skip that invalidation step
15239      * for cases that do not need it (for example, a component that remains at
15240      * the same dimensions with the same content).
15241      *
15242      * @param invalidateCache Whether the drawing cache for this view should be
15243      *            invalidated as well. This is usually true for a full
15244      *            invalidate, but may be set to false if the View's contents or
15245      *            dimensions have not changed.
15246      * @hide
15247      */
15248     public void invalidate(boolean invalidateCache) {
15249         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15250     }
15251
15252     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15253             boolean fullInvalidate) {
15254         if (mGhostView != null) {
15255             mGhostView.invalidate(true);
15256             return;
15257         }
15258
15259         if (skipInvalidate()) {
15260             return;
15261         }
15262
15263         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15264                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15265                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15266                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15267             if (fullInvalidate) {
15268                 mLastIsOpaque = isOpaque();
15269                 mPrivateFlags &= ~PFLAG_DRAWN;
15270             }
15271
15272             mPrivateFlags |= PFLAG_DIRTY;
15273
15274             if (invalidateCache) {
15275                 mPrivateFlags |= PFLAG_INVALIDATED;
15276                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15277             }
15278
15279             // Propagate the damage rectangle to the parent view.
15280             final AttachInfo ai = mAttachInfo;
15281             final ViewParent p = mParent;
15282             if (p != null && ai != null && l < r && t < b) {
15283                 final Rect damage = ai.mTmpInvalRect;
15284                 damage.set(l, t, r, b);
15285                 p.invalidateChild(this, damage);
15286             }
15287
15288             // Damage the entire projection receiver, if necessary.
15289             if (mBackground != null && mBackground.isProjected()) {
15290                 final View receiver = getProjectionReceiver();
15291                 if (receiver != null) {
15292                     receiver.damageInParent();
15293                 }
15294             }
15295         }
15296     }
15297
15298     /**
15299      * @return this view's projection receiver, or {@code null} if none exists
15300      */
15301     private View getProjectionReceiver() {
15302         ViewParent p = getParent();
15303         while (p != null && p instanceof View) {
15304             final View v = (View) p;
15305             if (v.isProjectionReceiver()) {
15306                 return v;
15307             }
15308             p = p.getParent();
15309         }
15310
15311         return null;
15312     }
15313
15314     /**
15315      * @return whether the view is a projection receiver
15316      */
15317     private boolean isProjectionReceiver() {
15318         return mBackground != null;
15319     }
15320
15321     /**
15322      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15323      * set any flags or handle all of the cases handled by the default invalidation methods.
15324      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15325      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15326      * walk up the hierarchy, transforming the dirty rect as necessary.
15327      *
15328      * The method also handles normal invalidation logic if display list properties are not
15329      * being used in this view. The invalidateParent and forceRedraw flags are used by that
15330      * backup approach, to handle these cases used in the various property-setting methods.
15331      *
15332      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15333      * are not being used in this view
15334      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15335      * list properties are not being used in this view
15336      */
15337     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15338         if (!isHardwareAccelerated()
15339                 || !mRenderNode.isValid()
15340                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15341             if (invalidateParent) {
15342                 invalidateParentCaches();
15343             }
15344             if (forceRedraw) {
15345                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15346             }
15347             invalidate(false);
15348         } else {
15349             damageInParent();
15350         }
15351     }
15352
15353     /**
15354      * Tells the parent view to damage this view's bounds.
15355      *
15356      * @hide
15357      */
15358     protected void damageInParent() {
15359         if (mParent != null && mAttachInfo != null) {
15360             mParent.onDescendantInvalidated(this, this);
15361         }
15362     }
15363
15364     /**
15365      * Utility method to transform a given Rect by the current matrix of this view.
15366      */
15367     void transformRect(final Rect rect) {
15368         if (!getMatrix().isIdentity()) {
15369             RectF boundingRect = mAttachInfo.mTmpTransformRect;
15370             boundingRect.set(rect);
15371             getMatrix().mapRect(boundingRect);
15372             rect.set((int) Math.floor(boundingRect.left),
15373                     (int) Math.floor(boundingRect.top),
15374                     (int) Math.ceil(boundingRect.right),
15375                     (int) Math.ceil(boundingRect.bottom));
15376         }
15377     }
15378
15379     /**
15380      * Used to indicate that the parent of this view should clear its caches. This functionality
15381      * is used to force the parent to rebuild its display list (when hardware-accelerated),
15382      * which is necessary when various parent-managed properties of the view change, such as
15383      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15384      * clears the parent caches and does not causes an invalidate event.
15385      *
15386      * @hide
15387      */
15388     protected void invalidateParentCaches() {
15389         if (mParent instanceof View) {
15390             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15391         }
15392     }
15393
15394     /**
15395      * Used to indicate that the parent of this view should be invalidated. This functionality
15396      * is used to force the parent to rebuild its display list (when hardware-accelerated),
15397      * which is necessary when various parent-managed properties of the view change, such as
15398      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15399      * an invalidation event to the parent.
15400      *
15401      * @hide
15402      */
15403     protected void invalidateParentIfNeeded() {
15404         if (isHardwareAccelerated() && mParent instanceof View) {
15405             ((View) mParent).invalidate(true);
15406         }
15407     }
15408
15409     /**
15410      * @hide
15411      */
15412     protected void invalidateParentIfNeededAndWasQuickRejected() {
15413         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15414             // View was rejected last time it was drawn by its parent; this may have changed
15415             invalidateParentIfNeeded();
15416         }
15417     }
15418
15419     /**
15420      * Indicates whether this View is opaque. An opaque View guarantees that it will
15421      * draw all the pixels overlapping its bounds using a fully opaque color.
15422      *
15423      * Subclasses of View should override this method whenever possible to indicate
15424      * whether an instance is opaque. Opaque Views are treated in a special way by
15425      * the View hierarchy, possibly allowing it to perform optimizations during
15426      * invalidate/draw passes.
15427      *
15428      * @return True if this View is guaranteed to be fully opaque, false otherwise.
15429      */
15430     @ViewDebug.ExportedProperty(category = "drawing")
15431     public boolean isOpaque() {
15432         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15433                 getFinalAlpha() >= 1.0f;
15434     }
15435
15436     /**
15437      * @hide
15438      */
15439     protected void computeOpaqueFlags() {
15440         // Opaque if:
15441         //   - Has a background
15442         //   - Background is opaque
15443         //   - Doesn't have scrollbars or scrollbars overlay
15444
15445         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15446             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15447         } else {
15448             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15449         }
15450
15451         final int flags = mViewFlags;
15452         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15453                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15454                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15455             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15456         } else {
15457             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15458         }
15459     }
15460
15461     /**
15462      * @hide
15463      */
15464     protected boolean hasOpaqueScrollbars() {
15465         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15466     }
15467
15468     /**
15469      * @return A handler associated with the thread running the View. This
15470      * handler can be used to pump events in the UI events queue.
15471      */
15472     public Handler getHandler() {
15473         final AttachInfo attachInfo = mAttachInfo;
15474         if (attachInfo != null) {
15475             return attachInfo.mHandler;
15476         }
15477         return null;
15478     }
15479
15480     /**
15481      * Returns the queue of runnable for this view.
15482      *
15483      * @return the queue of runnables for this view
15484      */
15485     private HandlerActionQueue getRunQueue() {
15486         if (mRunQueue == null) {
15487             mRunQueue = new HandlerActionQueue();
15488         }
15489         return mRunQueue;
15490     }
15491
15492     /**
15493      * Gets the view root associated with the View.
15494      * @return The view root, or null if none.
15495      * @hide
15496      */
15497     public ViewRootImpl getViewRootImpl() {
15498         if (mAttachInfo != null) {
15499             return mAttachInfo.mViewRootImpl;
15500         }
15501         return null;
15502     }
15503
15504     /**
15505      * @hide
15506      */
15507     public ThreadedRenderer getThreadedRenderer() {
15508         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15509     }
15510
15511     /**
15512      * <p>Causes the Runnable to be added to the message queue.
15513      * The runnable will be run on the user interface thread.</p>
15514      *
15515      * @param action The Runnable that will be executed.
15516      *
15517      * @return Returns true if the Runnable was successfully placed in to the
15518      *         message queue.  Returns false on failure, usually because the
15519      *         looper processing the message queue is exiting.
15520      *
15521      * @see #postDelayed
15522      * @see #removeCallbacks
15523      */
15524     public boolean post(Runnable action) {
15525         final AttachInfo attachInfo = mAttachInfo;
15526         if (attachInfo != null) {
15527             return attachInfo.mHandler.post(action);
15528         }
15529
15530         // Postpone the runnable until we know on which thread it needs to run.
15531         // Assume that the runnable will be successfully placed after attach.
15532         getRunQueue().post(action);
15533         return true;
15534     }
15535
15536     /**
15537      * <p>Causes the Runnable to be added to the message queue, to be run
15538      * after the specified amount of time elapses.
15539      * The runnable will be run on the user interface thread.</p>
15540      *
15541      * @param action The Runnable that will be executed.
15542      * @param delayMillis The delay (in milliseconds) until the Runnable
15543      *        will be executed.
15544      *
15545      * @return true if the Runnable was successfully placed in to the
15546      *         message queue.  Returns false on failure, usually because the
15547      *         looper processing the message queue is exiting.  Note that a
15548      *         result of true does not mean the Runnable will be processed --
15549      *         if the looper is quit before the delivery time of the message
15550      *         occurs then the message will be dropped.
15551      *
15552      * @see #post
15553      * @see #removeCallbacks
15554      */
15555     public boolean postDelayed(Runnable action, long delayMillis) {
15556         final AttachInfo attachInfo = mAttachInfo;
15557         if (attachInfo != null) {
15558             return attachInfo.mHandler.postDelayed(action, delayMillis);
15559         }
15560
15561         // Postpone the runnable until we know on which thread it needs to run.
15562         // Assume that the runnable will be successfully placed after attach.
15563         getRunQueue().postDelayed(action, delayMillis);
15564         return true;
15565     }
15566
15567     /**
15568      * <p>Causes the Runnable to execute on the next animation time step.
15569      * The runnable will be run on the user interface thread.</p>
15570      *
15571      * @param action The Runnable that will be executed.
15572      *
15573      * @see #postOnAnimationDelayed
15574      * @see #removeCallbacks
15575      */
15576     public void postOnAnimation(Runnable action) {
15577         final AttachInfo attachInfo = mAttachInfo;
15578         if (attachInfo != null) {
15579             attachInfo.mViewRootImpl.mChoreographer.postCallback(
15580                     Choreographer.CALLBACK_ANIMATION, action, null);
15581         } else {
15582             // Postpone the runnable until we know
15583             // on which thread it needs to run.
15584             getRunQueue().post(action);
15585         }
15586     }
15587
15588     /**
15589      * <p>Causes the Runnable to execute on the next animation time step,
15590      * after the specified amount of time elapses.
15591      * The runnable will be run on the user interface thread.</p>
15592      *
15593      * @param action The Runnable that will be executed.
15594      * @param delayMillis The delay (in milliseconds) until the Runnable
15595      *        will be executed.
15596      *
15597      * @see #postOnAnimation
15598      * @see #removeCallbacks
15599      */
15600     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15601         final AttachInfo attachInfo = mAttachInfo;
15602         if (attachInfo != null) {
15603             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15604                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15605         } else {
15606             // Postpone the runnable until we know
15607             // on which thread it needs to run.
15608             getRunQueue().postDelayed(action, delayMillis);
15609         }
15610     }
15611
15612     /**
15613      * <p>Removes the specified Runnable from the message queue.</p>
15614      *
15615      * @param action The Runnable to remove from the message handling queue
15616      *
15617      * @return true if this view could ask the Handler to remove the Runnable,
15618      *         false otherwise. When the returned value is true, the Runnable
15619      *         may or may not have been actually removed from the message queue
15620      *         (for instance, if the Runnable was not in the queue already.)
15621      *
15622      * @see #post
15623      * @see #postDelayed
15624      * @see #postOnAnimation
15625      * @see #postOnAnimationDelayed
15626      */
15627     public boolean removeCallbacks(Runnable action) {
15628         if (action != null) {
15629             final AttachInfo attachInfo = mAttachInfo;
15630             if (attachInfo != null) {
15631                 attachInfo.mHandler.removeCallbacks(action);
15632                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15633                         Choreographer.CALLBACK_ANIMATION, action, null);
15634             }
15635             getRunQueue().removeCallbacks(action);
15636         }
15637         return true;
15638     }
15639
15640     /**
15641      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15642      * Use this to invalidate the View from a non-UI thread.</p>
15643      *
15644      * <p>This method can be invoked from outside of the UI thread
15645      * only when this View is attached to a window.</p>
15646      *
15647      * @see #invalidate()
15648      * @see #postInvalidateDelayed(long)
15649      */
15650     public void postInvalidate() {
15651         postInvalidateDelayed(0);
15652     }
15653
15654     /**
15655      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15656      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15657      *
15658      * <p>This method can be invoked from outside of the UI thread
15659      * only when this View is attached to a window.</p>
15660      *
15661      * @param left The left coordinate of the rectangle to invalidate.
15662      * @param top The top coordinate of the rectangle to invalidate.
15663      * @param right The right coordinate of the rectangle to invalidate.
15664      * @param bottom The bottom coordinate of the rectangle to invalidate.
15665      *
15666      * @see #invalidate(int, int, int, int)
15667      * @see #invalidate(Rect)
15668      * @see #postInvalidateDelayed(long, int, int, int, int)
15669      */
15670     public void postInvalidate(int left, int top, int right, int bottom) {
15671         postInvalidateDelayed(0, left, top, right, bottom);
15672     }
15673
15674     /**
15675      * <p>Cause an invalidate to happen on a subsequent cycle through the event
15676      * loop. Waits for the specified amount of time.</p>
15677      *
15678      * <p>This method can be invoked from outside of the UI thread
15679      * only when this View is attached to a window.</p>
15680      *
15681      * @param delayMilliseconds the duration in milliseconds to delay the
15682      *         invalidation by
15683      *
15684      * @see #invalidate()
15685      * @see #postInvalidate()
15686      */
15687     public void postInvalidateDelayed(long delayMilliseconds) {
15688         // We try only with the AttachInfo because there's no point in invalidating
15689         // if we are not attached to our window
15690         final AttachInfo attachInfo = mAttachInfo;
15691         if (attachInfo != null) {
15692             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15693         }
15694     }
15695
15696     /**
15697      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15698      * through the event loop. Waits for the specified amount of time.</p>
15699      *
15700      * <p>This method can be invoked from outside of the UI thread
15701      * only when this View is attached to a window.</p>
15702      *
15703      * @param delayMilliseconds the duration in milliseconds to delay the
15704      *         invalidation by
15705      * @param left The left coordinate of the rectangle to invalidate.
15706      * @param top The top coordinate of the rectangle to invalidate.
15707      * @param right The right coordinate of the rectangle to invalidate.
15708      * @param bottom The bottom coordinate of the rectangle to invalidate.
15709      *
15710      * @see #invalidate(int, int, int, int)
15711      * @see #invalidate(Rect)
15712      * @see #postInvalidate(int, int, int, int)
15713      */
15714     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15715             int right, int bottom) {
15716
15717         // We try only with the AttachInfo because there's no point in invalidating
15718         // if we are not attached to our window
15719         final AttachInfo attachInfo = mAttachInfo;
15720         if (attachInfo != null) {
15721             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15722             info.target = this;
15723             info.left = left;
15724             info.top = top;
15725             info.right = right;
15726             info.bottom = bottom;
15727
15728             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15729         }
15730     }
15731
15732     /**
15733      * <p>Cause an invalidate to happen on the next animation time step, typically the
15734      * next display frame.</p>
15735      *
15736      * <p>This method can be invoked from outside of the UI thread
15737      * only when this View is attached to a window.</p>
15738      *
15739      * @see #invalidate()
15740      */
15741     public void postInvalidateOnAnimation() {
15742         // We try only with the AttachInfo because there's no point in invalidating
15743         // if we are not attached to our window
15744         final AttachInfo attachInfo = mAttachInfo;
15745         if (attachInfo != null) {
15746             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15747         }
15748     }
15749
15750     /**
15751      * <p>Cause an invalidate of the specified area to happen on the next animation
15752      * time step, typically the next display frame.</p>
15753      *
15754      * <p>This method can be invoked from outside of the UI thread
15755      * only when this View is attached to a window.</p>
15756      *
15757      * @param left The left coordinate of the rectangle to invalidate.
15758      * @param top The top coordinate of the rectangle to invalidate.
15759      * @param right The right coordinate of the rectangle to invalidate.
15760      * @param bottom The bottom coordinate of the rectangle to invalidate.
15761      *
15762      * @see #invalidate(int, int, int, int)
15763      * @see #invalidate(Rect)
15764      */
15765     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15766         // We try only with the AttachInfo because there's no point in invalidating
15767         // if we are not attached to our window
15768         final AttachInfo attachInfo = mAttachInfo;
15769         if (attachInfo != null) {
15770             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15771             info.target = this;
15772             info.left = left;
15773             info.top = top;
15774             info.right = right;
15775             info.bottom = bottom;
15776
15777             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15778         }
15779     }
15780
15781     /**
15782      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15783      * This event is sent at most once every
15784      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15785      */
15786     private void postSendViewScrolledAccessibilityEventCallback() {
15787         if (mSendViewScrolledAccessibilityEvent == null) {
15788             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15789         }
15790         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15791             mSendViewScrolledAccessibilityEvent.mIsPending = true;
15792             postDelayed(mSendViewScrolledAccessibilityEvent,
15793                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15794         }
15795     }
15796
15797     /**
15798      * Called by a parent to request that a child update its values for mScrollX
15799      * and mScrollY if necessary. This will typically be done if the child is
15800      * animating a scroll using a {@link android.widget.Scroller Scroller}
15801      * object.
15802      */
15803     public void computeScroll() {
15804     }
15805
15806     /**
15807      * <p>Indicate whether the horizontal edges are faded when the view is
15808      * scrolled horizontally.</p>
15809      *
15810      * @return true if the horizontal edges should are faded on scroll, false
15811      *         otherwise
15812      *
15813      * @see #setHorizontalFadingEdgeEnabled(boolean)
15814      *
15815      * @attr ref android.R.styleable#View_requiresFadingEdge
15816      */
15817     public boolean isHorizontalFadingEdgeEnabled() {
15818         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15819     }
15820
15821     /**
15822      * <p>Define whether the horizontal edges should be faded when this view
15823      * is scrolled horizontally.</p>
15824      *
15825      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15826      *                                    be faded when the view is scrolled
15827      *                                    horizontally
15828      *
15829      * @see #isHorizontalFadingEdgeEnabled()
15830      *
15831      * @attr ref android.R.styleable#View_requiresFadingEdge
15832      */
15833     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15834         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15835             if (horizontalFadingEdgeEnabled) {
15836                 initScrollCache();
15837             }
15838
15839             mViewFlags ^= FADING_EDGE_HORIZONTAL;
15840         }
15841     }
15842
15843     /**
15844      * <p>Indicate whether the vertical edges are faded when the view is
15845      * scrolled horizontally.</p>
15846      *
15847      * @return true if the vertical edges should are faded on scroll, false
15848      *         otherwise
15849      *
15850      * @see #setVerticalFadingEdgeEnabled(boolean)
15851      *
15852      * @attr ref android.R.styleable#View_requiresFadingEdge
15853      */
15854     public boolean isVerticalFadingEdgeEnabled() {
15855         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15856     }
15857
15858     /**
15859      * <p>Define whether the vertical edges should be faded when this view
15860      * is scrolled vertically.</p>
15861      *
15862      * @param verticalFadingEdgeEnabled true if the vertical edges should
15863      *                                  be faded when the view is scrolled
15864      *                                  vertically
15865      *
15866      * @see #isVerticalFadingEdgeEnabled()
15867      *
15868      * @attr ref android.R.styleable#View_requiresFadingEdge
15869      */
15870     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15871         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15872             if (verticalFadingEdgeEnabled) {
15873                 initScrollCache();
15874             }
15875
15876             mViewFlags ^= FADING_EDGE_VERTICAL;
15877         }
15878     }
15879
15880     /**
15881      * Returns the strength, or intensity, of the top faded edge. The strength is
15882      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15883      * returns 0.0 or 1.0 but no value in between.
15884      *
15885      * Subclasses should override this method to provide a smoother fade transition
15886      * when scrolling occurs.
15887      *
15888      * @return the intensity of the top fade as a float between 0.0f and 1.0f
15889      */
15890     protected float getTopFadingEdgeStrength() {
15891         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15892     }
15893
15894     /**
15895      * Returns the strength, or intensity, of the bottom faded edge. The strength is
15896      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15897      * returns 0.0 or 1.0 but no value in between.
15898      *
15899      * Subclasses should override this method to provide a smoother fade transition
15900      * when scrolling occurs.
15901      *
15902      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15903      */
15904     protected float getBottomFadingEdgeStrength() {
15905         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15906                 computeVerticalScrollRange() ? 1.0f : 0.0f;
15907     }
15908
15909     /**
15910      * Returns the strength, or intensity, of the left faded edge. The strength is
15911      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15912      * returns 0.0 or 1.0 but no value in between.
15913      *
15914      * Subclasses should override this method to provide a smoother fade transition
15915      * when scrolling occurs.
15916      *
15917      * @return the intensity of the left fade as a float between 0.0f and 1.0f
15918      */
15919     protected float getLeftFadingEdgeStrength() {
15920         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15921     }
15922
15923     /**
15924      * Returns the strength, or intensity, of the right faded edge. The strength is
15925      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15926      * returns 0.0 or 1.0 but no value in between.
15927      *
15928      * Subclasses should override this method to provide a smoother fade transition
15929      * when scrolling occurs.
15930      *
15931      * @return the intensity of the right fade as a float between 0.0f and 1.0f
15932      */
15933     protected float getRightFadingEdgeStrength() {
15934         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15935                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
15936     }
15937
15938     /**
15939      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15940      * scrollbar is not drawn by default.</p>
15941      *
15942      * @return true if the horizontal scrollbar should be painted, false
15943      *         otherwise
15944      *
15945      * @see #setHorizontalScrollBarEnabled(boolean)
15946      */
15947     public boolean isHorizontalScrollBarEnabled() {
15948         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15949     }
15950
15951     /**
15952      * <p>Define whether the horizontal scrollbar should be drawn or not. The
15953      * scrollbar is not drawn by default.</p>
15954      *
15955      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15956      *                                   be painted
15957      *
15958      * @see #isHorizontalScrollBarEnabled()
15959      */
15960     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15961         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15962             mViewFlags ^= SCROLLBARS_HORIZONTAL;
15963             computeOpaqueFlags();
15964             resolvePadding();
15965         }
15966     }
15967
15968     /**
15969      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15970      * scrollbar is not drawn by default.</p>
15971      *
15972      * @return true if the vertical scrollbar should be painted, false
15973      *         otherwise
15974      *
15975      * @see #setVerticalScrollBarEnabled(boolean)
15976      */
15977     public boolean isVerticalScrollBarEnabled() {
15978         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15979     }
15980
15981     /**
15982      * <p>Define whether the vertical scrollbar should be drawn or not. The
15983      * scrollbar is not drawn by default.</p>
15984      *
15985      * @param verticalScrollBarEnabled true if the vertical scrollbar should
15986      *                                 be painted
15987      *
15988      * @see #isVerticalScrollBarEnabled()
15989      */
15990     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15991         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15992             mViewFlags ^= SCROLLBARS_VERTICAL;
15993             computeOpaqueFlags();
15994             resolvePadding();
15995         }
15996     }
15997
15998     /**
15999      * @hide
16000      */
16001     protected void recomputePadding() {
16002         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16003     }
16004
16005     /**
16006      * Define whether scrollbars will fade when the view is not scrolling.
16007      *
16008      * @param fadeScrollbars whether to enable fading
16009      *
16010      * @attr ref android.R.styleable#View_fadeScrollbars
16011      */
16012     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
16013         initScrollCache();
16014         final ScrollabilityCache scrollabilityCache = mScrollCache;
16015         scrollabilityCache.fadeScrollBars = fadeScrollbars;
16016         if (fadeScrollbars) {
16017             scrollabilityCache.state = ScrollabilityCache.OFF;
16018         } else {
16019             scrollabilityCache.state = ScrollabilityCache.ON;
16020         }
16021     }
16022
16023     /**
16024      *
16025      * Returns true if scrollbars will fade when this view is not scrolling
16026      *
16027      * @return true if scrollbar fading is enabled
16028      *
16029      * @attr ref android.R.styleable#View_fadeScrollbars
16030      */
16031     public boolean isScrollbarFadingEnabled() {
16032         return mScrollCache != null && mScrollCache.fadeScrollBars;
16033     }
16034
16035     /**
16036      *
16037      * Returns the delay before scrollbars fade.
16038      *
16039      * @return the delay before scrollbars fade
16040      *
16041      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16042      */
16043     public int getScrollBarDefaultDelayBeforeFade() {
16044         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
16045                 mScrollCache.scrollBarDefaultDelayBeforeFade;
16046     }
16047
16048     /**
16049      * Define the delay before scrollbars fade.
16050      *
16051      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
16052      *
16053      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16054      */
16055     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
16056         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
16057     }
16058
16059     /**
16060      *
16061      * Returns the scrollbar fade duration.
16062      *
16063      * @return the scrollbar fade duration, in milliseconds
16064      *
16065      * @attr ref android.R.styleable#View_scrollbarFadeDuration
16066      */
16067     public int getScrollBarFadeDuration() {
16068         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
16069                 mScrollCache.scrollBarFadeDuration;
16070     }
16071
16072     /**
16073      * Define the scrollbar fade duration.
16074      *
16075      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
16076      *
16077      * @attr ref android.R.styleable#View_scrollbarFadeDuration
16078      */
16079     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
16080         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
16081     }
16082
16083     /**
16084      *
16085      * Returns the scrollbar size.
16086      *
16087      * @return the scrollbar size
16088      *
16089      * @attr ref android.R.styleable#View_scrollbarSize
16090      */
16091     public int getScrollBarSize() {
16092         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
16093                 mScrollCache.scrollBarSize;
16094     }
16095
16096     /**
16097      * Define the scrollbar size.
16098      *
16099      * @param scrollBarSize - the scrollbar size
16100      *
16101      * @attr ref android.R.styleable#View_scrollbarSize
16102      */
16103     public void setScrollBarSize(int scrollBarSize) {
16104         getScrollCache().scrollBarSize = scrollBarSize;
16105     }
16106
16107     /**
16108      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
16109      * inset. When inset, they add to the padding of the view. And the scrollbars
16110      * can be drawn inside the padding area or on the edge of the view. For example,
16111      * if a view has a background drawable and you want to draw the scrollbars
16112      * inside the padding specified by the drawable, you can use
16113      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
16114      * appear at the edge of the view, ignoring the padding, then you can use
16115      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
16116      * @param style the style of the scrollbars. Should be one of
16117      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
16118      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
16119      * @see #SCROLLBARS_INSIDE_OVERLAY
16120      * @see #SCROLLBARS_INSIDE_INSET
16121      * @see #SCROLLBARS_OUTSIDE_OVERLAY
16122      * @see #SCROLLBARS_OUTSIDE_INSET
16123      *
16124      * @attr ref android.R.styleable#View_scrollbarStyle
16125      */
16126     public void setScrollBarStyle(@ScrollBarStyle int style) {
16127         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
16128             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
16129             computeOpaqueFlags();
16130             resolvePadding();
16131         }
16132     }
16133
16134     /**
16135      * <p>Returns the current scrollbar style.</p>
16136      * @return the current scrollbar style
16137      * @see #SCROLLBARS_INSIDE_OVERLAY
16138      * @see #SCROLLBARS_INSIDE_INSET
16139      * @see #SCROLLBARS_OUTSIDE_OVERLAY
16140      * @see #SCROLLBARS_OUTSIDE_INSET
16141      *
16142      * @attr ref android.R.styleable#View_scrollbarStyle
16143      */
16144     @ViewDebug.ExportedProperty(mapping = {
16145             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
16146             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
16147             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
16148             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
16149     })
16150     @ScrollBarStyle
16151     public int getScrollBarStyle() {
16152         return mViewFlags & SCROLLBARS_STYLE_MASK;
16153     }
16154
16155     /**
16156      * <p>Compute the horizontal range that the horizontal scrollbar
16157      * represents.</p>
16158      *
16159      * <p>The range is expressed in arbitrary units that must be the same as the
16160      * units used by {@link #computeHorizontalScrollExtent()} and
16161      * {@link #computeHorizontalScrollOffset()}.</p>
16162      *
16163      * <p>The default range is the drawing width of this view.</p>
16164      *
16165      * @return the total horizontal range represented by the horizontal
16166      *         scrollbar
16167      *
16168      * @see #computeHorizontalScrollExtent()
16169      * @see #computeHorizontalScrollOffset()
16170      * @see android.widget.ScrollBarDrawable
16171      */
16172     protected int computeHorizontalScrollRange() {
16173         return getWidth();
16174     }
16175
16176     /**
16177      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
16178      * within the horizontal range. This value is used to compute the position
16179      * of the thumb within the scrollbar's track.</p>
16180      *
16181      * <p>The range is expressed in arbitrary units that must be the same as the
16182      * units used by {@link #computeHorizontalScrollRange()} and
16183      * {@link #computeHorizontalScrollExtent()}.</p>
16184      *
16185      * <p>The default offset is the scroll offset of this view.</p>
16186      *
16187      * @return the horizontal offset of the scrollbar's thumb
16188      *
16189      * @see #computeHorizontalScrollRange()
16190      * @see #computeHorizontalScrollExtent()
16191      * @see android.widget.ScrollBarDrawable
16192      */
16193     protected int computeHorizontalScrollOffset() {
16194         return mScrollX;
16195     }
16196
16197     /**
16198      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16199      * within the horizontal range. This value is used to compute the length
16200      * of the thumb within the scrollbar's track.</p>
16201      *
16202      * <p>The range is expressed in arbitrary units that must be the same as the
16203      * units used by {@link #computeHorizontalScrollRange()} and
16204      * {@link #computeHorizontalScrollOffset()}.</p>
16205      *
16206      * <p>The default extent is the drawing width of this view.</p>
16207      *
16208      * @return the horizontal extent of the scrollbar's thumb
16209      *
16210      * @see #computeHorizontalScrollRange()
16211      * @see #computeHorizontalScrollOffset()
16212      * @see android.widget.ScrollBarDrawable
16213      */
16214     protected int computeHorizontalScrollExtent() {
16215         return getWidth();
16216     }
16217
16218     /**
16219      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16220      *
16221      * <p>The range is expressed in arbitrary units that must be the same as the
16222      * units used by {@link #computeVerticalScrollExtent()} and
16223      * {@link #computeVerticalScrollOffset()}.</p>
16224      *
16225      * @return the total vertical range represented by the vertical scrollbar
16226      *
16227      * <p>The default range is the drawing height of this view.</p>
16228      *
16229      * @see #computeVerticalScrollExtent()
16230      * @see #computeVerticalScrollOffset()
16231      * @see android.widget.ScrollBarDrawable
16232      */
16233     protected int computeVerticalScrollRange() {
16234         return getHeight();
16235     }
16236
16237     /**
16238      * <p>Compute the vertical offset of the vertical scrollbar's thumb
16239      * within the horizontal range. This value is used to compute the position
16240      * of the thumb within the scrollbar's track.</p>
16241      *
16242      * <p>The range is expressed in arbitrary units that must be the same as the
16243      * units used by {@link #computeVerticalScrollRange()} and
16244      * {@link #computeVerticalScrollExtent()}.</p>
16245      *
16246      * <p>The default offset is the scroll offset of this view.</p>
16247      *
16248      * @return the vertical offset of the scrollbar's thumb
16249      *
16250      * @see #computeVerticalScrollRange()
16251      * @see #computeVerticalScrollExtent()
16252      * @see android.widget.ScrollBarDrawable
16253      */
16254     protected int computeVerticalScrollOffset() {
16255         return mScrollY;
16256     }
16257
16258     /**
16259      * <p>Compute the vertical extent of the vertical scrollbar's thumb
16260      * within the vertical range. This value is used to compute the length
16261      * of the thumb within the scrollbar's track.</p>
16262      *
16263      * <p>The range is expressed in arbitrary units that must be the same as the
16264      * units used by {@link #computeVerticalScrollRange()} and
16265      * {@link #computeVerticalScrollOffset()}.</p>
16266      *
16267      * <p>The default extent is the drawing height of this view.</p>
16268      *
16269      * @return the vertical extent of the scrollbar's thumb
16270      *
16271      * @see #computeVerticalScrollRange()
16272      * @see #computeVerticalScrollOffset()
16273      * @see android.widget.ScrollBarDrawable
16274      */
16275     protected int computeVerticalScrollExtent() {
16276         return getHeight();
16277     }
16278
16279     /**
16280      * Check if this view can be scrolled horizontally in a certain direction.
16281      *
16282      * @param direction Negative to check scrolling left, positive to check scrolling right.
16283      * @return true if this view can be scrolled in the specified direction, false otherwise.
16284      */
16285     public boolean canScrollHorizontally(int direction) {
16286         final int offset = computeHorizontalScrollOffset();
16287         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16288         if (range == 0) return false;
16289         if (direction < 0) {
16290             return offset > 0;
16291         } else {
16292             return offset < range - 1;
16293         }
16294     }
16295
16296     /**
16297      * Check if this view can be scrolled vertically in a certain direction.
16298      *
16299      * @param direction Negative to check scrolling up, positive to check scrolling down.
16300      * @return true if this view can be scrolled in the specified direction, false otherwise.
16301      */
16302     public boolean canScrollVertically(int direction) {
16303         final int offset = computeVerticalScrollOffset();
16304         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16305         if (range == 0) return false;
16306         if (direction < 0) {
16307             return offset > 0;
16308         } else {
16309             return offset < range - 1;
16310         }
16311     }
16312
16313     void getScrollIndicatorBounds(@NonNull Rect out) {
16314         out.left = mScrollX;
16315         out.right = mScrollX + mRight - mLeft;
16316         out.top = mScrollY;
16317         out.bottom = mScrollY + mBottom - mTop;
16318     }
16319
16320     private void onDrawScrollIndicators(Canvas c) {
16321         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16322             // No scroll indicators enabled.
16323             return;
16324         }
16325
16326         final Drawable dr = mScrollIndicatorDrawable;
16327         if (dr == null) {
16328             // Scroll indicators aren't supported here.
16329             return;
16330         }
16331
16332         final int h = dr.getIntrinsicHeight();
16333         final int w = dr.getIntrinsicWidth();
16334         final Rect rect = mAttachInfo.mTmpInvalRect;
16335         getScrollIndicatorBounds(rect);
16336
16337         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16338             final boolean canScrollUp = canScrollVertically(-1);
16339             if (canScrollUp) {
16340                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16341                 dr.draw(c);
16342             }
16343         }
16344
16345         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16346             final boolean canScrollDown = canScrollVertically(1);
16347             if (canScrollDown) {
16348                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16349                 dr.draw(c);
16350             }
16351         }
16352
16353         final int leftRtl;
16354         final int rightRtl;
16355         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16356             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16357             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16358         } else {
16359             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16360             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16361         }
16362
16363         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16364         if ((mPrivateFlags3 & leftMask) != 0) {
16365             final boolean canScrollLeft = canScrollHorizontally(-1);
16366             if (canScrollLeft) {
16367                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16368                 dr.draw(c);
16369             }
16370         }
16371
16372         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16373         if ((mPrivateFlags3 & rightMask) != 0) {
16374             final boolean canScrollRight = canScrollHorizontally(1);
16375             if (canScrollRight) {
16376                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16377                 dr.draw(c);
16378             }
16379         }
16380     }
16381
16382     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16383             @Nullable Rect touchBounds) {
16384         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16385         if (bounds == null) {
16386             return;
16387         }
16388         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16389         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16390                 && !isVerticalScrollBarHidden();
16391         final int size = getHorizontalScrollbarHeight();
16392         final int verticalScrollBarGap = drawVerticalScrollBar ?
16393                 getVerticalScrollbarWidth() : 0;
16394         final int width = mRight - mLeft;
16395         final int height = mBottom - mTop;
16396         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16397         bounds.left = mScrollX + (mPaddingLeft & inside);
16398         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16399         bounds.bottom = bounds.top + size;
16400
16401         if (touchBounds == null) {
16402             return;
16403         }
16404         if (touchBounds != bounds) {
16405             touchBounds.set(bounds);
16406         }
16407         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16408         if (touchBounds.height() < minTouchTarget) {
16409             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16410             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16411             touchBounds.top = touchBounds.bottom - minTouchTarget;
16412         }
16413         if (touchBounds.width() < minTouchTarget) {
16414             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16415             touchBounds.left -= adjust;
16416             touchBounds.right = touchBounds.left + minTouchTarget;
16417         }
16418     }
16419
16420     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16421         if (mRoundScrollbarRenderer == null) {
16422             getStraightVerticalScrollBarBounds(bounds, touchBounds);
16423         } else {
16424             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16425         }
16426     }
16427
16428     private void getRoundVerticalScrollBarBounds(Rect bounds) {
16429         final int width = mRight - mLeft;
16430         final int height = mBottom - mTop;
16431         // Do not take padding into account as we always want the scrollbars
16432         // to hug the screen for round wearable devices.
16433         bounds.left = mScrollX;
16434         bounds.top = mScrollY;
16435         bounds.right = bounds.left + width;
16436         bounds.bottom = mScrollY + height;
16437     }
16438
16439     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16440             @Nullable Rect touchBounds) {
16441         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16442         if (bounds == null) {
16443             return;
16444         }
16445         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16446         final int size = getVerticalScrollbarWidth();
16447         int verticalScrollbarPosition = mVerticalScrollbarPosition;
16448         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16449             verticalScrollbarPosition = isLayoutRtl() ?
16450                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16451         }
16452         final int width = mRight - mLeft;
16453         final int height = mBottom - mTop;
16454         switch (verticalScrollbarPosition) {
16455             default:
16456             case SCROLLBAR_POSITION_RIGHT:
16457                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16458                 break;
16459             case SCROLLBAR_POSITION_LEFT:
16460                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
16461                 break;
16462         }
16463         bounds.top = mScrollY + (mPaddingTop & inside);
16464         bounds.right = bounds.left + size;
16465         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16466
16467         if (touchBounds == null) {
16468             return;
16469         }
16470         if (touchBounds != bounds) {
16471             touchBounds.set(bounds);
16472         }
16473         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16474         if (touchBounds.width() < minTouchTarget) {
16475             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16476             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16477                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16478                 touchBounds.left = touchBounds.right - minTouchTarget;
16479             } else {
16480                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16481                 touchBounds.right = touchBounds.left + minTouchTarget;
16482             }
16483         }
16484         if (touchBounds.height() < minTouchTarget) {
16485             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16486             touchBounds.top -= adjust;
16487             touchBounds.bottom = touchBounds.top + minTouchTarget;
16488         }
16489     }
16490
16491     /**
16492      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16493      * scrollbars are painted only if they have been awakened first.</p>
16494      *
16495      * @param canvas the canvas on which to draw the scrollbars
16496      *
16497      * @see #awakenScrollBars(int)
16498      */
16499     protected final void onDrawScrollBars(Canvas canvas) {
16500         // scrollbars are drawn only when the animation is running
16501         final ScrollabilityCache cache = mScrollCache;
16502
16503         if (cache != null) {
16504
16505             int state = cache.state;
16506
16507             if (state == ScrollabilityCache.OFF) {
16508                 return;
16509             }
16510
16511             boolean invalidate = false;
16512
16513             if (state == ScrollabilityCache.FADING) {
16514                 // We're fading -- get our fade interpolation
16515                 if (cache.interpolatorValues == null) {
16516                     cache.interpolatorValues = new float[1];
16517                 }
16518
16519                 float[] values = cache.interpolatorValues;
16520
16521                 // Stops the animation if we're done
16522                 if (cache.scrollBarInterpolator.timeToValues(values) ==
16523                         Interpolator.Result.FREEZE_END) {
16524                     cache.state = ScrollabilityCache.OFF;
16525                 } else {
16526                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16527                 }
16528
16529                 // This will make the scroll bars inval themselves after
16530                 // drawing. We only want this when we're fading so that
16531                 // we prevent excessive redraws
16532                 invalidate = true;
16533             } else {
16534                 // We're just on -- but we may have been fading before so
16535                 // reset alpha
16536                 cache.scrollBar.mutate().setAlpha(255);
16537             }
16538
16539             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16540             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16541                     && !isVerticalScrollBarHidden();
16542
16543             // Fork out the scroll bar drawing for round wearable devices.
16544             if (mRoundScrollbarRenderer != null) {
16545                 if (drawVerticalScrollBar) {
16546                     final Rect bounds = cache.mScrollBarBounds;
16547                     getVerticalScrollBarBounds(bounds, null);
16548                     mRoundScrollbarRenderer.drawRoundScrollbars(
16549                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16550                     if (invalidate) {
16551                         invalidate();
16552                     }
16553                 }
16554                 // Do not draw horizontal scroll bars for round wearable devices.
16555             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16556                 final ScrollBarDrawable scrollBar = cache.scrollBar;
16557
16558                 if (drawHorizontalScrollBar) {
16559                     scrollBar.setParameters(computeHorizontalScrollRange(),
16560                             computeHorizontalScrollOffset(),
16561                             computeHorizontalScrollExtent(), false);
16562                     final Rect bounds = cache.mScrollBarBounds;
16563                     getHorizontalScrollBarBounds(bounds, null);
16564                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16565                             bounds.right, bounds.bottom);
16566                     if (invalidate) {
16567                         invalidate(bounds);
16568                     }
16569                 }
16570
16571                 if (drawVerticalScrollBar) {
16572                     scrollBar.setParameters(computeVerticalScrollRange(),
16573                             computeVerticalScrollOffset(),
16574                             computeVerticalScrollExtent(), true);
16575                     final Rect bounds = cache.mScrollBarBounds;
16576                     getVerticalScrollBarBounds(bounds, null);
16577                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16578                             bounds.right, bounds.bottom);
16579                     if (invalidate) {
16580                         invalidate(bounds);
16581                     }
16582                 }
16583             }
16584         }
16585     }
16586
16587     /**
16588      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16589      * FastScroller is visible.
16590      * @return whether to temporarily hide the vertical scrollbar
16591      * @hide
16592      */
16593     protected boolean isVerticalScrollBarHidden() {
16594         return false;
16595     }
16596
16597     /**
16598      * <p>Draw the horizontal scrollbar if
16599      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16600      *
16601      * @param canvas the canvas on which to draw the scrollbar
16602      * @param scrollBar the scrollbar's drawable
16603      *
16604      * @see #isHorizontalScrollBarEnabled()
16605      * @see #computeHorizontalScrollRange()
16606      * @see #computeHorizontalScrollExtent()
16607      * @see #computeHorizontalScrollOffset()
16608      * @see android.widget.ScrollBarDrawable
16609      * @hide
16610      */
16611     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16612             int l, int t, int r, int b) {
16613         scrollBar.setBounds(l, t, r, b);
16614         scrollBar.draw(canvas);
16615     }
16616
16617     /**
16618      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16619      * returns true.</p>
16620      *
16621      * @param canvas the canvas on which to draw the scrollbar
16622      * @param scrollBar the scrollbar's drawable
16623      *
16624      * @see #isVerticalScrollBarEnabled()
16625      * @see #computeVerticalScrollRange()
16626      * @see #computeVerticalScrollExtent()
16627      * @see #computeVerticalScrollOffset()
16628      * @see android.widget.ScrollBarDrawable
16629      * @hide
16630      */
16631     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16632             int l, int t, int r, int b) {
16633         scrollBar.setBounds(l, t, r, b);
16634         scrollBar.draw(canvas);
16635     }
16636
16637     /**
16638      * Implement this to do your drawing.
16639      *
16640      * @param canvas the canvas on which the background will be drawn
16641      */
16642     protected void onDraw(Canvas canvas) {
16643     }
16644
16645     /*
16646      * Caller is responsible for calling requestLayout if necessary.
16647      * (This allows addViewInLayout to not request a new layout.)
16648      */
16649     void assignParent(ViewParent parent) {
16650         if (mParent == null) {
16651             mParent = parent;
16652         } else if (parent == null) {
16653             mParent = null;
16654         } else {
16655             throw new RuntimeException("view " + this + " being added, but"
16656                     + " it already has a parent");
16657         }
16658     }
16659
16660     /**
16661      * This is called when the view is attached to a window.  At this point it
16662      * has a Surface and will start drawing.  Note that this function is
16663      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16664      * however it may be called any time before the first onDraw -- including
16665      * before or after {@link #onMeasure(int, int)}.
16666      *
16667      * @see #onDetachedFromWindow()
16668      */
16669     @CallSuper
16670     protected void onAttachedToWindow() {
16671         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16672             mParent.requestTransparentRegion(this);
16673         }
16674
16675         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16676
16677         jumpDrawablesToCurrentState();
16678
16679         resetSubtreeAccessibilityStateChanged();
16680
16681         // rebuild, since Outline not maintained while View is detached
16682         rebuildOutline();
16683
16684         if (isFocused()) {
16685             InputMethodManager imm = InputMethodManager.peekInstance();
16686             if (imm != null) {
16687                 imm.focusIn(this);
16688             }
16689         }
16690     }
16691
16692     /**
16693      * Resolve all RTL related properties.
16694      *
16695      * @return true if resolution of RTL properties has been done
16696      *
16697      * @hide
16698      */
16699     public boolean resolveRtlPropertiesIfNeeded() {
16700         if (!needRtlPropertiesResolution()) return false;
16701
16702         // Order is important here: LayoutDirection MUST be resolved first
16703         if (!isLayoutDirectionResolved()) {
16704             resolveLayoutDirection();
16705             resolveLayoutParams();
16706         }
16707         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16708         if (!isTextDirectionResolved()) {
16709             resolveTextDirection();
16710         }
16711         if (!isTextAlignmentResolved()) {
16712             resolveTextAlignment();
16713         }
16714         // Should resolve Drawables before Padding because we need the layout direction of the
16715         // Drawable to correctly resolve Padding.
16716         if (!areDrawablesResolved()) {
16717             resolveDrawables();
16718         }
16719         if (!isPaddingResolved()) {
16720             resolvePadding();
16721         }
16722         onRtlPropertiesChanged(getLayoutDirection());
16723         return true;
16724     }
16725
16726     /**
16727      * Reset resolution of all RTL related properties.
16728      *
16729      * @hide
16730      */
16731     public void resetRtlProperties() {
16732         resetResolvedLayoutDirection();
16733         resetResolvedTextDirection();
16734         resetResolvedTextAlignment();
16735         resetResolvedPadding();
16736         resetResolvedDrawables();
16737     }
16738
16739     /**
16740      * @see #onScreenStateChanged(int)
16741      */
16742     void dispatchScreenStateChanged(int screenState) {
16743         onScreenStateChanged(screenState);
16744     }
16745
16746     /**
16747      * This method is called whenever the state of the screen this view is
16748      * attached to changes. A state change will usually occurs when the screen
16749      * turns on or off (whether it happens automatically or the user does it
16750      * manually.)
16751      *
16752      * @param screenState The new state of the screen. Can be either
16753      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16754      */
16755     public void onScreenStateChanged(int screenState) {
16756     }
16757
16758     /**
16759      * @see #onMovedToDisplay(int, Configuration)
16760      */
16761     void dispatchMovedToDisplay(Display display, Configuration config) {
16762         mAttachInfo.mDisplay = display;
16763         mAttachInfo.mDisplayState = display.getState();
16764         onMovedToDisplay(display.getDisplayId(), config);
16765     }
16766
16767     /**
16768      * Called by the system when the hosting activity is moved from one display to another without
16769      * recreation. This means that the activity is declared to handle all changes to configuration
16770      * that happened when it was switched to another display, so it wasn't destroyed and created
16771      * again.
16772      *
16773      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16774      * applied configuration actually changed. It is up to app developer to choose whether to handle
16775      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16776      * call.
16777      *
16778      * <p>Use this callback to track changes to the displays if some functionality relies on an
16779      * association with some display properties.
16780      *
16781      * @param displayId The id of the display to which the view was moved.
16782      * @param config Configuration of the resources on new display after move.
16783      *
16784      * @see #onConfigurationChanged(Configuration)
16785      * @hide
16786      */
16787     public void onMovedToDisplay(int displayId, Configuration config) {
16788     }
16789
16790     /**
16791      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16792      */
16793     private boolean hasRtlSupport() {
16794         return mContext.getApplicationInfo().hasRtlSupport();
16795     }
16796
16797     /**
16798      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16799      * RTL not supported)
16800      */
16801     private boolean isRtlCompatibilityMode() {
16802         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16803         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16804     }
16805
16806     /**
16807      * @return true if RTL properties need resolution.
16808      *
16809      */
16810     private boolean needRtlPropertiesResolution() {
16811         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16812     }
16813
16814     /**
16815      * Called when any RTL property (layout direction or text direction or text alignment) has
16816      * been changed.
16817      *
16818      * Subclasses need to override this method to take care of cached information that depends on the
16819      * resolved layout direction, or to inform child views that inherit their layout direction.
16820      *
16821      * The default implementation does nothing.
16822      *
16823      * @param layoutDirection the direction of the layout
16824      *
16825      * @see #LAYOUT_DIRECTION_LTR
16826      * @see #LAYOUT_DIRECTION_RTL
16827      */
16828     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16829     }
16830
16831     /**
16832      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16833      * that the parent directionality can and will be resolved before its children.
16834      *
16835      * @return true if resolution has been done, false otherwise.
16836      *
16837      * @hide
16838      */
16839     public boolean resolveLayoutDirection() {
16840         // Clear any previous layout direction resolution
16841         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16842
16843         if (hasRtlSupport()) {
16844             // Set resolved depending on layout direction
16845             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16846                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16847                 case LAYOUT_DIRECTION_INHERIT:
16848                     // We cannot resolve yet. LTR is by default and let the resolution happen again
16849                     // later to get the correct resolved value
16850                     if (!canResolveLayoutDirection()) return false;
16851
16852                     // Parent has not yet resolved, LTR is still the default
16853                     try {
16854                         if (!mParent.isLayoutDirectionResolved()) return false;
16855
16856                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16857                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16858                         }
16859                     } catch (AbstractMethodError e) {
16860                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16861                                 " does not fully implement ViewParent", e);
16862                     }
16863                     break;
16864                 case LAYOUT_DIRECTION_RTL:
16865                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16866                     break;
16867                 case LAYOUT_DIRECTION_LOCALE:
16868                     if((LAYOUT_DIRECTION_RTL ==
16869                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16870                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16871                     }
16872                     break;
16873                 default:
16874                     // Nothing to do, LTR by default
16875             }
16876         }
16877
16878         // Set to resolved
16879         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16880         return true;
16881     }
16882
16883     /**
16884      * Check if layout direction resolution can be done.
16885      *
16886      * @return true if layout direction resolution can be done otherwise return false.
16887      */
16888     public boolean canResolveLayoutDirection() {
16889         switch (getRawLayoutDirection()) {
16890             case LAYOUT_DIRECTION_INHERIT:
16891                 if (mParent != null) {
16892                     try {
16893                         return mParent.canResolveLayoutDirection();
16894                     } catch (AbstractMethodError e) {
16895                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16896                                 " does not fully implement ViewParent", e);
16897                     }
16898                 }
16899                 return false;
16900
16901             default:
16902                 return true;
16903         }
16904     }
16905
16906     /**
16907      * Reset the resolved layout direction. Layout direction will be resolved during a call to
16908      * {@link #onMeasure(int, int)}.
16909      *
16910      * @hide
16911      */
16912     public void resetResolvedLayoutDirection() {
16913         // Reset the current resolved bits
16914         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16915     }
16916
16917     /**
16918      * @return true if the layout direction is inherited.
16919      *
16920      * @hide
16921      */
16922     public boolean isLayoutDirectionInherited() {
16923         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16924     }
16925
16926     /**
16927      * @return true if layout direction has been resolved.
16928      */
16929     public boolean isLayoutDirectionResolved() {
16930         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16931     }
16932
16933     /**
16934      * Return if padding has been resolved
16935      *
16936      * @hide
16937      */
16938     boolean isPaddingResolved() {
16939         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16940     }
16941
16942     /**
16943      * Resolves padding depending on layout direction, if applicable, and
16944      * recomputes internal padding values to adjust for scroll bars.
16945      *
16946      * @hide
16947      */
16948     public void resolvePadding() {
16949         final int resolvedLayoutDirection = getLayoutDirection();
16950
16951         if (!isRtlCompatibilityMode()) {
16952             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16953             // If start / end padding are defined, they will be resolved (hence overriding) to
16954             // left / right or right / left depending on the resolved layout direction.
16955             // If start / end padding are not defined, use the left / right ones.
16956             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16957                 Rect padding = sThreadLocal.get();
16958                 if (padding == null) {
16959                     padding = new Rect();
16960                     sThreadLocal.set(padding);
16961                 }
16962                 mBackground.getPadding(padding);
16963                 if (!mLeftPaddingDefined) {
16964                     mUserPaddingLeftInitial = padding.left;
16965                 }
16966                 if (!mRightPaddingDefined) {
16967                     mUserPaddingRightInitial = padding.right;
16968                 }
16969             }
16970             switch (resolvedLayoutDirection) {
16971                 case LAYOUT_DIRECTION_RTL:
16972                     if (mUserPaddingStart != UNDEFINED_PADDING) {
16973                         mUserPaddingRight = mUserPaddingStart;
16974                     } else {
16975                         mUserPaddingRight = mUserPaddingRightInitial;
16976                     }
16977                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
16978                         mUserPaddingLeft = mUserPaddingEnd;
16979                     } else {
16980                         mUserPaddingLeft = mUserPaddingLeftInitial;
16981                     }
16982                     break;
16983                 case LAYOUT_DIRECTION_LTR:
16984                 default:
16985                     if (mUserPaddingStart != UNDEFINED_PADDING) {
16986                         mUserPaddingLeft = mUserPaddingStart;
16987                     } else {
16988                         mUserPaddingLeft = mUserPaddingLeftInitial;
16989                     }
16990                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
16991                         mUserPaddingRight = mUserPaddingEnd;
16992                     } else {
16993                         mUserPaddingRight = mUserPaddingRightInitial;
16994                     }
16995             }
16996
16997             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16998         }
16999
17000         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
17001         onRtlPropertiesChanged(resolvedLayoutDirection);
17002
17003         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
17004     }
17005
17006     /**
17007      * Reset the resolved layout direction.
17008      *
17009      * @hide
17010      */
17011     public void resetResolvedPadding() {
17012         resetResolvedPaddingInternal();
17013     }
17014
17015     /**
17016      * Used when we only want to reset *this* view's padding and not trigger overrides
17017      * in ViewGroup that reset children too.
17018      */
17019     void resetResolvedPaddingInternal() {
17020         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
17021     }
17022
17023     /**
17024      * This is called when the view is detached from a window.  At this point it
17025      * no longer has a surface for drawing.
17026      *
17027      * @see #onAttachedToWindow()
17028      */
17029     @CallSuper
17030     protected void onDetachedFromWindow() {
17031     }
17032
17033     /**
17034      * This is a framework-internal mirror of onDetachedFromWindow() that's called
17035      * after onDetachedFromWindow().
17036      *
17037      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
17038      * The super method should be called at the end of the overridden method to ensure
17039      * subclasses are destroyed first
17040      *
17041      * @hide
17042      */
17043     @CallSuper
17044     protected void onDetachedFromWindowInternal() {
17045         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
17046         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
17047         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
17048
17049         removeUnsetPressCallback();
17050         removeLongPressCallback();
17051         removePerformClickCallback();
17052         removeSendViewScrolledAccessibilityEventCallback();
17053         stopNestedScroll();
17054
17055         // Anything that started animating right before detach should already
17056         // be in its final state when re-attached.
17057         jumpDrawablesToCurrentState();
17058
17059         destroyDrawingCache();
17060
17061         cleanupDraw();
17062         mCurrentAnimation = null;
17063
17064         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
17065             hideTooltip();
17066         }
17067     }
17068
17069     private void cleanupDraw() {
17070         resetDisplayList();
17071         if (mAttachInfo != null) {
17072             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
17073         }
17074     }
17075
17076     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
17077     }
17078
17079     /**
17080      * @return The number of times this view has been attached to a window
17081      */
17082     protected int getWindowAttachCount() {
17083         return mWindowAttachCount;
17084     }
17085
17086     /**
17087      * Retrieve a unique token identifying the window this view is attached to.
17088      * @return Return the window's token for use in
17089      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
17090      */
17091     public IBinder getWindowToken() {
17092         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
17093     }
17094
17095     /**
17096      * Retrieve the {@link WindowId} for the window this view is
17097      * currently attached to.
17098      */
17099     public WindowId getWindowId() {
17100         if (mAttachInfo == null) {
17101             return null;
17102         }
17103         if (mAttachInfo.mWindowId == null) {
17104             try {
17105                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
17106                         mAttachInfo.mWindowToken);
17107                 mAttachInfo.mWindowId = new WindowId(
17108                         mAttachInfo.mIWindowId);
17109             } catch (RemoteException e) {
17110             }
17111         }
17112         return mAttachInfo.mWindowId;
17113     }
17114
17115     /**
17116      * Retrieve a unique token identifying the top-level "real" window of
17117      * the window that this view is attached to.  That is, this is like
17118      * {@link #getWindowToken}, except if the window this view in is a panel
17119      * window (attached to another containing window), then the token of
17120      * the containing window is returned instead.
17121      *
17122      * @return Returns the associated window token, either
17123      * {@link #getWindowToken()} or the containing window's token.
17124      */
17125     public IBinder getApplicationWindowToken() {
17126         AttachInfo ai = mAttachInfo;
17127         if (ai != null) {
17128             IBinder appWindowToken = ai.mPanelParentWindowToken;
17129             if (appWindowToken == null) {
17130                 appWindowToken = ai.mWindowToken;
17131             }
17132             return appWindowToken;
17133         }
17134         return null;
17135     }
17136
17137     /**
17138      * Gets the logical display to which the view's window has been attached.
17139      *
17140      * @return The logical display, or null if the view is not currently attached to a window.
17141      */
17142     public Display getDisplay() {
17143         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
17144     }
17145
17146     /**
17147      * Retrieve private session object this view hierarchy is using to
17148      * communicate with the window manager.
17149      * @return the session object to communicate with the window manager
17150      */
17151     /*package*/ IWindowSession getWindowSession() {
17152         return mAttachInfo != null ? mAttachInfo.mSession : null;
17153     }
17154
17155     /**
17156      * Return the visibility value of the least visible component passed.
17157      */
17158     int combineVisibility(int vis1, int vis2) {
17159         // This works because VISIBLE < INVISIBLE < GONE.
17160         return Math.max(vis1, vis2);
17161     }
17162
17163     /**
17164      * @param info the {@link android.view.View.AttachInfo} to associated with
17165      *        this view
17166      */
17167     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
17168         mAttachInfo = info;
17169         if (mOverlay != null) {
17170             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
17171         }
17172         mWindowAttachCount++;
17173         // We will need to evaluate the drawable state at least once.
17174         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17175         if (mFloatingTreeObserver != null) {
17176             info.mTreeObserver.merge(mFloatingTreeObserver);
17177             mFloatingTreeObserver = null;
17178         }
17179
17180         registerPendingFrameMetricsObservers();
17181
17182         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
17183             mAttachInfo.mScrollContainers.add(this);
17184             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
17185         }
17186         // Transfer all pending runnables.
17187         if (mRunQueue != null) {
17188             mRunQueue.executeActions(info.mHandler);
17189             mRunQueue = null;
17190         }
17191         performCollectViewAttributes(mAttachInfo, visibility);
17192         onAttachedToWindow();
17193
17194         ListenerInfo li = mListenerInfo;
17195         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17196                 li != null ? li.mOnAttachStateChangeListeners : null;
17197         if (listeners != null && listeners.size() > 0) {
17198             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17199             // perform the dispatching. The iterator is a safe guard against listeners that
17200             // could mutate the list by calling the various add/remove methods. This prevents
17201             // the array from being modified while we iterate it.
17202             for (OnAttachStateChangeListener listener : listeners) {
17203                 listener.onViewAttachedToWindow(this);
17204             }
17205         }
17206
17207         int vis = info.mWindowVisibility;
17208         if (vis != GONE) {
17209             onWindowVisibilityChanged(vis);
17210             if (isShown()) {
17211                 // Calling onVisibilityAggregated directly here since the subtree will also
17212                 // receive dispatchAttachedToWindow and this same call
17213                 onVisibilityAggregated(vis == VISIBLE);
17214             }
17215         }
17216
17217         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17218         // As all views in the subtree will already receive dispatchAttachedToWindow
17219         // traversing the subtree again here is not desired.
17220         onVisibilityChanged(this, visibility);
17221
17222         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17223             // If nobody has evaluated the drawable state yet, then do it now.
17224             refreshDrawableState();
17225         }
17226         needGlobalAttributesUpdate(false);
17227
17228         notifyEnterOrExitForAutoFillIfNeeded(true);
17229     }
17230
17231     void dispatchDetachedFromWindow() {
17232         AttachInfo info = mAttachInfo;
17233         if (info != null) {
17234             int vis = info.mWindowVisibility;
17235             if (vis != GONE) {
17236                 onWindowVisibilityChanged(GONE);
17237                 if (isShown()) {
17238                     // Invoking onVisibilityAggregated directly here since the subtree
17239                     // will also receive detached from window
17240                     onVisibilityAggregated(false);
17241                 }
17242             }
17243         }
17244
17245         onDetachedFromWindow();
17246         onDetachedFromWindowInternal();
17247
17248         InputMethodManager imm = InputMethodManager.peekInstance();
17249         if (imm != null) {
17250             imm.onViewDetachedFromWindow(this);
17251         }
17252
17253         ListenerInfo li = mListenerInfo;
17254         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17255                 li != null ? li.mOnAttachStateChangeListeners : null;
17256         if (listeners != null && listeners.size() > 0) {
17257             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17258             // perform the dispatching. The iterator is a safe guard against listeners that
17259             // could mutate the list by calling the various add/remove methods. This prevents
17260             // the array from being modified while we iterate it.
17261             for (OnAttachStateChangeListener listener : listeners) {
17262                 listener.onViewDetachedFromWindow(this);
17263             }
17264         }
17265
17266         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17267             mAttachInfo.mScrollContainers.remove(this);
17268             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17269         }
17270
17271         mAttachInfo = null;
17272         if (mOverlay != null) {
17273             mOverlay.getOverlayView().dispatchDetachedFromWindow();
17274         }
17275
17276         notifyEnterOrExitForAutoFillIfNeeded(false);
17277     }
17278
17279     /**
17280      * Cancel any deferred high-level input events that were previously posted to the event queue.
17281      *
17282      * <p>Many views post high-level events such as click handlers to the event queue
17283      * to run deferred in order to preserve a desired user experience - clearing visible
17284      * pressed states before executing, etc. This method will abort any events of this nature
17285      * that are currently in flight.</p>
17286      *
17287      * <p>Custom views that generate their own high-level deferred input events should override
17288      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17289      *
17290      * <p>This will also cancel pending input events for any child views.</p>
17291      *
17292      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17293      * This will not impact newer events posted after this call that may occur as a result of
17294      * lower-level input events still waiting in the queue. If you are trying to prevent
17295      * double-submitted  events for the duration of some sort of asynchronous transaction
17296      * you should also take other steps to protect against unexpected double inputs e.g. calling
17297      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17298      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17299      */
17300     public final void cancelPendingInputEvents() {
17301         dispatchCancelPendingInputEvents();
17302     }
17303
17304     /**
17305      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17306      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17307      */
17308     void dispatchCancelPendingInputEvents() {
17309         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17310         onCancelPendingInputEvents();
17311         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17312             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17313                     " did not call through to super.onCancelPendingInputEvents()");
17314         }
17315     }
17316
17317     /**
17318      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17319      * a parent view.
17320      *
17321      * <p>This method is responsible for removing any pending high-level input events that were
17322      * posted to the event queue to run later. Custom view classes that post their own deferred
17323      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17324      * {@link android.os.Handler} should override this method, call
17325      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17326      * </p>
17327      */
17328     public void onCancelPendingInputEvents() {
17329         removePerformClickCallback();
17330         cancelLongPress();
17331         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17332     }
17333
17334     /**
17335      * Store this view hierarchy's frozen state into the given container.
17336      *
17337      * @param container The SparseArray in which to save the view's state.
17338      *
17339      * @see #restoreHierarchyState(android.util.SparseArray)
17340      * @see #dispatchSaveInstanceState(android.util.SparseArray)
17341      * @see #onSaveInstanceState()
17342      */
17343     public void saveHierarchyState(SparseArray<Parcelable> container) {
17344         dispatchSaveInstanceState(container);
17345     }
17346
17347     /**
17348      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17349      * this view and its children. May be overridden to modify how freezing happens to a
17350      * view's children; for example, some views may want to not store state for their children.
17351      *
17352      * @param container The SparseArray in which to save the view's state.
17353      *
17354      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17355      * @see #saveHierarchyState(android.util.SparseArray)
17356      * @see #onSaveInstanceState()
17357      */
17358     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17359         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17360             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17361             Parcelable state = onSaveInstanceState();
17362             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17363                 throw new IllegalStateException(
17364                         "Derived class did not call super.onSaveInstanceState()");
17365             }
17366             if (state != null) {
17367                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17368                 // + ": " + state);
17369                 container.put(mID, state);
17370             }
17371         }
17372     }
17373
17374     /**
17375      * Hook allowing a view to generate a representation of its internal state
17376      * that can later be used to create a new instance with that same state.
17377      * This state should only contain information that is not persistent or can
17378      * not be reconstructed later. For example, you will never store your
17379      * current position on screen because that will be computed again when a
17380      * new instance of the view is placed in its view hierarchy.
17381      * <p>
17382      * Some examples of things you may store here: the current cursor position
17383      * in a text view (but usually not the text itself since that is stored in a
17384      * content provider or other persistent storage), the currently selected
17385      * item in a list view.
17386      *
17387      * @return Returns a Parcelable object containing the view's current dynamic
17388      *         state, or null if there is nothing interesting to save.
17389      * @see #onRestoreInstanceState(android.os.Parcelable)
17390      * @see #saveHierarchyState(android.util.SparseArray)
17391      * @see #dispatchSaveInstanceState(android.util.SparseArray)
17392      * @see #setSaveEnabled(boolean)
17393      */
17394     @CallSuper
17395     @Nullable protected Parcelable onSaveInstanceState() {
17396         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17397         if (mStartActivityRequestWho != null || isAutofilled()
17398                 || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17399             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17400
17401             if (mStartActivityRequestWho != null) {
17402                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17403             }
17404
17405             if (isAutofilled()) {
17406                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17407             }
17408
17409             if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17410                 state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
17411             }
17412
17413             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17414             state.mIsAutofilled = isAutofilled();
17415             state.mAccessibilityViewId = mAccessibilityViewId;
17416             return state;
17417         }
17418         return BaseSavedState.EMPTY_STATE;
17419     }
17420
17421     /**
17422      * Restore this view hierarchy's frozen state from the given container.
17423      *
17424      * @param container The SparseArray which holds previously frozen states.
17425      *
17426      * @see #saveHierarchyState(android.util.SparseArray)
17427      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17428      * @see #onRestoreInstanceState(android.os.Parcelable)
17429      */
17430     public void restoreHierarchyState(SparseArray<Parcelable> container) {
17431         dispatchRestoreInstanceState(container);
17432     }
17433
17434     /**
17435      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17436      * state for this view and its children. May be overridden to modify how restoring
17437      * happens to a view's children; for example, some views may want to not store state
17438      * for their children.
17439      *
17440      * @param container The SparseArray which holds previously saved state.
17441      *
17442      * @see #dispatchSaveInstanceState(android.util.SparseArray)
17443      * @see #restoreHierarchyState(android.util.SparseArray)
17444      * @see #onRestoreInstanceState(android.os.Parcelable)
17445      */
17446     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17447         if (mID != NO_ID) {
17448             Parcelable state = container.get(mID);
17449             if (state != null) {
17450                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17451                 // + ": " + state);
17452                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17453                 onRestoreInstanceState(state);
17454                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17455                     throw new IllegalStateException(
17456                             "Derived class did not call super.onRestoreInstanceState()");
17457                 }
17458             }
17459         }
17460     }
17461
17462     /**
17463      * Hook allowing a view to re-apply a representation of its internal state that had previously
17464      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17465      * null state.
17466      *
17467      * @param state The frozen state that had previously been returned by
17468      *        {@link #onSaveInstanceState}.
17469      *
17470      * @see #onSaveInstanceState()
17471      * @see #restoreHierarchyState(android.util.SparseArray)
17472      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17473      */
17474     @CallSuper
17475     protected void onRestoreInstanceState(Parcelable state) {
17476         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17477         if (state != null && !(state instanceof AbsSavedState)) {
17478             throw new IllegalArgumentException("Wrong state class, expecting View State but "
17479                     + "received " + state.getClass().toString() + " instead. This usually happens "
17480                     + "when two views of different type have the same id in the same hierarchy. "
17481                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17482                     + "other views do not use the same id.");
17483         }
17484         if (state != null && state instanceof BaseSavedState) {
17485             BaseSavedState baseState = (BaseSavedState) state;
17486
17487             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17488                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17489             }
17490             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17491                 setAutofilled(baseState.mIsAutofilled);
17492             }
17493             if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
17494                 mAccessibilityViewId = baseState.mAccessibilityViewId;
17495             }
17496         }
17497     }
17498
17499     /**
17500      * <p>Return the time at which the drawing of the view hierarchy started.</p>
17501      *
17502      * @return the drawing start time in milliseconds
17503      */
17504     public long getDrawingTime() {
17505         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17506     }
17507
17508     /**
17509      * <p>Enables or disables the duplication of the parent's state into this view. When
17510      * duplication is enabled, this view gets its drawable state from its parent rather
17511      * than from its own internal properties.</p>
17512      *
17513      * <p>Note: in the current implementation, setting this property to true after the
17514      * view was added to a ViewGroup might have no effect at all. This property should
17515      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17516      *
17517      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17518      * property is enabled, an exception will be thrown.</p>
17519      *
17520      * <p>Note: if the child view uses and updates additional states which are unknown to the
17521      * parent, these states should not be affected by this method.</p>
17522      *
17523      * @param enabled True to enable duplication of the parent's drawable state, false
17524      *                to disable it.
17525      *
17526      * @see #getDrawableState()
17527      * @see #isDuplicateParentStateEnabled()
17528      */
17529     public void setDuplicateParentStateEnabled(boolean enabled) {
17530         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17531     }
17532
17533     /**
17534      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17535      *
17536      * @return True if this view's drawable state is duplicated from the parent,
17537      *         false otherwise
17538      *
17539      * @see #getDrawableState()
17540      * @see #setDuplicateParentStateEnabled(boolean)
17541      */
17542     public boolean isDuplicateParentStateEnabled() {
17543         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17544     }
17545
17546     /**
17547      * <p>Specifies the type of layer backing this view. The layer can be
17548      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17549      * {@link #LAYER_TYPE_HARDWARE}.</p>
17550      *
17551      * <p>A layer is associated with an optional {@link android.graphics.Paint}
17552      * instance that controls how the layer is composed on screen. The following
17553      * properties of the paint are taken into account when composing the layer:</p>
17554      * <ul>
17555      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17556      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17557      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17558      * </ul>
17559      *
17560      * <p>If this view has an alpha value set to < 1.0 by calling
17561      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17562      * by this view's alpha value.</p>
17563      *
17564      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17565      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17566      * for more information on when and how to use layers.</p>
17567      *
17568      * @param layerType The type of layer to use with this view, must be one of
17569      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17570      *        {@link #LAYER_TYPE_HARDWARE}
17571      * @param paint The paint used to compose the layer. This argument is optional
17572      *        and can be null. It is ignored when the layer type is
17573      *        {@link #LAYER_TYPE_NONE}
17574      *
17575      * @see #getLayerType()
17576      * @see #LAYER_TYPE_NONE
17577      * @see #LAYER_TYPE_SOFTWARE
17578      * @see #LAYER_TYPE_HARDWARE
17579      * @see #setAlpha(float)
17580      *
17581      * @attr ref android.R.styleable#View_layerType
17582      */
17583     public void setLayerType(int layerType, @Nullable Paint paint) {
17584         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17585             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17586                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17587         }
17588
17589         boolean typeChanged = mRenderNode.setLayerType(layerType);
17590
17591         if (!typeChanged) {
17592             setLayerPaint(paint);
17593             return;
17594         }
17595
17596         if (layerType != LAYER_TYPE_SOFTWARE) {
17597             // Destroy any previous software drawing cache if present
17598             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17599             // drawing cache created in View#draw when drawing to a SW canvas.
17600             destroyDrawingCache();
17601         }
17602
17603         mLayerType = layerType;
17604         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17605         mRenderNode.setLayerPaint(mLayerPaint);
17606
17607         // draw() behaves differently if we are on a layer, so we need to
17608         // invalidate() here
17609         invalidateParentCaches();
17610         invalidate(true);
17611     }
17612
17613     /**
17614      * Updates the {@link Paint} object used with the current layer (used only if the current
17615      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17616      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17617      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17618      * ensure that the view gets redrawn immediately.
17619      *
17620      * <p>A layer is associated with an optional {@link android.graphics.Paint}
17621      * instance that controls how the layer is composed on screen. The following
17622      * properties of the paint are taken into account when composing the layer:</p>
17623      * <ul>
17624      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17625      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17626      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17627      * </ul>
17628      *
17629      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17630      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17631      *
17632      * @param paint The paint used to compose the layer. This argument is optional
17633      *        and can be null. It is ignored when the layer type is
17634      *        {@link #LAYER_TYPE_NONE}
17635      *
17636      * @see #setLayerType(int, android.graphics.Paint)
17637      */
17638     public void setLayerPaint(@Nullable Paint paint) {
17639         int layerType = getLayerType();
17640         if (layerType != LAYER_TYPE_NONE) {
17641             mLayerPaint = paint;
17642             if (layerType == LAYER_TYPE_HARDWARE) {
17643                 if (mRenderNode.setLayerPaint(paint)) {
17644                     invalidateViewProperty(false, false);
17645                 }
17646             } else {
17647                 invalidate();
17648             }
17649         }
17650     }
17651
17652     /**
17653      * Indicates what type of layer is currently associated with this view. By default
17654      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17655      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17656      * for more information on the different types of layers.
17657      *
17658      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17659      *         {@link #LAYER_TYPE_HARDWARE}
17660      *
17661      * @see #setLayerType(int, android.graphics.Paint)
17662      * @see #buildLayer()
17663      * @see #LAYER_TYPE_NONE
17664      * @see #LAYER_TYPE_SOFTWARE
17665      * @see #LAYER_TYPE_HARDWARE
17666      */
17667     public int getLayerType() {
17668         return mLayerType;
17669     }
17670
17671     /**
17672      * Forces this view's layer to be created and this view to be rendered
17673      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17674      * invoking this method will have no effect.
17675      *
17676      * This method can for instance be used to render a view into its layer before
17677      * starting an animation. If this view is complex, rendering into the layer
17678      * before starting the animation will avoid skipping frames.
17679      *
17680      * @throws IllegalStateException If this view is not attached to a window
17681      *
17682      * @see #setLayerType(int, android.graphics.Paint)
17683      */
17684     public void buildLayer() {
17685         if (mLayerType == LAYER_TYPE_NONE) return;
17686
17687         final AttachInfo attachInfo = mAttachInfo;
17688         if (attachInfo == null) {
17689             throw new IllegalStateException("This view must be attached to a window first");
17690         }
17691
17692         if (getWidth() == 0 || getHeight() == 0) {
17693             return;
17694         }
17695
17696         switch (mLayerType) {
17697             case LAYER_TYPE_HARDWARE:
17698                 updateDisplayListIfDirty();
17699                 if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17700                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17701                 }
17702                 break;
17703             case LAYER_TYPE_SOFTWARE:
17704                 buildDrawingCache(true);
17705                 break;
17706         }
17707     }
17708
17709     /**
17710      * Destroys all hardware rendering resources. This method is invoked
17711      * when the system needs to reclaim resources. Upon execution of this
17712      * method, you should free any OpenGL resources created by the view.
17713      *
17714      * Note: you <strong>must</strong> call
17715      * <code>super.destroyHardwareResources()</code> when overriding
17716      * this method.
17717      *
17718      * @hide
17719      */
17720     @CallSuper
17721     protected void destroyHardwareResources() {
17722         if (mOverlay != null) {
17723             mOverlay.getOverlayView().destroyHardwareResources();
17724         }
17725         if (mGhostView != null) {
17726             mGhostView.destroyHardwareResources();
17727         }
17728     }
17729
17730     /**
17731      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17732      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17733      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17734      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17735      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17736      * null.</p>
17737      *
17738      * <p>Enabling the drawing cache is similar to
17739      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17740      * acceleration is turned off. When hardware acceleration is turned on, enabling the
17741      * drawing cache has no effect on rendering because the system uses a different mechanism
17742      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17743      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17744      * for information on how to enable software and hardware layers.</p>
17745      *
17746      * <p>This API can be used to manually generate
17747      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17748      * {@link #getDrawingCache()}.</p>
17749      *
17750      * @param enabled true to enable the drawing cache, false otherwise
17751      *
17752      * @see #isDrawingCacheEnabled()
17753      * @see #getDrawingCache()
17754      * @see #buildDrawingCache()
17755      * @see #setLayerType(int, android.graphics.Paint)
17756      */
17757     public void setDrawingCacheEnabled(boolean enabled) {
17758         mCachingFailed = false;
17759         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17760     }
17761
17762     /**
17763      * <p>Indicates whether the drawing cache is enabled for this view.</p>
17764      *
17765      * @return true if the drawing cache is enabled
17766      *
17767      * @see #setDrawingCacheEnabled(boolean)
17768      * @see #getDrawingCache()
17769      */
17770     @ViewDebug.ExportedProperty(category = "drawing")
17771     public boolean isDrawingCacheEnabled() {
17772         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17773     }
17774
17775     /**
17776      * Debugging utility which recursively outputs the dirty state of a view and its
17777      * descendants.
17778      *
17779      * @hide
17780      */
17781     @SuppressWarnings({"UnusedDeclaration"})
17782     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17783         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17784                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17785                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17786                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17787         if (clear) {
17788             mPrivateFlags &= clearMask;
17789         }
17790         if (this instanceof ViewGroup) {
17791             ViewGroup parent = (ViewGroup) this;
17792             final int count = parent.getChildCount();
17793             for (int i = 0; i < count; i++) {
17794                 final View child = parent.getChildAt(i);
17795                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
17796             }
17797         }
17798     }
17799
17800     /**
17801      * This method is used by ViewGroup to cause its children to restore or recreate their
17802      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17803      * to recreate its own display list, which would happen if it went through the normal
17804      * draw/dispatchDraw mechanisms.
17805      *
17806      * @hide
17807      */
17808     protected void dispatchGetDisplayList() {}
17809
17810     /**
17811      * A view that is not attached or hardware accelerated cannot create a display list.
17812      * This method checks these conditions and returns the appropriate result.
17813      *
17814      * @return true if view has the ability to create a display list, false otherwise.
17815      *
17816      * @hide
17817      */
17818     public boolean canHaveDisplayList() {
17819         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17820     }
17821
17822     /**
17823      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17824      * @hide
17825      */
17826     @NonNull
17827     public RenderNode updateDisplayListIfDirty() {
17828         final RenderNode renderNode = mRenderNode;
17829         if (!canHaveDisplayList()) {
17830             // can't populate RenderNode, don't try
17831             return renderNode;
17832         }
17833
17834         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17835                 || !renderNode.isValid()
17836                 || (mRecreateDisplayList)) {
17837             // Don't need to recreate the display list, just need to tell our
17838             // children to restore/recreate theirs
17839             if (renderNode.isValid()
17840                     && !mRecreateDisplayList) {
17841                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17842                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17843                 dispatchGetDisplayList();
17844
17845                 return renderNode; // no work needed
17846             }
17847
17848             // If we got here, we're recreating it. Mark it as such to ensure that
17849             // we copy in child display lists into ours in drawChild()
17850             mRecreateDisplayList = true;
17851
17852             int width = mRight - mLeft;
17853             int height = mBottom - mTop;
17854             int layerType = getLayerType();
17855
17856             final DisplayListCanvas canvas = renderNode.start(width, height);
17857             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17858
17859             try {
17860                 if (layerType == LAYER_TYPE_SOFTWARE) {
17861                     buildDrawingCache(true);
17862                     Bitmap cache = getDrawingCache(true);
17863                     if (cache != null) {
17864                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17865                     }
17866                 } else {
17867                     computeScroll();
17868
17869                     canvas.translate(-mScrollX, -mScrollY);
17870                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17871                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17872
17873                     // Fast path for layouts with no backgrounds
17874                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17875                         dispatchDraw(canvas);
17876                         drawAutofilledHighlight(canvas);
17877                         if (mOverlay != null && !mOverlay.isEmpty()) {
17878                             mOverlay.getOverlayView().draw(canvas);
17879                         }
17880                         if (debugDraw()) {
17881                             debugDrawFocus(canvas);
17882                         }
17883                     } else {
17884                         draw(canvas);
17885                     }
17886                 }
17887             } finally {
17888                 renderNode.end(canvas);
17889                 setDisplayListProperties(renderNode);
17890             }
17891         } else {
17892             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17893             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17894         }
17895         return renderNode;
17896     }
17897
17898     private void resetDisplayList() {
17899         mRenderNode.discardDisplayList();
17900         if (mBackgroundRenderNode != null) {
17901             mBackgroundRenderNode.discardDisplayList();
17902         }
17903     }
17904
17905     /**
17906      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17907      *
17908      * @return A non-scaled bitmap representing this view or null if cache is disabled.
17909      *
17910      * @see #getDrawingCache(boolean)
17911      */
17912     public Bitmap getDrawingCache() {
17913         return getDrawingCache(false);
17914     }
17915
17916     /**
17917      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17918      * is null when caching is disabled. If caching is enabled and the cache is not ready,
17919      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17920      * draw from the cache when the cache is enabled. To benefit from the cache, you must
17921      * request the drawing cache by calling this method and draw it on screen if the
17922      * returned bitmap is not null.</p>
17923      *
17924      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17925      * this method will create a bitmap of the same size as this view. Because this bitmap
17926      * will be drawn scaled by the parent ViewGroup, the result on screen might show
17927      * scaling artifacts. To avoid such artifacts, you should call this method by setting
17928      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17929      * size than the view. This implies that your application must be able to handle this
17930      * size.</p>
17931      *
17932      * @param autoScale Indicates whether the generated bitmap should be scaled based on
17933      *        the current density of the screen when the application is in compatibility
17934      *        mode.
17935      *
17936      * @return A bitmap representing this view or null if cache is disabled.
17937      *
17938      * @see #setDrawingCacheEnabled(boolean)
17939      * @see #isDrawingCacheEnabled()
17940      * @see #buildDrawingCache(boolean)
17941      * @see #destroyDrawingCache()
17942      */
17943     public Bitmap getDrawingCache(boolean autoScale) {
17944         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17945             return null;
17946         }
17947         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17948             buildDrawingCache(autoScale);
17949         }
17950         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17951     }
17952
17953     /**
17954      * <p>Frees the resources used by the drawing cache. If you call
17955      * {@link #buildDrawingCache()} manually without calling
17956      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17957      * should cleanup the cache with this method afterwards.</p>
17958      *
17959      * @see #setDrawingCacheEnabled(boolean)
17960      * @see #buildDrawingCache()
17961      * @see #getDrawingCache()
17962      */
17963     public void destroyDrawingCache() {
17964         if (mDrawingCache != null) {
17965             mDrawingCache.recycle();
17966             mDrawingCache = null;
17967         }
17968         if (mUnscaledDrawingCache != null) {
17969             mUnscaledDrawingCache.recycle();
17970             mUnscaledDrawingCache = null;
17971         }
17972     }
17973
17974     /**
17975      * Setting a solid background color for the drawing cache's bitmaps will improve
17976      * performance and memory usage. Note, though that this should only be used if this
17977      * view will always be drawn on top of a solid color.
17978      *
17979      * @param color The background color to use for the drawing cache's bitmap
17980      *
17981      * @see #setDrawingCacheEnabled(boolean)
17982      * @see #buildDrawingCache()
17983      * @see #getDrawingCache()
17984      */
17985     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17986         if (color != mDrawingCacheBackgroundColor) {
17987             mDrawingCacheBackgroundColor = color;
17988             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17989         }
17990     }
17991
17992     /**
17993      * @see #setDrawingCacheBackgroundColor(int)
17994      *
17995      * @return The background color to used for the drawing cache's bitmap
17996      */
17997     @ColorInt
17998     public int getDrawingCacheBackgroundColor() {
17999         return mDrawingCacheBackgroundColor;
18000     }
18001
18002     /**
18003      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
18004      *
18005      * @see #buildDrawingCache(boolean)
18006      */
18007     public void buildDrawingCache() {
18008         buildDrawingCache(false);
18009     }
18010
18011     /**
18012      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
18013      *
18014      * <p>If you call {@link #buildDrawingCache()} manually without calling
18015      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18016      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
18017      *
18018      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18019      * this method will create a bitmap of the same size as this view. Because this bitmap
18020      * will be drawn scaled by the parent ViewGroup, the result on screen might show
18021      * scaling artifacts. To avoid such artifacts, you should call this method by setting
18022      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18023      * size than the view. This implies that your application must be able to handle this
18024      * size.</p>
18025      *
18026      * <p>You should avoid calling this method when hardware acceleration is enabled. If
18027      * you do not need the drawing cache bitmap, calling this method will increase memory
18028      * usage and cause the view to be rendered in software once, thus negatively impacting
18029      * performance.</p>
18030      *
18031      * @see #getDrawingCache()
18032      * @see #destroyDrawingCache()
18033      */
18034     public void buildDrawingCache(boolean autoScale) {
18035         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
18036                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
18037             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
18038                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
18039                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
18040             }
18041             try {
18042                 buildDrawingCacheImpl(autoScale);
18043             } finally {
18044                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
18045             }
18046         }
18047     }
18048
18049     /**
18050      * private, internal implementation of buildDrawingCache, used to enable tracing
18051      */
18052     private void buildDrawingCacheImpl(boolean autoScale) {
18053         mCachingFailed = false;
18054
18055         int width = mRight - mLeft;
18056         int height = mBottom - mTop;
18057
18058         final AttachInfo attachInfo = mAttachInfo;
18059         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
18060
18061         if (autoScale && scalingRequired) {
18062             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
18063             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
18064         }
18065
18066         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
18067         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
18068         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
18069
18070         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
18071         final long drawingCacheSize =
18072                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
18073         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
18074             if (width > 0 && height > 0) {
18075                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
18076                         + " too large to fit into a software layer (or drawing cache), needs "
18077                         + projectedBitmapSize + " bytes, only "
18078                         + drawingCacheSize + " available");
18079             }
18080             destroyDrawingCache();
18081             mCachingFailed = true;
18082             return;
18083         }
18084
18085         boolean clear = true;
18086         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
18087
18088         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
18089             Bitmap.Config quality;
18090             if (!opaque) {
18091                 // Never pick ARGB_4444 because it looks awful
18092                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
18093                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
18094                     case DRAWING_CACHE_QUALITY_AUTO:
18095                     case DRAWING_CACHE_QUALITY_LOW:
18096                     case DRAWING_CACHE_QUALITY_HIGH:
18097                     default:
18098                         quality = Bitmap.Config.ARGB_8888;
18099                         break;
18100                 }
18101             } else {
18102                 // Optimization for translucent windows
18103                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
18104                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
18105             }
18106
18107             // Try to cleanup memory
18108             if (bitmap != null) bitmap.recycle();
18109
18110             try {
18111                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18112                         width, height, quality);
18113                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
18114                 if (autoScale) {
18115                     mDrawingCache = bitmap;
18116                 } else {
18117                     mUnscaledDrawingCache = bitmap;
18118                 }
18119                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
18120             } catch (OutOfMemoryError e) {
18121                 // If there is not enough memory to create the bitmap cache, just
18122                 // ignore the issue as bitmap caches are not required to draw the
18123                 // view hierarchy
18124                 if (autoScale) {
18125                     mDrawingCache = null;
18126                 } else {
18127                     mUnscaledDrawingCache = null;
18128                 }
18129                 mCachingFailed = true;
18130                 return;
18131             }
18132
18133             clear = drawingCacheBackgroundColor != 0;
18134         }
18135
18136         Canvas canvas;
18137         if (attachInfo != null) {
18138             canvas = attachInfo.mCanvas;
18139             if (canvas == null) {
18140                 canvas = new Canvas();
18141             }
18142             canvas.setBitmap(bitmap);
18143             // Temporarily clobber the cached Canvas in case one of our children
18144             // is also using a drawing cache. Without this, the children would
18145             // steal the canvas by attaching their own bitmap to it and bad, bad
18146             // thing would happen (invisible views, corrupted drawings, etc.)
18147             attachInfo.mCanvas = null;
18148         } else {
18149             // This case should hopefully never or seldom happen
18150             canvas = new Canvas(bitmap);
18151         }
18152
18153         if (clear) {
18154             bitmap.eraseColor(drawingCacheBackgroundColor);
18155         }
18156
18157         computeScroll();
18158         final int restoreCount = canvas.save();
18159
18160         if (autoScale && scalingRequired) {
18161             final float scale = attachInfo.mApplicationScale;
18162             canvas.scale(scale, scale);
18163         }
18164
18165         canvas.translate(-mScrollX, -mScrollY);
18166
18167         mPrivateFlags |= PFLAG_DRAWN;
18168         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
18169                 mLayerType != LAYER_TYPE_NONE) {
18170             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
18171         }
18172
18173         // Fast path for layouts with no backgrounds
18174         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18175             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18176             dispatchDraw(canvas);
18177             drawAutofilledHighlight(canvas);
18178             if (mOverlay != null && !mOverlay.isEmpty()) {
18179                 mOverlay.getOverlayView().draw(canvas);
18180             }
18181         } else {
18182             draw(canvas);
18183         }
18184
18185         canvas.restoreToCount(restoreCount);
18186         canvas.setBitmap(null);
18187
18188         if (attachInfo != null) {
18189             // Restore the cached Canvas for our siblings
18190             attachInfo.mCanvas = canvas;
18191         }
18192     }
18193
18194     /**
18195      * Create a snapshot of the view into a bitmap.  We should probably make
18196      * some form of this public, but should think about the API.
18197      *
18198      * @hide
18199      */
18200     public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18201         int width = mRight - mLeft;
18202         int height = mBottom - mTop;
18203
18204         final AttachInfo attachInfo = mAttachInfo;
18205         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18206         width = (int) ((width * scale) + 0.5f);
18207         height = (int) ((height * scale) + 0.5f);
18208
18209         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18210                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
18211         if (bitmap == null) {
18212             throw new OutOfMemoryError();
18213         }
18214
18215         Resources resources = getResources();
18216         if (resources != null) {
18217             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18218         }
18219
18220         Canvas canvas;
18221         if (attachInfo != null) {
18222             canvas = attachInfo.mCanvas;
18223             if (canvas == null) {
18224                 canvas = new Canvas();
18225             }
18226             canvas.setBitmap(bitmap);
18227             // Temporarily clobber the cached Canvas in case one of our children
18228             // is also using a drawing cache. Without this, the children would
18229             // steal the canvas by attaching their own bitmap to it and bad, bad
18230             // things would happen (invisible views, corrupted drawings, etc.)
18231             attachInfo.mCanvas = null;
18232         } else {
18233             // This case should hopefully never or seldom happen
18234             canvas = new Canvas(bitmap);
18235         }
18236         boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18237         canvas.setHwBitmapsInSwModeEnabled(true);
18238         if ((backgroundColor & 0xff000000) != 0) {
18239             bitmap.eraseColor(backgroundColor);
18240         }
18241
18242         computeScroll();
18243         final int restoreCount = canvas.save();
18244         canvas.scale(scale, scale);
18245         canvas.translate(-mScrollX, -mScrollY);
18246
18247         // Temporarily remove the dirty mask
18248         int flags = mPrivateFlags;
18249         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18250
18251         // Fast path for layouts with no backgrounds
18252         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18253             dispatchDraw(canvas);
18254             drawAutofilledHighlight(canvas);
18255             if (mOverlay != null && !mOverlay.isEmpty()) {
18256                 mOverlay.getOverlayView().draw(canvas);
18257             }
18258         } else {
18259             draw(canvas);
18260         }
18261
18262         mPrivateFlags = flags;
18263
18264         canvas.restoreToCount(restoreCount);
18265         canvas.setBitmap(null);
18266         canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18267
18268         if (attachInfo != null) {
18269             // Restore the cached Canvas for our siblings
18270             attachInfo.mCanvas = canvas;
18271         }
18272
18273         return bitmap;
18274     }
18275
18276     /**
18277      * Indicates whether this View is currently in edit mode. A View is usually
18278      * in edit mode when displayed within a developer tool. For instance, if
18279      * this View is being drawn by a visual user interface builder, this method
18280      * should return true.
18281      *
18282      * Subclasses should check the return value of this method to provide
18283      * different behaviors if their normal behavior might interfere with the
18284      * host environment. For instance: the class spawns a thread in its
18285      * constructor, the drawing code relies on device-specific features, etc.
18286      *
18287      * This method is usually checked in the drawing code of custom widgets.
18288      *
18289      * @return True if this View is in edit mode, false otherwise.
18290      */
18291     public boolean isInEditMode() {
18292         return false;
18293     }
18294
18295     /**
18296      * If the View draws content inside its padding and enables fading edges,
18297      * it needs to support padding offsets. Padding offsets are added to the
18298      * fading edges to extend the length of the fade so that it covers pixels
18299      * drawn inside the padding.
18300      *
18301      * Subclasses of this class should override this method if they need
18302      * to draw content inside the padding.
18303      *
18304      * @return True if padding offset must be applied, false otherwise.
18305      *
18306      * @see #getLeftPaddingOffset()
18307      * @see #getRightPaddingOffset()
18308      * @see #getTopPaddingOffset()
18309      * @see #getBottomPaddingOffset()
18310      *
18311      * @since CURRENT
18312      */
18313     protected boolean isPaddingOffsetRequired() {
18314         return false;
18315     }
18316
18317     /**
18318      * Amount by which to extend the left fading region. Called only when
18319      * {@link #isPaddingOffsetRequired()} returns true.
18320      *
18321      * @return The left padding offset in pixels.
18322      *
18323      * @see #isPaddingOffsetRequired()
18324      *
18325      * @since CURRENT
18326      */
18327     protected int getLeftPaddingOffset() {
18328         return 0;
18329     }
18330
18331     /**
18332      * Amount by which to extend the right fading region. Called only when
18333      * {@link #isPaddingOffsetRequired()} returns true.
18334      *
18335      * @return The right padding offset in pixels.
18336      *
18337      * @see #isPaddingOffsetRequired()
18338      *
18339      * @since CURRENT
18340      */
18341     protected int getRightPaddingOffset() {
18342         return 0;
18343     }
18344
18345     /**
18346      * Amount by which to extend the top fading region. Called only when
18347      * {@link #isPaddingOffsetRequired()} returns true.
18348      *
18349      * @return The top padding offset in pixels.
18350      *
18351      * @see #isPaddingOffsetRequired()
18352      *
18353      * @since CURRENT
18354      */
18355     protected int getTopPaddingOffset() {
18356         return 0;
18357     }
18358
18359     /**
18360      * Amount by which to extend the bottom fading region. Called only when
18361      * {@link #isPaddingOffsetRequired()} returns true.
18362      *
18363      * @return The bottom padding offset in pixels.
18364      *
18365      * @see #isPaddingOffsetRequired()
18366      *
18367      * @since CURRENT
18368      */
18369     protected int getBottomPaddingOffset() {
18370         return 0;
18371     }
18372
18373     /**
18374      * @hide
18375      * @param offsetRequired
18376      */
18377     protected int getFadeTop(boolean offsetRequired) {
18378         int top = mPaddingTop;
18379         if (offsetRequired) top += getTopPaddingOffset();
18380         return top;
18381     }
18382
18383     /**
18384      * @hide
18385      * @param offsetRequired
18386      */
18387     protected int getFadeHeight(boolean offsetRequired) {
18388         int padding = mPaddingTop;
18389         if (offsetRequired) padding += getTopPaddingOffset();
18390         return mBottom - mTop - mPaddingBottom - padding;
18391     }
18392
18393     /**
18394      * <p>Indicates whether this view is attached to a hardware accelerated
18395      * window or not.</p>
18396      *
18397      * <p>Even if this method returns true, it does not mean that every call
18398      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18399      * accelerated {@link android.graphics.Canvas}. For instance, if this view
18400      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18401      * window is hardware accelerated,
18402      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18403      * return false, and this method will return true.</p>
18404      *
18405      * @return True if the view is attached to a window and the window is
18406      *         hardware accelerated; false in any other case.
18407      */
18408     @ViewDebug.ExportedProperty(category = "drawing")
18409     public boolean isHardwareAccelerated() {
18410         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18411     }
18412
18413     /**
18414      * Sets a rectangular area on this view to which the view will be clipped
18415      * when it is drawn. Setting the value to null will remove the clip bounds
18416      * and the view will draw normally, using its full bounds.
18417      *
18418      * @param clipBounds The rectangular area, in the local coordinates of
18419      * this view, to which future drawing operations will be clipped.
18420      */
18421     public void setClipBounds(Rect clipBounds) {
18422         if (clipBounds == mClipBounds
18423                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18424             return;
18425         }
18426         if (clipBounds != null) {
18427             if (mClipBounds == null) {
18428                 mClipBounds = new Rect(clipBounds);
18429             } else {
18430                 mClipBounds.set(clipBounds);
18431             }
18432         } else {
18433             mClipBounds = null;
18434         }
18435         mRenderNode.setClipBounds(mClipBounds);
18436         invalidateViewProperty(false, false);
18437     }
18438
18439     /**
18440      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18441      *
18442      * @return A copy of the current clip bounds if clip bounds are set,
18443      * otherwise null.
18444      */
18445     public Rect getClipBounds() {
18446         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18447     }
18448
18449
18450     /**
18451      * Populates an output rectangle with the clip bounds of the view,
18452      * returning {@code true} if successful or {@code false} if the view's
18453      * clip bounds are {@code null}.
18454      *
18455      * @param outRect rectangle in which to place the clip bounds of the view
18456      * @return {@code true} if successful or {@code false} if the view's
18457      *         clip bounds are {@code null}
18458      */
18459     public boolean getClipBounds(Rect outRect) {
18460         if (mClipBounds != null) {
18461             outRect.set(mClipBounds);
18462             return true;
18463         }
18464         return false;
18465     }
18466
18467     /**
18468      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18469      * case of an active Animation being run on the view.
18470      */
18471     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18472             Animation a, boolean scalingRequired) {
18473         Transformation invalidationTransform;
18474         final int flags = parent.mGroupFlags;
18475         final boolean initialized = a.isInitialized();
18476         if (!initialized) {
18477             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18478             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18479             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18480             onAnimationStart();
18481         }
18482
18483         final Transformation t = parent.getChildTransformation();
18484         boolean more = a.getTransformation(drawingTime, t, 1f);
18485         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18486             if (parent.mInvalidationTransformation == null) {
18487                 parent.mInvalidationTransformation = new Transformation();
18488             }
18489             invalidationTransform = parent.mInvalidationTransformation;
18490             a.getTransformation(drawingTime, invalidationTransform, 1f);
18491         } else {
18492             invalidationTransform = t;
18493         }
18494
18495         if (more) {
18496             if (!a.willChangeBounds()) {
18497                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18498                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18499                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18500                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18501                     // The child need to draw an animation, potentially offscreen, so
18502                     // make sure we do not cancel invalidate requests
18503                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18504                     parent.invalidate(mLeft, mTop, mRight, mBottom);
18505                 }
18506             } else {
18507                 if (parent.mInvalidateRegion == null) {
18508                     parent.mInvalidateRegion = new RectF();
18509                 }
18510                 final RectF region = parent.mInvalidateRegion;
18511                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18512                         invalidationTransform);
18513
18514                 // The child need to draw an animation, potentially offscreen, so
18515                 // make sure we do not cancel invalidate requests
18516                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18517
18518                 final int left = mLeft + (int) region.left;
18519                 final int top = mTop + (int) region.top;
18520                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
18521                         top + (int) (region.height() + .5f));
18522             }
18523         }
18524         return more;
18525     }
18526
18527     /**
18528      * This method is called by getDisplayList() when a display list is recorded for a View.
18529      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18530      */
18531     void setDisplayListProperties(RenderNode renderNode) {
18532         if (renderNode != null) {
18533             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18534             renderNode.setClipToBounds(mParent instanceof ViewGroup
18535                     && ((ViewGroup) mParent).getClipChildren());
18536
18537             float alpha = 1;
18538             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18539                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18540                 ViewGroup parentVG = (ViewGroup) mParent;
18541                 final Transformation t = parentVG.getChildTransformation();
18542                 if (parentVG.getChildStaticTransformation(this, t)) {
18543                     final int transformType = t.getTransformationType();
18544                     if (transformType != Transformation.TYPE_IDENTITY) {
18545                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18546                             alpha = t.getAlpha();
18547                         }
18548                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18549                             renderNode.setStaticMatrix(t.getMatrix());
18550                         }
18551                     }
18552                 }
18553             }
18554             if (mTransformationInfo != null) {
18555                 alpha *= getFinalAlpha();
18556                 if (alpha < 1) {
18557                     final int multipliedAlpha = (int) (255 * alpha);
18558                     if (onSetAlpha(multipliedAlpha)) {
18559                         alpha = 1;
18560                     }
18561                 }
18562                 renderNode.setAlpha(alpha);
18563             } else if (alpha < 1) {
18564                 renderNode.setAlpha(alpha);
18565             }
18566         }
18567     }
18568
18569     /**
18570      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18571      *
18572      * This is where the View specializes rendering behavior based on layer type,
18573      * and hardware acceleration.
18574      */
18575     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18576         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18577         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18578          *
18579          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18580          * HW accelerated, it can't handle drawing RenderNodes.
18581          */
18582         boolean drawingWithRenderNode = mAttachInfo != null
18583                 && mAttachInfo.mHardwareAccelerated
18584                 && hardwareAcceleratedCanvas;
18585
18586         boolean more = false;
18587         final boolean childHasIdentityMatrix = hasIdentityMatrix();
18588         final int parentFlags = parent.mGroupFlags;
18589
18590         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18591             parent.getChildTransformation().clear();
18592             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18593         }
18594
18595         Transformation transformToApply = null;
18596         boolean concatMatrix = false;
18597         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18598         final Animation a = getAnimation();
18599         if (a != null) {
18600             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18601             concatMatrix = a.willChangeTransformationMatrix();
18602             if (concatMatrix) {
18603                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18604             }
18605             transformToApply = parent.getChildTransformation();
18606         } else {
18607             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18608                 // No longer animating: clear out old animation matrix
18609                 mRenderNode.setAnimationMatrix(null);
18610                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18611             }
18612             if (!drawingWithRenderNode
18613                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18614                 final Transformation t = parent.getChildTransformation();
18615                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18616                 if (hasTransform) {
18617                     final int transformType = t.getTransformationType();
18618                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18619                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18620                 }
18621             }
18622         }
18623
18624         concatMatrix |= !childHasIdentityMatrix;
18625
18626         // Sets the flag as early as possible to allow draw() implementations
18627         // to call invalidate() successfully when doing animations
18628         mPrivateFlags |= PFLAG_DRAWN;
18629
18630         if (!concatMatrix &&
18631                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18632                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18633                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18634                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18635             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18636             return more;
18637         }
18638         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18639
18640         if (hardwareAcceleratedCanvas) {
18641             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18642             // retain the flag's value temporarily in the mRecreateDisplayList flag
18643             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18644             mPrivateFlags &= ~PFLAG_INVALIDATED;
18645         }
18646
18647         RenderNode renderNode = null;
18648         Bitmap cache = null;
18649         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18650         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18651              if (layerType != LAYER_TYPE_NONE) {
18652                  // If not drawing with RenderNode, treat HW layers as SW
18653                  layerType = LAYER_TYPE_SOFTWARE;
18654                  buildDrawingCache(true);
18655             }
18656             cache = getDrawingCache(true);
18657         }
18658
18659         if (drawingWithRenderNode) {
18660             // Delay getting the display list until animation-driven alpha values are
18661             // set up and possibly passed on to the view
18662             renderNode = updateDisplayListIfDirty();
18663             if (!renderNode.isValid()) {
18664                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
18665                 // to getDisplayList(), the display list will be marked invalid and we should not
18666                 // try to use it again.
18667                 renderNode = null;
18668                 drawingWithRenderNode = false;
18669             }
18670         }
18671
18672         int sx = 0;
18673         int sy = 0;
18674         if (!drawingWithRenderNode) {
18675             computeScroll();
18676             sx = mScrollX;
18677             sy = mScrollY;
18678         }
18679
18680         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18681         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18682
18683         int restoreTo = -1;
18684         if (!drawingWithRenderNode || transformToApply != null) {
18685             restoreTo = canvas.save();
18686         }
18687         if (offsetForScroll) {
18688             canvas.translate(mLeft - sx, mTop - sy);
18689         } else {
18690             if (!drawingWithRenderNode) {
18691                 canvas.translate(mLeft, mTop);
18692             }
18693             if (scalingRequired) {
18694                 if (drawingWithRenderNode) {
18695                     // TODO: Might not need this if we put everything inside the DL
18696                     restoreTo = canvas.save();
18697                 }
18698                 // mAttachInfo cannot be null, otherwise scalingRequired == false
18699                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
18700                 canvas.scale(scale, scale);
18701             }
18702         }
18703
18704         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18705         if (transformToApply != null
18706                 || alpha < 1
18707                 || !hasIdentityMatrix()
18708                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18709             if (transformToApply != null || !childHasIdentityMatrix) {
18710                 int transX = 0;
18711                 int transY = 0;
18712
18713                 if (offsetForScroll) {
18714                     transX = -sx;
18715                     transY = -sy;
18716                 }
18717
18718                 if (transformToApply != null) {
18719                     if (concatMatrix) {
18720                         if (drawingWithRenderNode) {
18721                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
18722                         } else {
18723                             // Undo the scroll translation, apply the transformation matrix,
18724                             // then redo the scroll translate to get the correct result.
18725                             canvas.translate(-transX, -transY);
18726                             canvas.concat(transformToApply.getMatrix());
18727                             canvas.translate(transX, transY);
18728                         }
18729                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18730                     }
18731
18732                     float transformAlpha = transformToApply.getAlpha();
18733                     if (transformAlpha < 1) {
18734                         alpha *= transformAlpha;
18735                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18736                     }
18737                 }
18738
18739                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18740                     canvas.translate(-transX, -transY);
18741                     canvas.concat(getMatrix());
18742                     canvas.translate(transX, transY);
18743                 }
18744             }
18745
18746             // Deal with alpha if it is or used to be <1
18747             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18748                 if (alpha < 1) {
18749                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18750                 } else {
18751                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18752                 }
18753                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18754                 if (!drawingWithDrawingCache) {
18755                     final int multipliedAlpha = (int) (255 * alpha);
18756                     if (!onSetAlpha(multipliedAlpha)) {
18757                         if (drawingWithRenderNode) {
18758                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18759                         } else if (layerType == LAYER_TYPE_NONE) {
18760                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18761                                     multipliedAlpha);
18762                         }
18763                     } else {
18764                         // Alpha is handled by the child directly, clobber the layer's alpha
18765                         mPrivateFlags |= PFLAG_ALPHA_SET;
18766                     }
18767                 }
18768             }
18769         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18770             onSetAlpha(255);
18771             mPrivateFlags &= ~PFLAG_ALPHA_SET;
18772         }
18773
18774         if (!drawingWithRenderNode) {
18775             // apply clips directly, since RenderNode won't do it for this draw
18776             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18777                 if (offsetForScroll) {
18778                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18779                 } else {
18780                     if (!scalingRequired || cache == null) {
18781                         canvas.clipRect(0, 0, getWidth(), getHeight());
18782                     } else {
18783                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18784                     }
18785                 }
18786             }
18787
18788             if (mClipBounds != null) {
18789                 // clip bounds ignore scroll
18790                 canvas.clipRect(mClipBounds);
18791             }
18792         }
18793
18794         if (!drawingWithDrawingCache) {
18795             if (drawingWithRenderNode) {
18796                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18797                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18798             } else {
18799                 // Fast path for layouts with no backgrounds
18800                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18801                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18802                     dispatchDraw(canvas);
18803                 } else {
18804                     draw(canvas);
18805                 }
18806             }
18807         } else if (cache != null) {
18808             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18809             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18810                 // no layer paint, use temporary paint to draw bitmap
18811                 Paint cachePaint = parent.mCachePaint;
18812                 if (cachePaint == null) {
18813                     cachePaint = new Paint();
18814                     cachePaint.setDither(false);
18815                     parent.mCachePaint = cachePaint;
18816                 }
18817                 cachePaint.setAlpha((int) (alpha * 255));
18818                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18819             } else {
18820                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
18821                 int layerPaintAlpha = mLayerPaint.getAlpha();
18822                 if (alpha < 1) {
18823                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18824                 }
18825                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18826                 if (alpha < 1) {
18827                     mLayerPaint.setAlpha(layerPaintAlpha);
18828                 }
18829             }
18830         }
18831
18832         if (restoreTo >= 0) {
18833             canvas.restoreToCount(restoreTo);
18834         }
18835
18836         if (a != null && !more) {
18837             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18838                 onSetAlpha(255);
18839             }
18840             parent.finishAnimatingView(this, a);
18841         }
18842
18843         if (more && hardwareAcceleratedCanvas) {
18844             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18845                 // alpha animations should cause the child to recreate its display list
18846                 invalidate(true);
18847             }
18848         }
18849
18850         mRecreateDisplayList = false;
18851
18852         return more;
18853     }
18854
18855     static Paint getDebugPaint() {
18856         if (sDebugPaint == null) {
18857             sDebugPaint = new Paint();
18858             sDebugPaint.setAntiAlias(false);
18859         }
18860         return sDebugPaint;
18861     }
18862
18863     final int dipsToPixels(int dips) {
18864         float scale = getContext().getResources().getDisplayMetrics().density;
18865         return (int) (dips * scale + 0.5f);
18866     }
18867
18868     final private void debugDrawFocus(Canvas canvas) {
18869         if (isFocused()) {
18870             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18871             final int l = mScrollX;
18872             final int r = l + mRight - mLeft;
18873             final int t = mScrollY;
18874             final int b = t + mBottom - mTop;
18875
18876             final Paint paint = getDebugPaint();
18877             paint.setColor(DEBUG_CORNERS_COLOR);
18878
18879             // Draw squares in corners.
18880             paint.setStyle(Paint.Style.FILL);
18881             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18882             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18883             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18884             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18885
18886             // Draw big X across the view.
18887             paint.setStyle(Paint.Style.STROKE);
18888             canvas.drawLine(l, t, r, b, paint);
18889             canvas.drawLine(l, b, r, t, paint);
18890         }
18891     }
18892
18893     /**
18894      * Manually render this view (and all of its children) to the given Canvas.
18895      * The view must have already done a full layout before this function is
18896      * called.  When implementing a view, implement
18897      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18898      * If you do need to override this method, call the superclass version.
18899      *
18900      * @param canvas The Canvas to which the View is rendered.
18901      */
18902     @CallSuper
18903     public void draw(Canvas canvas) {
18904         final int privateFlags = mPrivateFlags;
18905         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18906                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18907         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18908
18909         /*
18910          * Draw traversal performs several drawing steps which must be executed
18911          * in the appropriate order:
18912          *
18913          *      1. Draw the background
18914          *      2. If necessary, save the canvas' layers to prepare for fading
18915          *      3. Draw view's content
18916          *      4. Draw children
18917          *      5. If necessary, draw the fading edges and restore layers
18918          *      6. Draw decorations (scrollbars for instance)
18919          */
18920
18921         // Step 1, draw the background, if needed
18922         int saveCount;
18923
18924         if (!dirtyOpaque) {
18925             drawBackground(canvas);
18926         }
18927
18928         // skip step 2 & 5 if possible (common case)
18929         final int viewFlags = mViewFlags;
18930         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18931         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18932         if (!verticalEdges && !horizontalEdges) {
18933             // Step 3, draw the content
18934             if (!dirtyOpaque) onDraw(canvas);
18935
18936             // Step 4, draw the children
18937             dispatchDraw(canvas);
18938
18939             drawAutofilledHighlight(canvas);
18940
18941             // Overlay is part of the content and draws beneath Foreground
18942             if (mOverlay != null && !mOverlay.isEmpty()) {
18943                 mOverlay.getOverlayView().dispatchDraw(canvas);
18944             }
18945
18946             // Step 6, draw decorations (foreground, scrollbars)
18947             onDrawForeground(canvas);
18948
18949             // Step 7, draw the default focus highlight
18950             drawDefaultFocusHighlight(canvas);
18951
18952             if (debugDraw()) {
18953                 debugDrawFocus(canvas);
18954             }
18955
18956             // we're done...
18957             return;
18958         }
18959
18960         /*
18961          * Here we do the full fledged routine...
18962          * (this is an uncommon case where speed matters less,
18963          * this is why we repeat some of the tests that have been
18964          * done above)
18965          */
18966
18967         boolean drawTop = false;
18968         boolean drawBottom = false;
18969         boolean drawLeft = false;
18970         boolean drawRight = false;
18971
18972         float topFadeStrength = 0.0f;
18973         float bottomFadeStrength = 0.0f;
18974         float leftFadeStrength = 0.0f;
18975         float rightFadeStrength = 0.0f;
18976
18977         // Step 2, save the canvas' layers
18978         int paddingLeft = mPaddingLeft;
18979
18980         final boolean offsetRequired = isPaddingOffsetRequired();
18981         if (offsetRequired) {
18982             paddingLeft += getLeftPaddingOffset();
18983         }
18984
18985         int left = mScrollX + paddingLeft;
18986         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18987         int top = mScrollY + getFadeTop(offsetRequired);
18988         int bottom = top + getFadeHeight(offsetRequired);
18989
18990         if (offsetRequired) {
18991             right += getRightPaddingOffset();
18992             bottom += getBottomPaddingOffset();
18993         }
18994
18995         final ScrollabilityCache scrollabilityCache = mScrollCache;
18996         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18997         int length = (int) fadeHeight;
18998
18999         // clip the fade length if top and bottom fades overlap
19000         // overlapping fades produce odd-looking artifacts
19001         if (verticalEdges && (top + length > bottom - length)) {
19002             length = (bottom - top) / 2;
19003         }
19004
19005         // also clip horizontal fades if necessary
19006         if (horizontalEdges && (left + length > right - length)) {
19007             length = (right - left) / 2;
19008         }
19009
19010         if (verticalEdges) {
19011             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
19012             drawTop = topFadeStrength * fadeHeight > 1.0f;
19013             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
19014             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
19015         }
19016
19017         if (horizontalEdges) {
19018             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
19019             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
19020             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
19021             drawRight = rightFadeStrength * fadeHeight > 1.0f;
19022         }
19023
19024         saveCount = canvas.getSaveCount();
19025
19026         int solidColor = getSolidColor();
19027         if (solidColor == 0) {
19028             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
19029
19030             if (drawTop) {
19031                 canvas.saveLayer(left, top, right, top + length, null, flags);
19032             }
19033
19034             if (drawBottom) {
19035                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
19036             }
19037
19038             if (drawLeft) {
19039                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
19040             }
19041
19042             if (drawRight) {
19043                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
19044             }
19045         } else {
19046             scrollabilityCache.setFadeColor(solidColor);
19047         }
19048
19049         // Step 3, draw the content
19050         if (!dirtyOpaque) onDraw(canvas);
19051
19052         // Step 4, draw the children
19053         dispatchDraw(canvas);
19054
19055         // Step 5, draw the fade effect and restore layers
19056         final Paint p = scrollabilityCache.paint;
19057         final Matrix matrix = scrollabilityCache.matrix;
19058         final Shader fade = scrollabilityCache.shader;
19059
19060         if (drawTop) {
19061             matrix.setScale(1, fadeHeight * topFadeStrength);
19062             matrix.postTranslate(left, top);
19063             fade.setLocalMatrix(matrix);
19064             p.setShader(fade);
19065             canvas.drawRect(left, top, right, top + length, p);
19066         }
19067
19068         if (drawBottom) {
19069             matrix.setScale(1, fadeHeight * bottomFadeStrength);
19070             matrix.postRotate(180);
19071             matrix.postTranslate(left, bottom);
19072             fade.setLocalMatrix(matrix);
19073             p.setShader(fade);
19074             canvas.drawRect(left, bottom - length, right, bottom, p);
19075         }
19076
19077         if (drawLeft) {
19078             matrix.setScale(1, fadeHeight * leftFadeStrength);
19079             matrix.postRotate(-90);
19080             matrix.postTranslate(left, top);
19081             fade.setLocalMatrix(matrix);
19082             p.setShader(fade);
19083             canvas.drawRect(left, top, left + length, bottom, p);
19084         }
19085
19086         if (drawRight) {
19087             matrix.setScale(1, fadeHeight * rightFadeStrength);
19088             matrix.postRotate(90);
19089             matrix.postTranslate(right, top);
19090             fade.setLocalMatrix(matrix);
19091             p.setShader(fade);
19092             canvas.drawRect(right - length, top, right, bottom, p);
19093         }
19094
19095         canvas.restoreToCount(saveCount);
19096
19097         drawAutofilledHighlight(canvas);
19098
19099         // Overlay is part of the content and draws beneath Foreground
19100         if (mOverlay != null && !mOverlay.isEmpty()) {
19101             mOverlay.getOverlayView().dispatchDraw(canvas);
19102         }
19103
19104         // Step 6, draw decorations (foreground, scrollbars)
19105         onDrawForeground(canvas);
19106
19107         if (debugDraw()) {
19108             debugDrawFocus(canvas);
19109         }
19110     }
19111
19112     /**
19113      * Draws the background onto the specified canvas.
19114      *
19115      * @param canvas Canvas on which to draw the background
19116      */
19117     private void drawBackground(Canvas canvas) {
19118         final Drawable background = mBackground;
19119         if (background == null) {
19120             return;
19121         }
19122
19123         setBackgroundBounds();
19124
19125         // Attempt to use a display list if requested.
19126         if (canvas.isHardwareAccelerated() && mAttachInfo != null
19127                 && mAttachInfo.mThreadedRenderer != null) {
19128             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
19129
19130             final RenderNode renderNode = mBackgroundRenderNode;
19131             if (renderNode != null && renderNode.isValid()) {
19132                 setBackgroundRenderNodeProperties(renderNode);
19133                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19134                 return;
19135             }
19136         }
19137
19138         final int scrollX = mScrollX;
19139         final int scrollY = mScrollY;
19140         if ((scrollX | scrollY) == 0) {
19141             background.draw(canvas);
19142         } else {
19143             canvas.translate(scrollX, scrollY);
19144             background.draw(canvas);
19145             canvas.translate(-scrollX, -scrollY);
19146         }
19147     }
19148
19149     /**
19150      * Sets the correct background bounds and rebuilds the outline, if needed.
19151      * <p/>
19152      * This is called by LayoutLib.
19153      */
19154     void setBackgroundBounds() {
19155         if (mBackgroundSizeChanged && mBackground != null) {
19156             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
19157             mBackgroundSizeChanged = false;
19158             rebuildOutline();
19159         }
19160     }
19161
19162     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
19163         renderNode.setTranslationX(mScrollX);
19164         renderNode.setTranslationY(mScrollY);
19165     }
19166
19167     /**
19168      * Creates a new display list or updates the existing display list for the
19169      * specified Drawable.
19170      *
19171      * @param drawable Drawable for which to create a display list
19172      * @param renderNode Existing RenderNode, or {@code null}
19173      * @return A valid display list for the specified drawable
19174      */
19175     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
19176         if (renderNode == null) {
19177             renderNode = RenderNode.create(drawable.getClass().getName(), this);
19178         }
19179
19180         final Rect bounds = drawable.getBounds();
19181         final int width = bounds.width();
19182         final int height = bounds.height();
19183         final DisplayListCanvas canvas = renderNode.start(width, height);
19184
19185         // Reverse left/top translation done by drawable canvas, which will
19186         // instead be applied by rendernode's LTRB bounds below. This way, the
19187         // drawable's bounds match with its rendernode bounds and its content
19188         // will lie within those bounds in the rendernode tree.
19189         canvas.translate(-bounds.left, -bounds.top);
19190
19191         try {
19192             drawable.draw(canvas);
19193         } finally {
19194             renderNode.end(canvas);
19195         }
19196
19197         // Set up drawable properties that are view-independent.
19198         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19199         renderNode.setProjectBackwards(drawable.isProjected());
19200         renderNode.setProjectionReceiver(true);
19201         renderNode.setClipToBounds(false);
19202         return renderNode;
19203     }
19204
19205     /**
19206      * Returns the overlay for this view, creating it if it does not yet exist.
19207      * Adding drawables to the overlay will cause them to be displayed whenever
19208      * the view itself is redrawn. Objects in the overlay should be actively
19209      * managed: remove them when they should not be displayed anymore. The
19210      * overlay will always have the same size as its host view.
19211      *
19212      * <p>Note: Overlays do not currently work correctly with {@link
19213      * SurfaceView} or {@link TextureView}; contents in overlays for these
19214      * types of views may not display correctly.</p>
19215      *
19216      * @return The ViewOverlay object for this view.
19217      * @see ViewOverlay
19218      */
19219     public ViewOverlay getOverlay() {
19220         if (mOverlay == null) {
19221             mOverlay = new ViewOverlay(mContext, this);
19222         }
19223         return mOverlay;
19224     }
19225
19226     /**
19227      * Override this if your view is known to always be drawn on top of a solid color background,
19228      * and needs to draw fading edges. Returning a non-zero color enables the view system to
19229      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19230      * should be set to 0xFF.
19231      *
19232      * @see #setVerticalFadingEdgeEnabled(boolean)
19233      * @see #setHorizontalFadingEdgeEnabled(boolean)
19234      *
19235      * @return The known solid color background for this view, or 0 if the color may vary
19236      */
19237     @ViewDebug.ExportedProperty(category = "drawing")
19238     @ColorInt
19239     public int getSolidColor() {
19240         return 0;
19241     }
19242
19243     /**
19244      * Build a human readable string representation of the specified view flags.
19245      *
19246      * @param flags the view flags to convert to a string
19247      * @return a String representing the supplied flags
19248      */
19249     private static String printFlags(int flags) {
19250         String output = "";
19251         int numFlags = 0;
19252         if ((flags & FOCUSABLE) == FOCUSABLE) {
19253             output += "TAKES_FOCUS";
19254             numFlags++;
19255         }
19256
19257         switch (flags & VISIBILITY_MASK) {
19258         case INVISIBLE:
19259             if (numFlags > 0) {
19260                 output += " ";
19261             }
19262             output += "INVISIBLE";
19263             // USELESS HERE numFlags++;
19264             break;
19265         case GONE:
19266             if (numFlags > 0) {
19267                 output += " ";
19268             }
19269             output += "GONE";
19270             // USELESS HERE numFlags++;
19271             break;
19272         default:
19273             break;
19274         }
19275         return output;
19276     }
19277
19278     /**
19279      * Build a human readable string representation of the specified private
19280      * view flags.
19281      *
19282      * @param privateFlags the private view flags to convert to a string
19283      * @return a String representing the supplied flags
19284      */
19285     private static String printPrivateFlags(int privateFlags) {
19286         String output = "";
19287         int numFlags = 0;
19288
19289         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19290             output += "WANTS_FOCUS";
19291             numFlags++;
19292         }
19293
19294         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19295             if (numFlags > 0) {
19296                 output += " ";
19297             }
19298             output += "FOCUSED";
19299             numFlags++;
19300         }
19301
19302         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19303             if (numFlags > 0) {
19304                 output += " ";
19305             }
19306             output += "SELECTED";
19307             numFlags++;
19308         }
19309
19310         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19311             if (numFlags > 0) {
19312                 output += " ";
19313             }
19314             output += "IS_ROOT_NAMESPACE";
19315             numFlags++;
19316         }
19317
19318         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19319             if (numFlags > 0) {
19320                 output += " ";
19321             }
19322             output += "HAS_BOUNDS";
19323             numFlags++;
19324         }
19325
19326         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19327             if (numFlags > 0) {
19328                 output += " ";
19329             }
19330             output += "DRAWN";
19331             // USELESS HERE numFlags++;
19332         }
19333         return output;
19334     }
19335
19336     /**
19337      * <p>Indicates whether or not this view's layout will be requested during
19338      * the next hierarchy layout pass.</p>
19339      *
19340      * @return true if the layout will be forced during next layout pass
19341      */
19342     public boolean isLayoutRequested() {
19343         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19344     }
19345
19346     /**
19347      * Return true if o is a ViewGroup that is laying out using optical bounds.
19348      * @hide
19349      */
19350     public static boolean isLayoutModeOptical(Object o) {
19351         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19352     }
19353
19354     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19355         Insets parentInsets = mParent instanceof View ?
19356                 ((View) mParent).getOpticalInsets() : Insets.NONE;
19357         Insets childInsets = getOpticalInsets();
19358         return setFrame(
19359                 left   + parentInsets.left - childInsets.left,
19360                 top    + parentInsets.top  - childInsets.top,
19361                 right  + parentInsets.left + childInsets.right,
19362                 bottom + parentInsets.top  + childInsets.bottom);
19363     }
19364
19365     /**
19366      * Assign a size and position to a view and all of its
19367      * descendants
19368      *
19369      * <p>This is the second phase of the layout mechanism.
19370      * (The first is measuring). In this phase, each parent calls
19371      * layout on all of its children to position them.
19372      * This is typically done using the child measurements
19373      * that were stored in the measure pass().</p>
19374      *
19375      * <p>Derived classes should not override this method.
19376      * Derived classes with children should override
19377      * onLayout. In that method, they should
19378      * call layout on each of their children.</p>
19379      *
19380      * @param l Left position, relative to parent
19381      * @param t Top position, relative to parent
19382      * @param r Right position, relative to parent
19383      * @param b Bottom position, relative to parent
19384      */
19385     @SuppressWarnings({"unchecked"})
19386     public void layout(int l, int t, int r, int b) {
19387         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19388             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19389             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19390         }
19391
19392         int oldL = mLeft;
19393         int oldT = mTop;
19394         int oldB = mBottom;
19395         int oldR = mRight;
19396
19397         boolean changed = isLayoutModeOptical(mParent) ?
19398                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19399
19400         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19401             onLayout(changed, l, t, r, b);
19402
19403             if (shouldDrawRoundScrollbar()) {
19404                 if(mRoundScrollbarRenderer == null) {
19405                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19406                 }
19407             } else {
19408                 mRoundScrollbarRenderer = null;
19409             }
19410
19411             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19412
19413             ListenerInfo li = mListenerInfo;
19414             if (li != null && li.mOnLayoutChangeListeners != null) {
19415                 ArrayList<OnLayoutChangeListener> listenersCopy =
19416                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19417                 int numListeners = listenersCopy.size();
19418                 for (int i = 0; i < numListeners; ++i) {
19419                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19420                 }
19421             }
19422         }
19423
19424         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19425         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19426
19427         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
19428             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
19429             notifyEnterOrExitForAutoFillIfNeeded(true);
19430         }
19431     }
19432
19433     /**
19434      * Called from layout when this view should
19435      * assign a size and position to each of its children.
19436      *
19437      * Derived classes with children should override
19438      * this method and call layout on each of
19439      * their children.
19440      * @param changed This is a new size or position for this view
19441      * @param left Left position, relative to parent
19442      * @param top Top position, relative to parent
19443      * @param right Right position, relative to parent
19444      * @param bottom Bottom position, relative to parent
19445      */
19446     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19447     }
19448
19449     /**
19450      * Assign a size and position to this view.
19451      *
19452      * This is called from layout.
19453      *
19454      * @param left Left position, relative to parent
19455      * @param top Top position, relative to parent
19456      * @param right Right position, relative to parent
19457      * @param bottom Bottom position, relative to parent
19458      * @return true if the new size and position are different than the
19459      *         previous ones
19460      * {@hide}
19461      */
19462     protected boolean setFrame(int left, int top, int right, int bottom) {
19463         boolean changed = false;
19464
19465         if (DBG) {
19466             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19467                     + right + "," + bottom + ")");
19468         }
19469
19470         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19471             changed = true;
19472
19473             // Remember our drawn bit
19474             int drawn = mPrivateFlags & PFLAG_DRAWN;
19475
19476             int oldWidth = mRight - mLeft;
19477             int oldHeight = mBottom - mTop;
19478             int newWidth = right - left;
19479             int newHeight = bottom - top;
19480             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19481
19482             // Invalidate our old position
19483             invalidate(sizeChanged);
19484
19485             mLeft = left;
19486             mTop = top;
19487             mRight = right;
19488             mBottom = bottom;
19489             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19490
19491             mPrivateFlags |= PFLAG_HAS_BOUNDS;
19492
19493
19494             if (sizeChanged) {
19495                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19496             }
19497
19498             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19499                 // If we are visible, force the DRAWN bit to on so that
19500                 // this invalidate will go through (at least to our parent).
19501                 // This is because someone may have invalidated this view
19502                 // before this call to setFrame came in, thereby clearing
19503                 // the DRAWN bit.
19504                 mPrivateFlags |= PFLAG_DRAWN;
19505                 invalidate(sizeChanged);
19506                 // parent display list may need to be recreated based on a change in the bounds
19507                 // of any child
19508                 invalidateParentCaches();
19509             }
19510
19511             // Reset drawn bit to original value (invalidate turns it off)
19512             mPrivateFlags |= drawn;
19513
19514             mBackgroundSizeChanged = true;
19515             mDefaultFocusHighlightSizeChanged = true;
19516             if (mForegroundInfo != null) {
19517                 mForegroundInfo.mBoundsChanged = true;
19518             }
19519
19520             notifySubtreeAccessibilityStateChangedIfNeeded();
19521         }
19522         return changed;
19523     }
19524
19525     /**
19526      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19527      * @hide
19528      */
19529     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19530         setFrame(left, top, right, bottom);
19531     }
19532
19533     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19534         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19535         if (mOverlay != null) {
19536             mOverlay.getOverlayView().setRight(newWidth);
19537             mOverlay.getOverlayView().setBottom(newHeight);
19538         }
19539         rebuildOutline();
19540     }
19541
19542     /**
19543      * Finalize inflating a view from XML.  This is called as the last phase
19544      * of inflation, after all child views have been added.
19545      *
19546      * <p>Even if the subclass overrides onFinishInflate, they should always be
19547      * sure to call the super method, so that we get called.
19548      */
19549     @CallSuper
19550     protected void onFinishInflate() {
19551     }
19552
19553     /**
19554      * Returns the resources associated with this view.
19555      *
19556      * @return Resources object.
19557      */
19558     public Resources getResources() {
19559         return mResources;
19560     }
19561
19562     /**
19563      * Invalidates the specified Drawable.
19564      *
19565      * @param drawable the drawable to invalidate
19566      */
19567     @Override
19568     public void invalidateDrawable(@NonNull Drawable drawable) {
19569         if (verifyDrawable(drawable)) {
19570             final Rect dirty = drawable.getDirtyBounds();
19571             final int scrollX = mScrollX;
19572             final int scrollY = mScrollY;
19573
19574             invalidate(dirty.left + scrollX, dirty.top + scrollY,
19575                     dirty.right + scrollX, dirty.bottom + scrollY);
19576             rebuildOutline();
19577         }
19578     }
19579
19580     /**
19581      * Schedules an action on a drawable to occur at a specified time.
19582      *
19583      * @param who the recipient of the action
19584      * @param what the action to run on the drawable
19585      * @param when the time at which the action must occur. Uses the
19586      *        {@link SystemClock#uptimeMillis} timebase.
19587      */
19588     @Override
19589     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19590         if (verifyDrawable(who) && what != null) {
19591             final long delay = when - SystemClock.uptimeMillis();
19592             if (mAttachInfo != null) {
19593                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19594                         Choreographer.CALLBACK_ANIMATION, what, who,
19595                         Choreographer.subtractFrameDelay(delay));
19596             } else {
19597                 // Postpone the runnable until we know
19598                 // on which thread it needs to run.
19599                 getRunQueue().postDelayed(what, delay);
19600             }
19601         }
19602     }
19603
19604     /**
19605      * Cancels a scheduled action on a drawable.
19606      *
19607      * @param who the recipient of the action
19608      * @param what the action to cancel
19609      */
19610     @Override
19611     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19612         if (verifyDrawable(who) && what != null) {
19613             if (mAttachInfo != null) {
19614                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19615                         Choreographer.CALLBACK_ANIMATION, what, who);
19616             }
19617             getRunQueue().removeCallbacks(what);
19618         }
19619     }
19620
19621     /**
19622      * Unschedule any events associated with the given Drawable.  This can be
19623      * used when selecting a new Drawable into a view, so that the previous
19624      * one is completely unscheduled.
19625      *
19626      * @param who The Drawable to unschedule.
19627      *
19628      * @see #drawableStateChanged
19629      */
19630     public void unscheduleDrawable(Drawable who) {
19631         if (mAttachInfo != null && who != null) {
19632             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19633                     Choreographer.CALLBACK_ANIMATION, null, who);
19634         }
19635     }
19636
19637     /**
19638      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19639      * that the View directionality can and will be resolved before its Drawables.
19640      *
19641      * Will call {@link View#onResolveDrawables} when resolution is done.
19642      *
19643      * @hide
19644      */
19645     protected void resolveDrawables() {
19646         // Drawables resolution may need to happen before resolving the layout direction (which is
19647         // done only during the measure() call).
19648         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19649         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19650         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19651         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19652         // direction to be resolved as its resolved value will be the same as its raw value.
19653         if (!isLayoutDirectionResolved() &&
19654                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19655             return;
19656         }
19657
19658         final int layoutDirection = isLayoutDirectionResolved() ?
19659                 getLayoutDirection() : getRawLayoutDirection();
19660
19661         if (mBackground != null) {
19662             mBackground.setLayoutDirection(layoutDirection);
19663         }
19664         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19665             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19666         }
19667         if (mDefaultFocusHighlight != null) {
19668             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19669         }
19670         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19671         onResolveDrawables(layoutDirection);
19672     }
19673
19674     boolean areDrawablesResolved() {
19675         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19676     }
19677
19678     /**
19679      * Called when layout direction has been resolved.
19680      *
19681      * The default implementation does nothing.
19682      *
19683      * @param layoutDirection The resolved layout direction.
19684      *
19685      * @see #LAYOUT_DIRECTION_LTR
19686      * @see #LAYOUT_DIRECTION_RTL
19687      *
19688      * @hide
19689      */
19690     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19691     }
19692
19693     /**
19694      * @hide
19695      */
19696     protected void resetResolvedDrawables() {
19697         resetResolvedDrawablesInternal();
19698     }
19699
19700     void resetResolvedDrawablesInternal() {
19701         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19702     }
19703
19704     /**
19705      * If your view subclass is displaying its own Drawable objects, it should
19706      * override this function and return true for any Drawable it is
19707      * displaying.  This allows animations for those drawables to be
19708      * scheduled.
19709      *
19710      * <p>Be sure to call through to the super class when overriding this
19711      * function.
19712      *
19713      * @param who The Drawable to verify.  Return true if it is one you are
19714      *            displaying, else return the result of calling through to the
19715      *            super class.
19716      *
19717      * @return boolean If true than the Drawable is being displayed in the
19718      *         view; else false and it is not allowed to animate.
19719      *
19720      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19721      * @see #drawableStateChanged()
19722      */
19723     @CallSuper
19724     protected boolean verifyDrawable(@NonNull Drawable who) {
19725         // Avoid verifying the scroll bar drawable so that we don't end up in
19726         // an invalidation loop. This effectively prevents the scroll bar
19727         // drawable from triggering invalidations and scheduling runnables.
19728         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19729                 || (mDefaultFocusHighlight == who);
19730     }
19731
19732     /**
19733      * This function is called whenever the state of the view changes in such
19734      * a way that it impacts the state of drawables being shown.
19735      * <p>
19736      * If the View has a StateListAnimator, it will also be called to run necessary state
19737      * change animations.
19738      * <p>
19739      * Be sure to call through to the superclass when overriding this function.
19740      *
19741      * @see Drawable#setState(int[])
19742      */
19743     @CallSuper
19744     protected void drawableStateChanged() {
19745         final int[] state = getDrawableState();
19746         boolean changed = false;
19747
19748         final Drawable bg = mBackground;
19749         if (bg != null && bg.isStateful()) {
19750             changed |= bg.setState(state);
19751         }
19752
19753         final Drawable hl = mDefaultFocusHighlight;
19754         if (hl != null && hl.isStateful()) {
19755             changed |= hl.setState(state);
19756         }
19757
19758         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19759         if (fg != null && fg.isStateful()) {
19760             changed |= fg.setState(state);
19761         }
19762
19763         if (mScrollCache != null) {
19764             final Drawable scrollBar = mScrollCache.scrollBar;
19765             if (scrollBar != null && scrollBar.isStateful()) {
19766                 changed |= scrollBar.setState(state)
19767                         && mScrollCache.state != ScrollabilityCache.OFF;
19768             }
19769         }
19770
19771         if (mStateListAnimator != null) {
19772             mStateListAnimator.setState(state);
19773         }
19774
19775         if (changed) {
19776             invalidate();
19777         }
19778     }
19779
19780     /**
19781      * This function is called whenever the view hotspot changes and needs to
19782      * be propagated to drawables or child views managed by the view.
19783      * <p>
19784      * Dispatching to child views is handled by
19785      * {@link #dispatchDrawableHotspotChanged(float, float)}.
19786      * <p>
19787      * Be sure to call through to the superclass when overriding this function.
19788      *
19789      * @param x hotspot x coordinate
19790      * @param y hotspot y coordinate
19791      */
19792     @CallSuper
19793     public void drawableHotspotChanged(float x, float y) {
19794         if (mBackground != null) {
19795             mBackground.setHotspot(x, y);
19796         }
19797         if (mDefaultFocusHighlight != null) {
19798             mDefaultFocusHighlight.setHotspot(x, y);
19799         }
19800         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19801             mForegroundInfo.mDrawable.setHotspot(x, y);
19802         }
19803
19804         dispatchDrawableHotspotChanged(x, y);
19805     }
19806
19807     /**
19808      * Dispatches drawableHotspotChanged to all of this View's children.
19809      *
19810      * @param x hotspot x coordinate
19811      * @param y hotspot y coordinate
19812      * @see #drawableHotspotChanged(float, float)
19813      */
19814     public void dispatchDrawableHotspotChanged(float x, float y) {
19815     }
19816
19817     /**
19818      * Call this to force a view to update its drawable state. This will cause
19819      * drawableStateChanged to be called on this view. Views that are interested
19820      * in the new state should call getDrawableState.
19821      *
19822      * @see #drawableStateChanged
19823      * @see #getDrawableState
19824      */
19825     public void refreshDrawableState() {
19826         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19827         drawableStateChanged();
19828
19829         ViewParent parent = mParent;
19830         if (parent != null) {
19831             parent.childDrawableStateChanged(this);
19832         }
19833     }
19834
19835     /**
19836      * Create a default focus highlight if it doesn't exist.
19837      * @return a default focus highlight.
19838      */
19839     private Drawable getDefaultFocusHighlightDrawable() {
19840         if (mDefaultFocusHighlightCache == null) {
19841             if (mContext != null) {
19842                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
19843                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
19844                 mDefaultFocusHighlightCache = ta.getDrawable(0);
19845                 ta.recycle();
19846             }
19847         }
19848         return mDefaultFocusHighlightCache;
19849     }
19850
19851     /**
19852      * Set the current default focus highlight.
19853      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
19854      */
19855     private void setDefaultFocusHighlight(Drawable highlight) {
19856         mDefaultFocusHighlight = highlight;
19857         mDefaultFocusHighlightSizeChanged = true;
19858         if (highlight != null) {
19859             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19860                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19861             }
19862             highlight.setLayoutDirection(getLayoutDirection());
19863             if (highlight.isStateful()) {
19864                 highlight.setState(getDrawableState());
19865             }
19866             if (isAttachedToWindow()) {
19867                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19868             }
19869             // Set callback last, since the view may still be initializing.
19870             highlight.setCallback(this);
19871         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
19872                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19873             mPrivateFlags |= PFLAG_SKIP_DRAW;
19874         }
19875         invalidate();
19876     }
19877
19878     /**
19879      * Check whether we need to draw a default focus highlight when this view gets focused,
19880      * which requires:
19881      * <ul>
19882      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
19883      *         is not defined.</li>
19884      *     <li>This view is not in touch mode.</li>
19885      *     <li>This view doesn't opt out for a default focus highlight, via
19886      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
19887      *     <li>This view is attached to window.</li>
19888      * </ul>
19889      * @return {@code true} if a default focus highlight is needed.
19890      * @hide
19891      */
19892     @TestApi
19893     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
19894         final boolean lackFocusState = (background == null || !background.isStateful()
19895                 || !background.hasFocusStateSpecified())
19896                 && (foreground == null || !foreground.isStateful()
19897                 || !foreground.hasFocusStateSpecified());
19898         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
19899                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
19900     }
19901
19902     /**
19903      * When this view is focused, switches on/off the default focused highlight.
19904      * <p>
19905      * This always happens when this view is focused, and only at this moment the default focus
19906      * highlight can be visible.
19907      */
19908     private void switchDefaultFocusHighlight() {
19909         if (isFocused()) {
19910             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
19911                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
19912             final boolean active = mDefaultFocusHighlight != null;
19913             if (needed && !active) {
19914                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
19915             } else if (!needed && active) {
19916                 // The highlight is no longer needed, so tear it down.
19917                 setDefaultFocusHighlight(null);
19918             }
19919         }
19920     }
19921
19922     /**
19923      * Draw the default focus highlight onto the canvas.
19924      * @param canvas the canvas where we're drawing the highlight.
19925      */
19926     private void drawDefaultFocusHighlight(Canvas canvas) {
19927         if (mDefaultFocusHighlight != null) {
19928             if (mDefaultFocusHighlightSizeChanged) {
19929                 mDefaultFocusHighlightSizeChanged = false;
19930                 final int l = mScrollX;
19931                 final int r = l + mRight - mLeft;
19932                 final int t = mScrollY;
19933                 final int b = t + mBottom - mTop;
19934                 mDefaultFocusHighlight.setBounds(l, t, r, b);
19935             }
19936             mDefaultFocusHighlight.draw(canvas);
19937         }
19938     }
19939
19940     /**
19941      * Return an array of resource IDs of the drawable states representing the
19942      * current state of the view.
19943      *
19944      * @return The current drawable state
19945      *
19946      * @see Drawable#setState(int[])
19947      * @see #drawableStateChanged()
19948      * @see #onCreateDrawableState(int)
19949      */
19950     public final int[] getDrawableState() {
19951         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19952             return mDrawableState;
19953         } else {
19954             mDrawableState = onCreateDrawableState(0);
19955             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19956             return mDrawableState;
19957         }
19958     }
19959
19960     /**
19961      * Generate the new {@link android.graphics.drawable.Drawable} state for
19962      * this view. This is called by the view
19963      * system when the cached Drawable state is determined to be invalid.  To
19964      * retrieve the current state, you should use {@link #getDrawableState}.
19965      *
19966      * @param extraSpace if non-zero, this is the number of extra entries you
19967      * would like in the returned array in which you can place your own
19968      * states.
19969      *
19970      * @return Returns an array holding the current {@link Drawable} state of
19971      * the view.
19972      *
19973      * @see #mergeDrawableStates(int[], int[])
19974      */
19975     protected int[] onCreateDrawableState(int extraSpace) {
19976         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19977                 mParent instanceof View) {
19978             return ((View) mParent).onCreateDrawableState(extraSpace);
19979         }
19980
19981         int[] drawableState;
19982
19983         int privateFlags = mPrivateFlags;
19984
19985         int viewStateIndex = 0;
19986         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19987         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19988         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19989         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19990         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19991         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19992         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19993                 ThreadedRenderer.isAvailable()) {
19994             // This is set if HW acceleration is requested, even if the current
19995             // process doesn't allow it.  This is just to allow app preview
19996             // windows to better match their app.
19997             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19998         }
19999         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
20000
20001         final int privateFlags2 = mPrivateFlags2;
20002         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
20003             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
20004         }
20005         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
20006             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
20007         }
20008
20009         drawableState = StateSet.get(viewStateIndex);
20010
20011         //noinspection ConstantIfStatement
20012         if (false) {
20013             Log.i("View", "drawableStateIndex=" + viewStateIndex);
20014             Log.i("View", toString()
20015                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
20016                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
20017                     + " fo=" + hasFocus()
20018                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
20019                     + " wf=" + hasWindowFocus()
20020                     + ": " + Arrays.toString(drawableState));
20021         }
20022
20023         if (extraSpace == 0) {
20024             return drawableState;
20025         }
20026
20027         final int[] fullState;
20028         if (drawableState != null) {
20029             fullState = new int[drawableState.length + extraSpace];
20030             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
20031         } else {
20032             fullState = new int[extraSpace];
20033         }
20034
20035         return fullState;
20036     }
20037
20038     /**
20039      * Merge your own state values in <var>additionalState</var> into the base
20040      * state values <var>baseState</var> that were returned by
20041      * {@link #onCreateDrawableState(int)}.
20042      *
20043      * @param baseState The base state values returned by
20044      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
20045      * own additional state values.
20046      *
20047      * @param additionalState The additional state values you would like
20048      * added to <var>baseState</var>; this array is not modified.
20049      *
20050      * @return As a convenience, the <var>baseState</var> array you originally
20051      * passed into the function is returned.
20052      *
20053      * @see #onCreateDrawableState(int)
20054      */
20055     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
20056         final int N = baseState.length;
20057         int i = N - 1;
20058         while (i >= 0 && baseState[i] == 0) {
20059             i--;
20060         }
20061         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
20062         return baseState;
20063     }
20064
20065     /**
20066      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
20067      * on all Drawable objects associated with this view.
20068      * <p>
20069      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
20070      * attached to this view.
20071      */
20072     @CallSuper
20073     public void jumpDrawablesToCurrentState() {
20074         if (mBackground != null) {
20075             mBackground.jumpToCurrentState();
20076         }
20077         if (mStateListAnimator != null) {
20078             mStateListAnimator.jumpToCurrentState();
20079         }
20080         if (mDefaultFocusHighlight != null) {
20081             mDefaultFocusHighlight.jumpToCurrentState();
20082         }
20083         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20084             mForegroundInfo.mDrawable.jumpToCurrentState();
20085         }
20086     }
20087
20088     /**
20089      * Sets the background color for this view.
20090      * @param color the color of the background
20091      */
20092     @RemotableViewMethod
20093     public void setBackgroundColor(@ColorInt int color) {
20094         if (mBackground instanceof ColorDrawable) {
20095             ((ColorDrawable) mBackground.mutate()).setColor(color);
20096             computeOpaqueFlags();
20097             mBackgroundResource = 0;
20098         } else {
20099             setBackground(new ColorDrawable(color));
20100         }
20101     }
20102
20103     /**
20104      * Set the background to a given resource. The resource should refer to
20105      * a Drawable object or 0 to remove the background.
20106      * @param resid The identifier of the resource.
20107      *
20108      * @attr ref android.R.styleable#View_background
20109      */
20110     @RemotableViewMethod
20111     public void setBackgroundResource(@DrawableRes int resid) {
20112         if (resid != 0 && resid == mBackgroundResource) {
20113             return;
20114         }
20115
20116         Drawable d = null;
20117         if (resid != 0) {
20118             d = mContext.getDrawable(resid);
20119         }
20120         setBackground(d);
20121
20122         mBackgroundResource = resid;
20123     }
20124
20125     /**
20126      * Set the background to a given Drawable, or remove the background. If the
20127      * background has padding, this View's padding is set to the background's
20128      * padding. However, when a background is removed, this View's padding isn't
20129      * touched. If setting the padding is desired, please use
20130      * {@link #setPadding(int, int, int, int)}.
20131      *
20132      * @param background The Drawable to use as the background, or null to remove the
20133      *        background
20134      */
20135     public void setBackground(Drawable background) {
20136         //noinspection deprecation
20137         setBackgroundDrawable(background);
20138     }
20139
20140     /**
20141      * @deprecated use {@link #setBackground(Drawable)} instead
20142      */
20143     @Deprecated
20144     public void setBackgroundDrawable(Drawable background) {
20145         computeOpaqueFlags();
20146
20147         if (background == mBackground) {
20148             return;
20149         }
20150
20151         boolean requestLayout = false;
20152
20153         mBackgroundResource = 0;
20154
20155         /*
20156          * Regardless of whether we're setting a new background or not, we want
20157          * to clear the previous drawable. setVisible first while we still have the callback set.
20158          */
20159         if (mBackground != null) {
20160             if (isAttachedToWindow()) {
20161                 mBackground.setVisible(false, false);
20162             }
20163             mBackground.setCallback(null);
20164             unscheduleDrawable(mBackground);
20165         }
20166
20167         if (background != null) {
20168             Rect padding = sThreadLocal.get();
20169             if (padding == null) {
20170                 padding = new Rect();
20171                 sThreadLocal.set(padding);
20172             }
20173             resetResolvedDrawablesInternal();
20174             background.setLayoutDirection(getLayoutDirection());
20175             if (background.getPadding(padding)) {
20176                 resetResolvedPaddingInternal();
20177                 switch (background.getLayoutDirection()) {
20178                     case LAYOUT_DIRECTION_RTL:
20179                         mUserPaddingLeftInitial = padding.right;
20180                         mUserPaddingRightInitial = padding.left;
20181                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
20182                         break;
20183                     case LAYOUT_DIRECTION_LTR:
20184                     default:
20185                         mUserPaddingLeftInitial = padding.left;
20186                         mUserPaddingRightInitial = padding.right;
20187                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
20188                 }
20189                 mLeftPaddingDefined = false;
20190                 mRightPaddingDefined = false;
20191             }
20192
20193             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
20194             // if it has a different minimum size, we should layout again
20195             if (mBackground == null
20196                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
20197                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
20198                 requestLayout = true;
20199             }
20200
20201             // Set mBackground before we set this as the callback and start making other
20202             // background drawable state change calls. In particular, the setVisible call below
20203             // can result in drawables attempting to start animations or otherwise invalidate,
20204             // which requires the view set as the callback (us) to recognize the drawable as
20205             // belonging to it as per verifyDrawable.
20206             mBackground = background;
20207             if (background.isStateful()) {
20208                 background.setState(getDrawableState());
20209             }
20210             if (isAttachedToWindow()) {
20211                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20212             }
20213
20214             applyBackgroundTint();
20215
20216             // Set callback last, since the view may still be initializing.
20217             background.setCallback(this);
20218
20219             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20220                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20221                 requestLayout = true;
20222             }
20223         } else {
20224             /* Remove the background */
20225             mBackground = null;
20226             if ((mViewFlags & WILL_NOT_DRAW) != 0
20227                     && (mDefaultFocusHighlight == null)
20228                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20229                 mPrivateFlags |= PFLAG_SKIP_DRAW;
20230             }
20231
20232             /*
20233              * When the background is set, we try to apply its padding to this
20234              * View. When the background is removed, we don't touch this View's
20235              * padding. This is noted in the Javadocs. Hence, we don't need to
20236              * requestLayout(), the invalidate() below is sufficient.
20237              */
20238
20239             // The old background's minimum size could have affected this
20240             // View's layout, so let's requestLayout
20241             requestLayout = true;
20242         }
20243
20244         computeOpaqueFlags();
20245
20246         if (requestLayout) {
20247             requestLayout();
20248         }
20249
20250         mBackgroundSizeChanged = true;
20251         invalidate(true);
20252         invalidateOutline();
20253     }
20254
20255     /**
20256      * Gets the background drawable
20257      *
20258      * @return The drawable used as the background for this view, if any.
20259      *
20260      * @see #setBackground(Drawable)
20261      *
20262      * @attr ref android.R.styleable#View_background
20263      */
20264     public Drawable getBackground() {
20265         return mBackground;
20266     }
20267
20268     /**
20269      * Applies a tint to the background drawable. Does not modify the current tint
20270      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20271      * <p>
20272      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20273      * mutate the drawable and apply the specified tint and tint mode using
20274      * {@link Drawable#setTintList(ColorStateList)}.
20275      *
20276      * @param tint the tint to apply, may be {@code null} to clear tint
20277      *
20278      * @attr ref android.R.styleable#View_backgroundTint
20279      * @see #getBackgroundTintList()
20280      * @see Drawable#setTintList(ColorStateList)
20281      */
20282     public void setBackgroundTintList(@Nullable ColorStateList tint) {
20283         if (mBackgroundTint == null) {
20284             mBackgroundTint = new TintInfo();
20285         }
20286         mBackgroundTint.mTintList = tint;
20287         mBackgroundTint.mHasTintList = true;
20288
20289         applyBackgroundTint();
20290     }
20291
20292     /**
20293      * Return the tint applied to the background drawable, if specified.
20294      *
20295      * @return the tint applied to the background drawable
20296      * @attr ref android.R.styleable#View_backgroundTint
20297      * @see #setBackgroundTintList(ColorStateList)
20298      */
20299     @Nullable
20300     public ColorStateList getBackgroundTintList() {
20301         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20302     }
20303
20304     /**
20305      * Specifies the blending mode used to apply the tint specified by
20306      * {@link #setBackgroundTintList(ColorStateList)}} to the background
20307      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20308      *
20309      * @param tintMode the blending mode used to apply the tint, may be
20310      *                 {@code null} to clear tint
20311      * @attr ref android.R.styleable#View_backgroundTintMode
20312      * @see #getBackgroundTintMode()
20313      * @see Drawable#setTintMode(PorterDuff.Mode)
20314      */
20315     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20316         if (mBackgroundTint == null) {
20317             mBackgroundTint = new TintInfo();
20318         }
20319         mBackgroundTint.mTintMode = tintMode;
20320         mBackgroundTint.mHasTintMode = true;
20321
20322         applyBackgroundTint();
20323     }
20324
20325     /**
20326      * Return the blending mode used to apply the tint to the background
20327      * drawable, if specified.
20328      *
20329      * @return the blending mode used to apply the tint to the background
20330      *         drawable
20331      * @attr ref android.R.styleable#View_backgroundTintMode
20332      * @see #setBackgroundTintMode(PorterDuff.Mode)
20333      */
20334     @Nullable
20335     public PorterDuff.Mode getBackgroundTintMode() {
20336         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20337     }
20338
20339     private void applyBackgroundTint() {
20340         if (mBackground != null && mBackgroundTint != null) {
20341             final TintInfo tintInfo = mBackgroundTint;
20342             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20343                 mBackground = mBackground.mutate();
20344
20345                 if (tintInfo.mHasTintList) {
20346                     mBackground.setTintList(tintInfo.mTintList);
20347                 }
20348
20349                 if (tintInfo.mHasTintMode) {
20350                     mBackground.setTintMode(tintInfo.mTintMode);
20351                 }
20352
20353                 // The drawable (or one of its children) may not have been
20354                 // stateful before applying the tint, so let's try again.
20355                 if (mBackground.isStateful()) {
20356                     mBackground.setState(getDrawableState());
20357                 }
20358             }
20359         }
20360     }
20361
20362     /**
20363      * Returns the drawable used as the foreground of this View. The
20364      * foreground drawable, if non-null, is always drawn on top of the view's content.
20365      *
20366      * @return a Drawable or null if no foreground was set
20367      *
20368      * @see #onDrawForeground(Canvas)
20369      */
20370     public Drawable getForeground() {
20371         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20372     }
20373
20374     /**
20375      * Supply a Drawable that is to be rendered on top of all of the content in the view.
20376      *
20377      * @param foreground the Drawable to be drawn on top of the children
20378      *
20379      * @attr ref android.R.styleable#View_foreground
20380      */
20381     public void setForeground(Drawable foreground) {
20382         if (mForegroundInfo == null) {
20383             if (foreground == null) {
20384                 // Nothing to do.
20385                 return;
20386             }
20387             mForegroundInfo = new ForegroundInfo();
20388         }
20389
20390         if (foreground == mForegroundInfo.mDrawable) {
20391             // Nothing to do
20392             return;
20393         }
20394
20395         if (mForegroundInfo.mDrawable != null) {
20396             if (isAttachedToWindow()) {
20397                 mForegroundInfo.mDrawable.setVisible(false, false);
20398             }
20399             mForegroundInfo.mDrawable.setCallback(null);
20400             unscheduleDrawable(mForegroundInfo.mDrawable);
20401         }
20402
20403         mForegroundInfo.mDrawable = foreground;
20404         mForegroundInfo.mBoundsChanged = true;
20405         if (foreground != null) {
20406             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20407                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20408             }
20409             foreground.setLayoutDirection(getLayoutDirection());
20410             if (foreground.isStateful()) {
20411                 foreground.setState(getDrawableState());
20412             }
20413             applyForegroundTint();
20414             if (isAttachedToWindow()) {
20415                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20416             }
20417             // Set callback last, since the view may still be initializing.
20418             foreground.setCallback(this);
20419         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20420                 && (mDefaultFocusHighlight == null)) {
20421             mPrivateFlags |= PFLAG_SKIP_DRAW;
20422         }
20423         requestLayout();
20424         invalidate();
20425     }
20426
20427     /**
20428      * Magic bit used to support features of framework-internal window decor implementation details.
20429      * This used to live exclusively in FrameLayout.
20430      *
20431      * @return true if the foreground should draw inside the padding region or false
20432      *         if it should draw inset by the view's padding
20433      * @hide internal use only; only used by FrameLayout and internal screen layouts.
20434      */
20435     public boolean isForegroundInsidePadding() {
20436         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20437     }
20438
20439     /**
20440      * Describes how the foreground is positioned.
20441      *
20442      * @return foreground gravity.
20443      *
20444      * @see #setForegroundGravity(int)
20445      *
20446      * @attr ref android.R.styleable#View_foregroundGravity
20447      */
20448     public int getForegroundGravity() {
20449         return mForegroundInfo != null ? mForegroundInfo.mGravity
20450                 : Gravity.START | Gravity.TOP;
20451     }
20452
20453     /**
20454      * Describes how the foreground is positioned. Defaults to START and TOP.
20455      *
20456      * @param gravity see {@link android.view.Gravity}
20457      *
20458      * @see #getForegroundGravity()
20459      *
20460      * @attr ref android.R.styleable#View_foregroundGravity
20461      */
20462     public void setForegroundGravity(int gravity) {
20463         if (mForegroundInfo == null) {
20464             mForegroundInfo = new ForegroundInfo();
20465         }
20466
20467         if (mForegroundInfo.mGravity != gravity) {
20468             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20469                 gravity |= Gravity.START;
20470             }
20471
20472             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20473                 gravity |= Gravity.TOP;
20474             }
20475
20476             mForegroundInfo.mGravity = gravity;
20477             requestLayout();
20478         }
20479     }
20480
20481     /**
20482      * Applies a tint to the foreground drawable. Does not modify the current tint
20483      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20484      * <p>
20485      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20486      * mutate the drawable and apply the specified tint and tint mode using
20487      * {@link Drawable#setTintList(ColorStateList)}.
20488      *
20489      * @param tint the tint to apply, may be {@code null} to clear tint
20490      *
20491      * @attr ref android.R.styleable#View_foregroundTint
20492      * @see #getForegroundTintList()
20493      * @see Drawable#setTintList(ColorStateList)
20494      */
20495     public void setForegroundTintList(@Nullable ColorStateList tint) {
20496         if (mForegroundInfo == null) {
20497             mForegroundInfo = new ForegroundInfo();
20498         }
20499         if (mForegroundInfo.mTintInfo == null) {
20500             mForegroundInfo.mTintInfo = new TintInfo();
20501         }
20502         mForegroundInfo.mTintInfo.mTintList = tint;
20503         mForegroundInfo.mTintInfo.mHasTintList = true;
20504
20505         applyForegroundTint();
20506     }
20507
20508     /**
20509      * Return the tint applied to the foreground drawable, if specified.
20510      *
20511      * @return the tint applied to the foreground drawable
20512      * @attr ref android.R.styleable#View_foregroundTint
20513      * @see #setForegroundTintList(ColorStateList)
20514      */
20515     @Nullable
20516     public ColorStateList getForegroundTintList() {
20517         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20518                 ? mForegroundInfo.mTintInfo.mTintList : null;
20519     }
20520
20521     /**
20522      * Specifies the blending mode used to apply the tint specified by
20523      * {@link #setForegroundTintList(ColorStateList)}} to the background
20524      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20525      *
20526      * @param tintMode the blending mode used to apply the tint, may be
20527      *                 {@code null} to clear tint
20528      * @attr ref android.R.styleable#View_foregroundTintMode
20529      * @see #getForegroundTintMode()
20530      * @see Drawable#setTintMode(PorterDuff.Mode)
20531      */
20532     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20533         if (mForegroundInfo == null) {
20534             mForegroundInfo = new ForegroundInfo();
20535         }
20536         if (mForegroundInfo.mTintInfo == null) {
20537             mForegroundInfo.mTintInfo = new TintInfo();
20538         }
20539         mForegroundInfo.mTintInfo.mTintMode = tintMode;
20540         mForegroundInfo.mTintInfo.mHasTintMode = true;
20541
20542         applyForegroundTint();
20543     }
20544
20545     /**
20546      * Return the blending mode used to apply the tint to the foreground
20547      * drawable, if specified.
20548      *
20549      * @return the blending mode used to apply the tint to the foreground
20550      *         drawable
20551      * @attr ref android.R.styleable#View_foregroundTintMode
20552      * @see #setForegroundTintMode(PorterDuff.Mode)
20553      */
20554     @Nullable
20555     public PorterDuff.Mode getForegroundTintMode() {
20556         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20557                 ? mForegroundInfo.mTintInfo.mTintMode : null;
20558     }
20559
20560     private void applyForegroundTint() {
20561         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20562                 && mForegroundInfo.mTintInfo != null) {
20563             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20564             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20565                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20566
20567                 if (tintInfo.mHasTintList) {
20568                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20569                 }
20570
20571                 if (tintInfo.mHasTintMode) {
20572                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20573                 }
20574
20575                 // The drawable (or one of its children) may not have been
20576                 // stateful before applying the tint, so let's try again.
20577                 if (mForegroundInfo.mDrawable.isStateful()) {
20578                     mForegroundInfo.mDrawable.setState(getDrawableState());
20579                 }
20580             }
20581         }
20582     }
20583
20584     /**
20585      * Get the drawable to be overlayed when a view is autofilled
20586      *
20587      * @return The drawable
20588      *
20589      * @throws IllegalStateException if the drawable could not be found.
20590      */
20591     @Nullable private Drawable getAutofilledDrawable() {
20592         if (mAttachInfo == null) {
20593             return null;
20594         }
20595         // Lazily load the isAutofilled drawable.
20596         if (mAttachInfo.mAutofilledDrawable == null) {
20597             Context rootContext = getRootView().getContext();
20598             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
20599             int attributeResourceId = a.getResourceId(0, 0);
20600             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
20601             a.recycle();
20602         }
20603
20604         return mAttachInfo.mAutofilledDrawable;
20605     }
20606
20607     /**
20608      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20609      *
20610      * @param canvas The canvas to draw on
20611      */
20612     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20613         if (isAutofilled()) {
20614             Drawable autofilledHighlight = getAutofilledDrawable();
20615
20616             if (autofilledHighlight != null) {
20617                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20618                 autofilledHighlight.draw(canvas);
20619             }
20620         }
20621     }
20622
20623     /**
20624      * Draw any foreground content for this view.
20625      *
20626      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20627      * drawable or other view-specific decorations. The foreground is drawn on top of the
20628      * primary view content.</p>
20629      *
20630      * @param canvas canvas to draw into
20631      */
20632     public void onDrawForeground(Canvas canvas) {
20633         onDrawScrollIndicators(canvas);
20634         onDrawScrollBars(canvas);
20635
20636         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20637         if (foreground != null) {
20638             if (mForegroundInfo.mBoundsChanged) {
20639                 mForegroundInfo.mBoundsChanged = false;
20640                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
20641                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20642
20643                 if (mForegroundInfo.mInsidePadding) {
20644                     selfBounds.set(0, 0, getWidth(), getHeight());
20645                 } else {
20646                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
20647                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20648                 }
20649
20650                 final int ld = getLayoutDirection();
20651                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20652                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20653                 foreground.setBounds(overlayBounds);
20654             }
20655
20656             foreground.draw(canvas);
20657         }
20658     }
20659
20660     /**
20661      * Sets the padding. The view may add on the space required to display
20662      * the scrollbars, depending on the style and visibility of the scrollbars.
20663      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20664      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20665      * from the values set in this call.
20666      *
20667      * @attr ref android.R.styleable#View_padding
20668      * @attr ref android.R.styleable#View_paddingBottom
20669      * @attr ref android.R.styleable#View_paddingLeft
20670      * @attr ref android.R.styleable#View_paddingRight
20671      * @attr ref android.R.styleable#View_paddingTop
20672      * @param left the left padding in pixels
20673      * @param top the top padding in pixels
20674      * @param right the right padding in pixels
20675      * @param bottom the bottom padding in pixels
20676      */
20677     public void setPadding(int left, int top, int right, int bottom) {
20678         resetResolvedPaddingInternal();
20679
20680         mUserPaddingStart = UNDEFINED_PADDING;
20681         mUserPaddingEnd = UNDEFINED_PADDING;
20682
20683         mUserPaddingLeftInitial = left;
20684         mUserPaddingRightInitial = right;
20685
20686         mLeftPaddingDefined = true;
20687         mRightPaddingDefined = true;
20688
20689         internalSetPadding(left, top, right, bottom);
20690     }
20691
20692     /**
20693      * @hide
20694      */
20695     protected void internalSetPadding(int left, int top, int right, int bottom) {
20696         mUserPaddingLeft = left;
20697         mUserPaddingRight = right;
20698         mUserPaddingBottom = bottom;
20699
20700         final int viewFlags = mViewFlags;
20701         boolean changed = false;
20702
20703         // Common case is there are no scroll bars.
20704         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20705             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20706                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20707                         ? 0 : getVerticalScrollbarWidth();
20708                 switch (mVerticalScrollbarPosition) {
20709                     case SCROLLBAR_POSITION_DEFAULT:
20710                         if (isLayoutRtl()) {
20711                             left += offset;
20712                         } else {
20713                             right += offset;
20714                         }
20715                         break;
20716                     case SCROLLBAR_POSITION_RIGHT:
20717                         right += offset;
20718                         break;
20719                     case SCROLLBAR_POSITION_LEFT:
20720                         left += offset;
20721                         break;
20722                 }
20723             }
20724             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20725                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20726                         ? 0 : getHorizontalScrollbarHeight();
20727             }
20728         }
20729
20730         if (mPaddingLeft != left) {
20731             changed = true;
20732             mPaddingLeft = left;
20733         }
20734         if (mPaddingTop != top) {
20735             changed = true;
20736             mPaddingTop = top;
20737         }
20738         if (mPaddingRight != right) {
20739             changed = true;
20740             mPaddingRight = right;
20741         }
20742         if (mPaddingBottom != bottom) {
20743             changed = true;
20744             mPaddingBottom = bottom;
20745         }
20746
20747         if (changed) {
20748             requestLayout();
20749             invalidateOutline();
20750         }
20751     }
20752
20753     /**
20754      * Sets the relative padding. The view may add on the space required to display
20755      * the scrollbars, depending on the style and visibility of the scrollbars.
20756      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20757      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20758      * from the values set in this call.
20759      *
20760      * @attr ref android.R.styleable#View_padding
20761      * @attr ref android.R.styleable#View_paddingBottom
20762      * @attr ref android.R.styleable#View_paddingStart
20763      * @attr ref android.R.styleable#View_paddingEnd
20764      * @attr ref android.R.styleable#View_paddingTop
20765      * @param start the start padding in pixels
20766      * @param top the top padding in pixels
20767      * @param end the end padding in pixels
20768      * @param bottom the bottom padding in pixels
20769      */
20770     public void setPaddingRelative(int start, int top, int end, int bottom) {
20771         resetResolvedPaddingInternal();
20772
20773         mUserPaddingStart = start;
20774         mUserPaddingEnd = end;
20775         mLeftPaddingDefined = true;
20776         mRightPaddingDefined = true;
20777
20778         switch(getLayoutDirection()) {
20779             case LAYOUT_DIRECTION_RTL:
20780                 mUserPaddingLeftInitial = end;
20781                 mUserPaddingRightInitial = start;
20782                 internalSetPadding(end, top, start, bottom);
20783                 break;
20784             case LAYOUT_DIRECTION_LTR:
20785             default:
20786                 mUserPaddingLeftInitial = start;
20787                 mUserPaddingRightInitial = end;
20788                 internalSetPadding(start, top, end, bottom);
20789         }
20790     }
20791
20792     /**
20793      * Returns the top padding of this view.
20794      *
20795      * @return the top padding in pixels
20796      */
20797     public int getPaddingTop() {
20798         return mPaddingTop;
20799     }
20800
20801     /**
20802      * Returns the bottom padding of this view. If there are inset and enabled
20803      * scrollbars, this value may include the space required to display the
20804      * scrollbars as well.
20805      *
20806      * @return the bottom padding in pixels
20807      */
20808     public int getPaddingBottom() {
20809         return mPaddingBottom;
20810     }
20811
20812     /**
20813      * Returns the left padding of this view. If there are inset and enabled
20814      * scrollbars, this value may include the space required to display the
20815      * scrollbars as well.
20816      *
20817      * @return the left padding in pixels
20818      */
20819     public int getPaddingLeft() {
20820         if (!isPaddingResolved()) {
20821             resolvePadding();
20822         }
20823         return mPaddingLeft;
20824     }
20825
20826     /**
20827      * Returns the start padding of this view depending on its resolved layout direction.
20828      * If there are inset and enabled scrollbars, this value may include the space
20829      * required to display the scrollbars as well.
20830      *
20831      * @return the start padding in pixels
20832      */
20833     public int getPaddingStart() {
20834         if (!isPaddingResolved()) {
20835             resolvePadding();
20836         }
20837         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20838                 mPaddingRight : mPaddingLeft;
20839     }
20840
20841     /**
20842      * Returns the right padding of this view. If there are inset and enabled
20843      * scrollbars, this value may include the space required to display the
20844      * scrollbars as well.
20845      *
20846      * @return the right padding in pixels
20847      */
20848     public int getPaddingRight() {
20849         if (!isPaddingResolved()) {
20850             resolvePadding();
20851         }
20852         return mPaddingRight;
20853     }
20854
20855     /**
20856      * Returns the end padding of this view depending on its resolved layout direction.
20857      * If there are inset and enabled scrollbars, this value may include the space
20858      * required to display the scrollbars as well.
20859      *
20860      * @return the end padding in pixels
20861      */
20862     public int getPaddingEnd() {
20863         if (!isPaddingResolved()) {
20864             resolvePadding();
20865         }
20866         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20867                 mPaddingLeft : mPaddingRight;
20868     }
20869
20870     /**
20871      * Return if the padding has been set through relative values
20872      * {@link #setPaddingRelative(int, int, int, int)} or through
20873      * @attr ref android.R.styleable#View_paddingStart or
20874      * @attr ref android.R.styleable#View_paddingEnd
20875      *
20876      * @return true if the padding is relative or false if it is not.
20877      */
20878     public boolean isPaddingRelative() {
20879         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20880     }
20881
20882     Insets computeOpticalInsets() {
20883         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20884     }
20885
20886     /**
20887      * @hide
20888      */
20889     public void resetPaddingToInitialValues() {
20890         if (isRtlCompatibilityMode()) {
20891             mPaddingLeft = mUserPaddingLeftInitial;
20892             mPaddingRight = mUserPaddingRightInitial;
20893             return;
20894         }
20895         if (isLayoutRtl()) {
20896             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20897             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20898         } else {
20899             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20900             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20901         }
20902     }
20903
20904     /**
20905      * @hide
20906      */
20907     public Insets getOpticalInsets() {
20908         if (mLayoutInsets == null) {
20909             mLayoutInsets = computeOpticalInsets();
20910         }
20911         return mLayoutInsets;
20912     }
20913
20914     /**
20915      * Set this view's optical insets.
20916      *
20917      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20918      * property. Views that compute their own optical insets should call it as part of measurement.
20919      * This method does not request layout. If you are setting optical insets outside of
20920      * measure/layout itself you will want to call requestLayout() yourself.
20921      * </p>
20922      * @hide
20923      */
20924     public void setOpticalInsets(Insets insets) {
20925         mLayoutInsets = insets;
20926     }
20927
20928     /**
20929      * Changes the selection state of this view. A view can be selected or not.
20930      * Note that selection is not the same as focus. Views are typically
20931      * selected in the context of an AdapterView like ListView or GridView;
20932      * the selected view is the view that is highlighted.
20933      *
20934      * @param selected true if the view must be selected, false otherwise
20935      */
20936     public void setSelected(boolean selected) {
20937         //noinspection DoubleNegation
20938         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20939             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20940             if (!selected) resetPressedState();
20941             invalidate(true);
20942             refreshDrawableState();
20943             dispatchSetSelected(selected);
20944             if (selected) {
20945                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20946             } else {
20947                 notifyViewAccessibilityStateChangedIfNeeded(
20948                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20949             }
20950         }
20951     }
20952
20953     /**
20954      * Dispatch setSelected to all of this View's children.
20955      *
20956      * @see #setSelected(boolean)
20957      *
20958      * @param selected The new selected state
20959      */
20960     protected void dispatchSetSelected(boolean selected) {
20961     }
20962
20963     /**
20964      * Indicates the selection state of this view.
20965      *
20966      * @return true if the view is selected, false otherwise
20967      */
20968     @ViewDebug.ExportedProperty
20969     public boolean isSelected() {
20970         return (mPrivateFlags & PFLAG_SELECTED) != 0;
20971     }
20972
20973     /**
20974      * Changes the activated state of this view. A view can be activated or not.
20975      * Note that activation is not the same as selection.  Selection is
20976      * a transient property, representing the view (hierarchy) the user is
20977      * currently interacting with.  Activation is a longer-term state that the
20978      * user can move views in and out of.  For example, in a list view with
20979      * single or multiple selection enabled, the views in the current selection
20980      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20981      * here.)  The activated state is propagated down to children of the view it
20982      * is set on.
20983      *
20984      * @param activated true if the view must be activated, false otherwise
20985      */
20986     public void setActivated(boolean activated) {
20987         //noinspection DoubleNegation
20988         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20989             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20990             invalidate(true);
20991             refreshDrawableState();
20992             dispatchSetActivated(activated);
20993         }
20994     }
20995
20996     /**
20997      * Dispatch setActivated to all of this View's children.
20998      *
20999      * @see #setActivated(boolean)
21000      *
21001      * @param activated The new activated state
21002      */
21003     protected void dispatchSetActivated(boolean activated) {
21004     }
21005
21006     /**
21007      * Indicates the activation state of this view.
21008      *
21009      * @return true if the view is activated, false otherwise
21010      */
21011     @ViewDebug.ExportedProperty
21012     public boolean isActivated() {
21013         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
21014     }
21015
21016     /**
21017      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
21018      * observer can be used to get notifications when global events, like
21019      * layout, happen.
21020      *
21021      * The returned ViewTreeObserver observer is not guaranteed to remain
21022      * valid for the lifetime of this View. If the caller of this method keeps
21023      * a long-lived reference to ViewTreeObserver, it should always check for
21024      * the return value of {@link ViewTreeObserver#isAlive()}.
21025      *
21026      * @return The ViewTreeObserver for this view's hierarchy.
21027      */
21028     public ViewTreeObserver getViewTreeObserver() {
21029         if (mAttachInfo != null) {
21030             return mAttachInfo.mTreeObserver;
21031         }
21032         if (mFloatingTreeObserver == null) {
21033             mFloatingTreeObserver = new ViewTreeObserver(mContext);
21034         }
21035         return mFloatingTreeObserver;
21036     }
21037
21038     /**
21039      * <p>Finds the topmost view in the current view hierarchy.</p>
21040      *
21041      * @return the topmost view containing this view
21042      */
21043     public View getRootView() {
21044         if (mAttachInfo != null) {
21045             final View v = mAttachInfo.mRootView;
21046             if (v != null) {
21047                 return v;
21048             }
21049         }
21050
21051         View parent = this;
21052
21053         while (parent.mParent != null && parent.mParent instanceof View) {
21054             parent = (View) parent.mParent;
21055         }
21056
21057         return parent;
21058     }
21059
21060     /**
21061      * Transforms a motion event from view-local coordinates to on-screen
21062      * coordinates.
21063      *
21064      * @param ev the view-local motion event
21065      * @return false if the transformation could not be applied
21066      * @hide
21067      */
21068     public boolean toGlobalMotionEvent(MotionEvent ev) {
21069         final AttachInfo info = mAttachInfo;
21070         if (info == null) {
21071             return false;
21072         }
21073
21074         final Matrix m = info.mTmpMatrix;
21075         m.set(Matrix.IDENTITY_MATRIX);
21076         transformMatrixToGlobal(m);
21077         ev.transform(m);
21078         return true;
21079     }
21080
21081     /**
21082      * Transforms a motion event from on-screen coordinates to view-local
21083      * coordinates.
21084      *
21085      * @param ev the on-screen motion event
21086      * @return false if the transformation could not be applied
21087      * @hide
21088      */
21089     public boolean toLocalMotionEvent(MotionEvent ev) {
21090         final AttachInfo info = mAttachInfo;
21091         if (info == null) {
21092             return false;
21093         }
21094
21095         final Matrix m = info.mTmpMatrix;
21096         m.set(Matrix.IDENTITY_MATRIX);
21097         transformMatrixToLocal(m);
21098         ev.transform(m);
21099         return true;
21100     }
21101
21102     /**
21103      * Modifies the input matrix such that it maps view-local coordinates to
21104      * on-screen coordinates.
21105      *
21106      * @param m input matrix to modify
21107      * @hide
21108      */
21109     public void transformMatrixToGlobal(Matrix m) {
21110         final ViewParent parent = mParent;
21111         if (parent instanceof View) {
21112             final View vp = (View) parent;
21113             vp.transformMatrixToGlobal(m);
21114             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
21115         } else if (parent instanceof ViewRootImpl) {
21116             final ViewRootImpl vr = (ViewRootImpl) parent;
21117             vr.transformMatrixToGlobal(m);
21118             m.preTranslate(0, -vr.mCurScrollY);
21119         }
21120
21121         m.preTranslate(mLeft, mTop);
21122
21123         if (!hasIdentityMatrix()) {
21124             m.preConcat(getMatrix());
21125         }
21126     }
21127
21128     /**
21129      * Modifies the input matrix such that it maps on-screen coordinates to
21130      * view-local coordinates.
21131      *
21132      * @param m input matrix to modify
21133      * @hide
21134      */
21135     public void transformMatrixToLocal(Matrix m) {
21136         final ViewParent parent = mParent;
21137         if (parent instanceof View) {
21138             final View vp = (View) parent;
21139             vp.transformMatrixToLocal(m);
21140             m.postTranslate(vp.mScrollX, vp.mScrollY);
21141         } else if (parent instanceof ViewRootImpl) {
21142             final ViewRootImpl vr = (ViewRootImpl) parent;
21143             vr.transformMatrixToLocal(m);
21144             m.postTranslate(0, vr.mCurScrollY);
21145         }
21146
21147         m.postTranslate(-mLeft, -mTop);
21148
21149         if (!hasIdentityMatrix()) {
21150             m.postConcat(getInverseMatrix());
21151         }
21152     }
21153
21154     /**
21155      * @hide
21156      */
21157     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
21158             @ViewDebug.IntToString(from = 0, to = "x"),
21159             @ViewDebug.IntToString(from = 1, to = "y")
21160     })
21161     public int[] getLocationOnScreen() {
21162         int[] location = new int[2];
21163         getLocationOnScreen(location);
21164         return location;
21165     }
21166
21167     /**
21168      * <p>Computes the coordinates of this view on the screen. The argument
21169      * must be an array of two integers. After the method returns, the array
21170      * contains the x and y location in that order.</p>
21171      *
21172      * @param outLocation an array of two integers in which to hold the coordinates
21173      */
21174     public void getLocationOnScreen(@Size(2) int[] outLocation) {
21175         getLocationInWindow(outLocation);
21176
21177         final AttachInfo info = mAttachInfo;
21178         if (info != null) {
21179             outLocation[0] += info.mWindowLeft;
21180             outLocation[1] += info.mWindowTop;
21181         }
21182     }
21183
21184     /**
21185      * <p>Computes the coordinates of this view in its window. The argument
21186      * must be an array of two integers. After the method returns, the array
21187      * contains the x and y location in that order.</p>
21188      *
21189      * @param outLocation an array of two integers in which to hold the coordinates
21190      */
21191     public void getLocationInWindow(@Size(2) int[] outLocation) {
21192         if (outLocation == null || outLocation.length < 2) {
21193             throw new IllegalArgumentException("outLocation must be an array of two integers");
21194         }
21195
21196         outLocation[0] = 0;
21197         outLocation[1] = 0;
21198
21199         transformFromViewToWindowSpace(outLocation);
21200     }
21201
21202     /** @hide */
21203     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
21204         if (inOutLocation == null || inOutLocation.length < 2) {
21205             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
21206         }
21207
21208         if (mAttachInfo == null) {
21209             // When the view is not attached to a window, this method does not make sense
21210             inOutLocation[0] = inOutLocation[1] = 0;
21211             return;
21212         }
21213
21214         float position[] = mAttachInfo.mTmpTransformLocation;
21215         position[0] = inOutLocation[0];
21216         position[1] = inOutLocation[1];
21217
21218         if (!hasIdentityMatrix()) {
21219             getMatrix().mapPoints(position);
21220         }
21221
21222         position[0] += mLeft;
21223         position[1] += mTop;
21224
21225         ViewParent viewParent = mParent;
21226         while (viewParent instanceof View) {
21227             final View view = (View) viewParent;
21228
21229             position[0] -= view.mScrollX;
21230             position[1] -= view.mScrollY;
21231
21232             if (!view.hasIdentityMatrix()) {
21233                 view.getMatrix().mapPoints(position);
21234             }
21235
21236             position[0] += view.mLeft;
21237             position[1] += view.mTop;
21238
21239             viewParent = view.mParent;
21240          }
21241
21242         if (viewParent instanceof ViewRootImpl) {
21243             // *cough*
21244             final ViewRootImpl vr = (ViewRootImpl) viewParent;
21245             position[1] -= vr.mCurScrollY;
21246         }
21247
21248         inOutLocation[0] = Math.round(position[0]);
21249         inOutLocation[1] = Math.round(position[1]);
21250     }
21251
21252     /**
21253      * @param id the id of the view to be found
21254      * @return the view of the specified id, null if cannot be found
21255      * @hide
21256      */
21257     protected <T extends View> T findViewTraversal(@IdRes int id) {
21258         if (id == mID) {
21259             return (T) this;
21260         }
21261         return null;
21262     }
21263
21264     /**
21265      * @param tag the tag of the view to be found
21266      * @return the view of specified tag, null if cannot be found
21267      * @hide
21268      */
21269     protected <T extends View> T findViewWithTagTraversal(Object tag) {
21270         if (tag != null && tag.equals(mTag)) {
21271             return (T) this;
21272         }
21273         return null;
21274     }
21275
21276     /**
21277      * @param predicate The predicate to evaluate.
21278      * @param childToSkip If not null, ignores this child during the recursive traversal.
21279      * @return The first view that matches the predicate or null.
21280      * @hide
21281      */
21282     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21283             View childToSkip) {
21284         if (predicate.test(this)) {
21285             return (T) this;
21286         }
21287         return null;
21288     }
21289
21290     /**
21291      * Finds the first descendant view with the given ID, the view itself if
21292      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21293      * (< 0) or there is no matching view in the hierarchy.
21294      * <p>
21295      * <strong>Note:</strong> In most cases -- depending on compiler support --
21296      * the resulting view is automatically cast to the target class type. If
21297      * the target class type is unconstrained, an explicit cast may be
21298      * necessary.
21299      *
21300      * @param id the ID to search for
21301      * @return a view with given ID if found, or {@code null} otherwise
21302      * @see View#findViewById(int)
21303      */
21304     @Nullable
21305     public final <T extends View> T findViewById(@IdRes int id) {
21306         if (id == NO_ID) {
21307             return null;
21308         }
21309         return findViewTraversal(id);
21310     }
21311
21312     /**
21313      * Finds a view by its unuque and stable accessibility id.
21314      *
21315      * @param accessibilityId The searched accessibility id.
21316      * @return The found view.
21317      */
21318     final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
21319         if (accessibilityId < 0) {
21320             return null;
21321         }
21322         T view = findViewByAccessibilityIdTraversal(accessibilityId);
21323         if (view != null) {
21324             return view.includeForAccessibility() ? view : null;
21325         }
21326         return null;
21327     }
21328
21329     /**
21330      * Performs the traversal to find a view by its unuque and stable accessibility id.
21331      *
21332      * <strong>Note:</strong>This method does not stop at the root namespace
21333      * boundary since the user can touch the screen at an arbitrary location
21334      * potentially crossing the root namespace bounday which will send an
21335      * accessibility event to accessibility services and they should be able
21336      * to obtain the event source. Also accessibility ids are guaranteed to be
21337      * unique in the window.
21338      *
21339      * @param accessibilityId The accessibility id.
21340      * @return The found view.
21341      * @hide
21342      */
21343     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21344         if (getAccessibilityViewId() == accessibilityId) {
21345             return (T) this;
21346         }
21347         return null;
21348     }
21349
21350     /**
21351      * Look for a child view with the given tag.  If this view has the given
21352      * tag, return this view.
21353      *
21354      * @param tag The tag to search for, using "tag.equals(getTag())".
21355      * @return The View that has the given tag in the hierarchy or null
21356      */
21357     public final <T extends View> T findViewWithTag(Object tag) {
21358         if (tag == null) {
21359             return null;
21360         }
21361         return findViewWithTagTraversal(tag);
21362     }
21363
21364     /**
21365      * Look for a child view that matches the specified predicate.
21366      * If this view matches the predicate, return this view.
21367      *
21368      * @param predicate The predicate to evaluate.
21369      * @return The first view that matches the predicate or null.
21370      * @hide
21371      */
21372     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21373         return findViewByPredicateTraversal(predicate, null);
21374     }
21375
21376     /**
21377      * Look for a child view that matches the specified predicate,
21378      * starting with the specified view and its descendents and then
21379      * recusively searching the ancestors and siblings of that view
21380      * until this view is reached.
21381      *
21382      * This method is useful in cases where the predicate does not match
21383      * a single unique view (perhaps multiple views use the same id)
21384      * and we are trying to find the view that is "closest" in scope to the
21385      * starting view.
21386      *
21387      * @param start The view to start from.
21388      * @param predicate The predicate to evaluate.
21389      * @return The first view that matches the predicate or null.
21390      * @hide
21391      */
21392     public final <T extends View> T findViewByPredicateInsideOut(
21393             View start, Predicate<View> predicate) {
21394         View childToSkip = null;
21395         for (;;) {
21396             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21397             if (view != null || start == this) {
21398                 return view;
21399             }
21400
21401             ViewParent parent = start.getParent();
21402             if (parent == null || !(parent instanceof View)) {
21403                 return null;
21404             }
21405
21406             childToSkip = start;
21407             start = (View) parent;
21408         }
21409     }
21410
21411     /**
21412      * Sets the identifier for this view. The identifier does not have to be
21413      * unique in this view's hierarchy. The identifier should be a positive
21414      * number.
21415      *
21416      * @see #NO_ID
21417      * @see #getId()
21418      * @see #findViewById(int)
21419      *
21420      * @param id a number used to identify the view
21421      *
21422      * @attr ref android.R.styleable#View_id
21423      */
21424     public void setId(@IdRes int id) {
21425         mID = id;
21426         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21427             mID = generateViewId();
21428         }
21429     }
21430
21431     /**
21432      * {@hide}
21433      *
21434      * @param isRoot true if the view belongs to the root namespace, false
21435      *        otherwise
21436      */
21437     public void setIsRootNamespace(boolean isRoot) {
21438         if (isRoot) {
21439             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21440         } else {
21441             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21442         }
21443     }
21444
21445     /**
21446      * {@hide}
21447      *
21448      * @return true if the view belongs to the root namespace, false otherwise
21449      */
21450     public boolean isRootNamespace() {
21451         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21452     }
21453
21454     /**
21455      * Returns this view's identifier.
21456      *
21457      * @return a positive integer used to identify the view or {@link #NO_ID}
21458      *         if the view has no ID
21459      *
21460      * @see #setId(int)
21461      * @see #findViewById(int)
21462      * @attr ref android.R.styleable#View_id
21463      */
21464     @IdRes
21465     @ViewDebug.CapturedViewProperty
21466     public int getId() {
21467         return mID;
21468     }
21469
21470     /**
21471      * Returns this view's tag.
21472      *
21473      * @return the Object stored in this view as a tag, or {@code null} if not
21474      *         set
21475      *
21476      * @see #setTag(Object)
21477      * @see #getTag(int)
21478      */
21479     @ViewDebug.ExportedProperty
21480     public Object getTag() {
21481         return mTag;
21482     }
21483
21484     /**
21485      * Sets the tag associated with this view. A tag can be used to mark
21486      * a view in its hierarchy and does not have to be unique within the
21487      * hierarchy. Tags can also be used to store data within a view without
21488      * resorting to another data structure.
21489      *
21490      * @param tag an Object to tag the view with
21491      *
21492      * @see #getTag()
21493      * @see #setTag(int, Object)
21494      */
21495     public void setTag(final Object tag) {
21496         mTag = tag;
21497     }
21498
21499     /**
21500      * Returns the tag associated with this view and the specified key.
21501      *
21502      * @param key The key identifying the tag
21503      *
21504      * @return the Object stored in this view as a tag, or {@code null} if not
21505      *         set
21506      *
21507      * @see #setTag(int, Object)
21508      * @see #getTag()
21509      */
21510     public Object getTag(int key) {
21511         if (mKeyedTags != null) return mKeyedTags.get(key);
21512         return null;
21513     }
21514
21515     /**
21516      * Sets a tag associated with this view and a key. A tag can be used
21517      * to mark a view in its hierarchy and does not have to be unique within
21518      * the hierarchy. Tags can also be used to store data within a view
21519      * without resorting to another data structure.
21520      *
21521      * The specified key should be an id declared in the resources of the
21522      * application to ensure it is unique (see the <a
21523      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21524      * Keys identified as belonging to
21525      * the Android framework or not associated with any package will cause
21526      * an {@link IllegalArgumentException} to be thrown.
21527      *
21528      * @param key The key identifying the tag
21529      * @param tag An Object to tag the view with
21530      *
21531      * @throws IllegalArgumentException If they specified key is not valid
21532      *
21533      * @see #setTag(Object)
21534      * @see #getTag(int)
21535      */
21536     public void setTag(int key, final Object tag) {
21537         // If the package id is 0x00 or 0x01, it's either an undefined package
21538         // or a framework id
21539         if ((key >>> 24) < 2) {
21540             throw new IllegalArgumentException("The key must be an application-specific "
21541                     + "resource id.");
21542         }
21543
21544         setKeyedTag(key, tag);
21545     }
21546
21547     /**
21548      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21549      * framework id.
21550      *
21551      * @hide
21552      */
21553     public void setTagInternal(int key, Object tag) {
21554         if ((key >>> 24) != 0x1) {
21555             throw new IllegalArgumentException("The key must be a framework-specific "
21556                     + "resource id.");
21557         }
21558
21559         setKeyedTag(key, tag);
21560     }
21561
21562     private void setKeyedTag(int key, Object tag) {
21563         if (mKeyedTags == null) {
21564             mKeyedTags = new SparseArray<Object>(2);
21565         }
21566
21567         mKeyedTags.put(key, tag);
21568     }
21569
21570     /**
21571      * Prints information about this view in the log output, with the tag
21572      * {@link #VIEW_LOG_TAG}.
21573      *
21574      * @hide
21575      */
21576     public void debug() {
21577         debug(0);
21578     }
21579
21580     /**
21581      * Prints information about this view in the log output, with the tag
21582      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21583      * indentation defined by the <code>depth</code>.
21584      *
21585      * @param depth the indentation level
21586      *
21587      * @hide
21588      */
21589     protected void debug(int depth) {
21590         String output = debugIndent(depth - 1);
21591
21592         output += "+ " + this;
21593         int id = getId();
21594         if (id != -1) {
21595             output += " (id=" + id + ")";
21596         }
21597         Object tag = getTag();
21598         if (tag != null) {
21599             output += " (tag=" + tag + ")";
21600         }
21601         Log.d(VIEW_LOG_TAG, output);
21602
21603         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21604             output = debugIndent(depth) + " FOCUSED";
21605             Log.d(VIEW_LOG_TAG, output);
21606         }
21607
21608         output = debugIndent(depth);
21609         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21610                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21611                 + "} ";
21612         Log.d(VIEW_LOG_TAG, output);
21613
21614         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21615                 || mPaddingBottom != 0) {
21616             output = debugIndent(depth);
21617             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21618                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21619             Log.d(VIEW_LOG_TAG, output);
21620         }
21621
21622         output = debugIndent(depth);
21623         output += "mMeasureWidth=" + mMeasuredWidth +
21624                 " mMeasureHeight=" + mMeasuredHeight;
21625         Log.d(VIEW_LOG_TAG, output);
21626
21627         output = debugIndent(depth);
21628         if (mLayoutParams == null) {
21629             output += "BAD! no layout params";
21630         } else {
21631             output = mLayoutParams.debug(output);
21632         }
21633         Log.d(VIEW_LOG_TAG, output);
21634
21635         output = debugIndent(depth);
21636         output += "flags={";
21637         output += View.printFlags(mViewFlags);
21638         output += "}";
21639         Log.d(VIEW_LOG_TAG, output);
21640
21641         output = debugIndent(depth);
21642         output += "privateFlags={";
21643         output += View.printPrivateFlags(mPrivateFlags);
21644         output += "}";
21645         Log.d(VIEW_LOG_TAG, output);
21646     }
21647
21648     /**
21649      * Creates a string of whitespaces used for indentation.
21650      *
21651      * @param depth the indentation level
21652      * @return a String containing (depth * 2 + 3) * 2 white spaces
21653      *
21654      * @hide
21655      */
21656     protected static String debugIndent(int depth) {
21657         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21658         for (int i = 0; i < (depth * 2) + 3; i++) {
21659             spaces.append(' ').append(' ');
21660         }
21661         return spaces.toString();
21662     }
21663
21664     /**
21665      * <p>Return the offset of the widget's text baseline from the widget's top
21666      * boundary. If this widget does not support baseline alignment, this
21667      * method returns -1. </p>
21668      *
21669      * @return the offset of the baseline within the widget's bounds or -1
21670      *         if baseline alignment is not supported
21671      */
21672     @ViewDebug.ExportedProperty(category = "layout")
21673     public int getBaseline() {
21674         return -1;
21675     }
21676
21677     /**
21678      * Returns whether the view hierarchy is currently undergoing a layout pass. This
21679      * information is useful to avoid situations such as calling {@link #requestLayout()} during
21680      * a layout pass.
21681      *
21682      * @return whether the view hierarchy is currently undergoing a layout pass
21683      */
21684     public boolean isInLayout() {
21685         ViewRootImpl viewRoot = getViewRootImpl();
21686         return (viewRoot != null && viewRoot.isInLayout());
21687     }
21688
21689     /**
21690      * Call this when something has changed which has invalidated the
21691      * layout of this view. This will schedule a layout pass of the view
21692      * tree. This should not be called while the view hierarchy is currently in a layout
21693      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21694      * end of the current layout pass (and then layout will run again) or after the current
21695      * frame is drawn and the next layout occurs.
21696      *
21697      * <p>Subclasses which override this method should call the superclass method to
21698      * handle possible request-during-layout errors correctly.</p>
21699      */
21700     @CallSuper
21701     public void requestLayout() {
21702         if (mMeasureCache != null) mMeasureCache.clear();
21703
21704         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21705             // Only trigger request-during-layout logic if this is the view requesting it,
21706             // not the views in its parent hierarchy
21707             ViewRootImpl viewRoot = getViewRootImpl();
21708             if (viewRoot != null && viewRoot.isInLayout()) {
21709                 if (!viewRoot.requestLayoutDuringLayout(this)) {
21710                     return;
21711                 }
21712             }
21713             mAttachInfo.mViewRequestingLayout = this;
21714         }
21715
21716         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21717         mPrivateFlags |= PFLAG_INVALIDATED;
21718
21719         if (mParent != null && !mParent.isLayoutRequested()) {
21720             mParent.requestLayout();
21721         }
21722         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21723             mAttachInfo.mViewRequestingLayout = null;
21724         }
21725     }
21726
21727     /**
21728      * Forces this view to be laid out during the next layout pass.
21729      * This method does not call requestLayout() or forceLayout()
21730      * on the parent.
21731      */
21732     public void forceLayout() {
21733         if (mMeasureCache != null) mMeasureCache.clear();
21734
21735         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21736         mPrivateFlags |= PFLAG_INVALIDATED;
21737     }
21738
21739     /**
21740      * <p>
21741      * This is called to find out how big a view should be. The parent
21742      * supplies constraint information in the width and height parameters.
21743      * </p>
21744      *
21745      * <p>
21746      * The actual measurement work of a view is performed in
21747      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21748      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21749      * </p>
21750      *
21751      *
21752      * @param widthMeasureSpec Horizontal space requirements as imposed by the
21753      *        parent
21754      * @param heightMeasureSpec Vertical space requirements as imposed by the
21755      *        parent
21756      *
21757      * @see #onMeasure(int, int)
21758      */
21759     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21760         boolean optical = isLayoutModeOptical(this);
21761         if (optical != isLayoutModeOptical(mParent)) {
21762             Insets insets = getOpticalInsets();
21763             int oWidth  = insets.left + insets.right;
21764             int oHeight = insets.top  + insets.bottom;
21765             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21766             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21767         }
21768
21769         // Suppress sign extension for the low bytes
21770         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21771         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21772
21773         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21774
21775         // Optimize layout by avoiding an extra EXACTLY pass when the view is
21776         // already measured as the correct size. In API 23 and below, this
21777         // extra pass is required to make LinearLayout re-distribute weight.
21778         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21779                 || heightMeasureSpec != mOldHeightMeasureSpec;
21780         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21781                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21782         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21783                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21784         final boolean needsLayout = specChanged
21785                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21786
21787         if (forceLayout || needsLayout) {
21788             // first clears the measured dimension flag
21789             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21790
21791             resolveRtlPropertiesIfNeeded();
21792
21793             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21794             if (cacheIndex < 0 || sIgnoreMeasureCache) {
21795                 // measure ourselves, this should set the measured dimension flag back
21796                 onMeasure(widthMeasureSpec, heightMeasureSpec);
21797                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21798             } else {
21799                 long value = mMeasureCache.valueAt(cacheIndex);
21800                 // Casting a long to int drops the high 32 bits, no mask needed
21801                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21802                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21803             }
21804
21805             // flag not set, setMeasuredDimension() was not invoked, we raise
21806             // an exception to warn the developer
21807             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21808                 throw new IllegalStateException("View with id " + getId() + ": "
21809                         + getClass().getName() + "#onMeasure() did not set the"
21810                         + " measured dimension by calling"
21811                         + " setMeasuredDimension()");
21812             }
21813
21814             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21815         }
21816
21817         mOldWidthMeasureSpec = widthMeasureSpec;
21818         mOldHeightMeasureSpec = heightMeasureSpec;
21819
21820         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21821                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21822     }
21823
21824     /**
21825      * <p>
21826      * Measure the view and its content to determine the measured width and the
21827      * measured height. This method is invoked by {@link #measure(int, int)} and
21828      * should be overridden by subclasses to provide accurate and efficient
21829      * measurement of their contents.
21830      * </p>
21831      *
21832      * <p>
21833      * <strong>CONTRACT:</strong> When overriding this method, you
21834      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21835      * measured width and height of this view. Failure to do so will trigger an
21836      * <code>IllegalStateException</code>, thrown by
21837      * {@link #measure(int, int)}. Calling the superclass'
21838      * {@link #onMeasure(int, int)} is a valid use.
21839      * </p>
21840      *
21841      * <p>
21842      * The base class implementation of measure defaults to the background size,
21843      * unless a larger size is allowed by the MeasureSpec. Subclasses should
21844      * override {@link #onMeasure(int, int)} to provide better measurements of
21845      * their content.
21846      * </p>
21847      *
21848      * <p>
21849      * If this method is overridden, it is the subclass's responsibility to make
21850      * sure the measured height and width are at least the view's minimum height
21851      * and width ({@link #getSuggestedMinimumHeight()} and
21852      * {@link #getSuggestedMinimumWidth()}).
21853      * </p>
21854      *
21855      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21856      *                         The requirements are encoded with
21857      *                         {@link android.view.View.MeasureSpec}.
21858      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21859      *                         The requirements are encoded with
21860      *                         {@link android.view.View.MeasureSpec}.
21861      *
21862      * @see #getMeasuredWidth()
21863      * @see #getMeasuredHeight()
21864      * @see #setMeasuredDimension(int, int)
21865      * @see #getSuggestedMinimumHeight()
21866      * @see #getSuggestedMinimumWidth()
21867      * @see android.view.View.MeasureSpec#getMode(int)
21868      * @see android.view.View.MeasureSpec#getSize(int)
21869      */
21870     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21871         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21872                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21873     }
21874
21875     /**
21876      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21877      * measured width and measured height. Failing to do so will trigger an
21878      * exception at measurement time.</p>
21879      *
21880      * @param measuredWidth The measured width of this view.  May be a complex
21881      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21882      * {@link #MEASURED_STATE_TOO_SMALL}.
21883      * @param measuredHeight The measured height of this view.  May be a complex
21884      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21885      * {@link #MEASURED_STATE_TOO_SMALL}.
21886      */
21887     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21888         boolean optical = isLayoutModeOptical(this);
21889         if (optical != isLayoutModeOptical(mParent)) {
21890             Insets insets = getOpticalInsets();
21891             int opticalWidth  = insets.left + insets.right;
21892             int opticalHeight = insets.top  + insets.bottom;
21893
21894             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21895             measuredHeight += optical ? opticalHeight : -opticalHeight;
21896         }
21897         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21898     }
21899
21900     /**
21901      * Sets the measured dimension without extra processing for things like optical bounds.
21902      * Useful for reapplying consistent values that have already been cooked with adjustments
21903      * for optical bounds, etc. such as those from the measurement cache.
21904      *
21905      * @param measuredWidth The measured width of this view.  May be a complex
21906      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21907      * {@link #MEASURED_STATE_TOO_SMALL}.
21908      * @param measuredHeight The measured height of this view.  May be a complex
21909      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21910      * {@link #MEASURED_STATE_TOO_SMALL}.
21911      */
21912     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21913         mMeasuredWidth = measuredWidth;
21914         mMeasuredHeight = measuredHeight;
21915
21916         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21917     }
21918
21919     /**
21920      * Merge two states as returned by {@link #getMeasuredState()}.
21921      * @param curState The current state as returned from a view or the result
21922      * of combining multiple views.
21923      * @param newState The new view state to combine.
21924      * @return Returns a new integer reflecting the combination of the two
21925      * states.
21926      */
21927     public static int combineMeasuredStates(int curState, int newState) {
21928         return curState | newState;
21929     }
21930
21931     /**
21932      * Version of {@link #resolveSizeAndState(int, int, int)}
21933      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21934      */
21935     public static int resolveSize(int size, int measureSpec) {
21936         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21937     }
21938
21939     /**
21940      * Utility to reconcile a desired size and state, with constraints imposed
21941      * by a MeasureSpec. Will take the desired size, unless a different size
21942      * is imposed by the constraints. The returned value is a compound integer,
21943      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21944      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21945      * resulting size is smaller than the size the view wants to be.
21946      *
21947      * @param size How big the view wants to be.
21948      * @param measureSpec Constraints imposed by the parent.
21949      * @param childMeasuredState Size information bit mask for the view's
21950      *                           children.
21951      * @return Size information bit mask as defined by
21952      *         {@link #MEASURED_SIZE_MASK} and
21953      *         {@link #MEASURED_STATE_TOO_SMALL}.
21954      */
21955     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21956         final int specMode = MeasureSpec.getMode(measureSpec);
21957         final int specSize = MeasureSpec.getSize(measureSpec);
21958         final int result;
21959         switch (specMode) {
21960             case MeasureSpec.AT_MOST:
21961                 if (specSize < size) {
21962                     result = specSize | MEASURED_STATE_TOO_SMALL;
21963                 } else {
21964                     result = size;
21965                 }
21966                 break;
21967             case MeasureSpec.EXACTLY:
21968                 result = specSize;
21969                 break;
21970             case MeasureSpec.UNSPECIFIED:
21971             default:
21972                 result = size;
21973         }
21974         return result | (childMeasuredState & MEASURED_STATE_MASK);
21975     }
21976
21977     /**
21978      * Utility to return a default size. Uses the supplied size if the
21979      * MeasureSpec imposed no constraints. Will get larger if allowed
21980      * by the MeasureSpec.
21981      *
21982      * @param size Default size for this view
21983      * @param measureSpec Constraints imposed by the parent
21984      * @return The size this view should be.
21985      */
21986     public static int getDefaultSize(int size, int measureSpec) {
21987         int result = size;
21988         int specMode = MeasureSpec.getMode(measureSpec);
21989         int specSize = MeasureSpec.getSize(measureSpec);
21990
21991         switch (specMode) {
21992         case MeasureSpec.UNSPECIFIED:
21993             result = size;
21994             break;
21995         case MeasureSpec.AT_MOST:
21996         case MeasureSpec.EXACTLY:
21997             result = specSize;
21998             break;
21999         }
22000         return result;
22001     }
22002
22003     /**
22004      * Returns the suggested minimum height that the view should use. This
22005      * returns the maximum of the view's minimum height
22006      * and the background's minimum height
22007      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
22008      * <p>
22009      * When being used in {@link #onMeasure(int, int)}, the caller should still
22010      * ensure the returned height is within the requirements of the parent.
22011      *
22012      * @return The suggested minimum height of the view.
22013      */
22014     protected int getSuggestedMinimumHeight() {
22015         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
22016
22017     }
22018
22019     /**
22020      * Returns the suggested minimum width that the view should use. This
22021      * returns the maximum of the view's minimum width
22022      * and the background's minimum width
22023      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
22024      * <p>
22025      * When being used in {@link #onMeasure(int, int)}, the caller should still
22026      * ensure the returned width is within the requirements of the parent.
22027      *
22028      * @return The suggested minimum width of the view.
22029      */
22030     protected int getSuggestedMinimumWidth() {
22031         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
22032     }
22033
22034     /**
22035      * Returns the minimum height of the view.
22036      *
22037      * @return the minimum height the view will try to be, in pixels
22038      *
22039      * @see #setMinimumHeight(int)
22040      *
22041      * @attr ref android.R.styleable#View_minHeight
22042      */
22043     public int getMinimumHeight() {
22044         return mMinHeight;
22045     }
22046
22047     /**
22048      * Sets the minimum height of the view. It is not guaranteed the view will
22049      * be able to achieve this minimum height (for example, if its parent layout
22050      * constrains it with less available height).
22051      *
22052      * @param minHeight The minimum height the view will try to be, in pixels
22053      *
22054      * @see #getMinimumHeight()
22055      *
22056      * @attr ref android.R.styleable#View_minHeight
22057      */
22058     @RemotableViewMethod
22059     public void setMinimumHeight(int minHeight) {
22060         mMinHeight = minHeight;
22061         requestLayout();
22062     }
22063
22064     /**
22065      * Returns the minimum width of the view.
22066      *
22067      * @return the minimum width the view will try to be, in pixels
22068      *
22069      * @see #setMinimumWidth(int)
22070      *
22071      * @attr ref android.R.styleable#View_minWidth
22072      */
22073     public int getMinimumWidth() {
22074         return mMinWidth;
22075     }
22076
22077     /**
22078      * Sets the minimum width of the view. It is not guaranteed the view will
22079      * be able to achieve this minimum width (for example, if its parent layout
22080      * constrains it with less available width).
22081      *
22082      * @param minWidth The minimum width the view will try to be, in pixels
22083      *
22084      * @see #getMinimumWidth()
22085      *
22086      * @attr ref android.R.styleable#View_minWidth
22087      */
22088     public void setMinimumWidth(int minWidth) {
22089         mMinWidth = minWidth;
22090         requestLayout();
22091
22092     }
22093
22094     /**
22095      * Get the animation currently associated with this view.
22096      *
22097      * @return The animation that is currently playing or
22098      *         scheduled to play for this view.
22099      */
22100     public Animation getAnimation() {
22101         return mCurrentAnimation;
22102     }
22103
22104     /**
22105      * Start the specified animation now.
22106      *
22107      * @param animation the animation to start now
22108      */
22109     public void startAnimation(Animation animation) {
22110         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
22111         setAnimation(animation);
22112         invalidateParentCaches();
22113         invalidate(true);
22114     }
22115
22116     /**
22117      * Cancels any animations for this view.
22118      */
22119     public void clearAnimation() {
22120         if (mCurrentAnimation != null) {
22121             mCurrentAnimation.detach();
22122         }
22123         mCurrentAnimation = null;
22124         invalidateParentIfNeeded();
22125     }
22126
22127     /**
22128      * Sets the next animation to play for this view.
22129      * If you want the animation to play immediately, use
22130      * {@link #startAnimation(android.view.animation.Animation)} instead.
22131      * This method provides allows fine-grained
22132      * control over the start time and invalidation, but you
22133      * must make sure that 1) the animation has a start time set, and
22134      * 2) the view's parent (which controls animations on its children)
22135      * will be invalidated when the animation is supposed to
22136      * start.
22137      *
22138      * @param animation The next animation, or null.
22139      */
22140     public void setAnimation(Animation animation) {
22141         mCurrentAnimation = animation;
22142
22143         if (animation != null) {
22144             // If the screen is off assume the animation start time is now instead of
22145             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
22146             // would cause the animation to start when the screen turns back on
22147             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
22148                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
22149                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
22150             }
22151             animation.reset();
22152         }
22153     }
22154
22155     /**
22156      * Invoked by a parent ViewGroup to notify the start of the animation
22157      * currently associated with this view. If you override this method,
22158      * always call super.onAnimationStart();
22159      *
22160      * @see #setAnimation(android.view.animation.Animation)
22161      * @see #getAnimation()
22162      */
22163     @CallSuper
22164     protected void onAnimationStart() {
22165         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
22166     }
22167
22168     /**
22169      * Invoked by a parent ViewGroup to notify the end of the animation
22170      * currently associated with this view. If you override this method,
22171      * always call super.onAnimationEnd();
22172      *
22173      * @see #setAnimation(android.view.animation.Animation)
22174      * @see #getAnimation()
22175      */
22176     @CallSuper
22177     protected void onAnimationEnd() {
22178         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
22179     }
22180
22181     /**
22182      * Invoked if there is a Transform that involves alpha. Subclass that can
22183      * draw themselves with the specified alpha should return true, and then
22184      * respect that alpha when their onDraw() is called. If this returns false
22185      * then the view may be redirected to draw into an offscreen buffer to
22186      * fulfill the request, which will look fine, but may be slower than if the
22187      * subclass handles it internally. The default implementation returns false.
22188      *
22189      * @param alpha The alpha (0..255) to apply to the view's drawing
22190      * @return true if the view can draw with the specified alpha.
22191      */
22192     protected boolean onSetAlpha(int alpha) {
22193         return false;
22194     }
22195
22196     /**
22197      * This is used by the RootView to perform an optimization when
22198      * the view hierarchy contains one or several SurfaceView.
22199      * SurfaceView is always considered transparent, but its children are not,
22200      * therefore all View objects remove themselves from the global transparent
22201      * region (passed as a parameter to this function).
22202      *
22203      * @param region The transparent region for this ViewAncestor (window).
22204      *
22205      * @return Returns true if the effective visibility of the view at this
22206      * point is opaque, regardless of the transparent region; returns false
22207      * if it is possible for underlying windows to be seen behind the view.
22208      *
22209      * {@hide}
22210      */
22211     public boolean gatherTransparentRegion(Region region) {
22212         final AttachInfo attachInfo = mAttachInfo;
22213         if (region != null && attachInfo != null) {
22214             final int pflags = mPrivateFlags;
22215             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22216                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22217                 // remove it from the transparent region.
22218                 final int[] location = attachInfo.mTransparentLocation;
22219                 getLocationInWindow(location);
22220                 // When a view has Z value, then it will be better to leave some area below the view
22221                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22222                 // the bottom part needs more offset than the left, top and right parts due to the
22223                 // spot light effects.
22224                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22225                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22226                         location[0] + mRight - mLeft + shadowOffset,
22227                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22228             } else {
22229                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22230                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22231                     // the background drawable's non-transparent parts from this transparent region.
22232                     applyDrawableToTransparentRegion(mBackground, region);
22233                 }
22234                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22235                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22236                     // Similarly, we remove the foreground drawable's non-transparent parts.
22237                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22238                 }
22239                 if (mDefaultFocusHighlight != null
22240                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22241                     // Similarly, we remove the default focus highlight's non-transparent parts.
22242                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22243                 }
22244             }
22245         }
22246         return true;
22247     }
22248
22249     /**
22250      * Play a sound effect for this view.
22251      *
22252      * <p>The framework will play sound effects for some built in actions, such as
22253      * clicking, but you may wish to play these effects in your widget,
22254      * for instance, for internal navigation.
22255      *
22256      * <p>The sound effect will only be played if sound effects are enabled by the user, and
22257      * {@link #isSoundEffectsEnabled()} is true.
22258      *
22259      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22260      */
22261     public void playSoundEffect(int soundConstant) {
22262         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22263             return;
22264         }
22265         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22266     }
22267
22268     /**
22269      * BZZZTT!!1!
22270      *
22271      * <p>Provide haptic feedback to the user for this view.
22272      *
22273      * <p>The framework will provide haptic feedback for some built in actions,
22274      * such as long presses, but you may wish to provide feedback for your
22275      * own widget.
22276      *
22277      * <p>The feedback will only be performed if
22278      * {@link #isHapticFeedbackEnabled()} is true.
22279      *
22280      * @param feedbackConstant One of the constants defined in
22281      * {@link HapticFeedbackConstants}
22282      */
22283     public boolean performHapticFeedback(int feedbackConstant) {
22284         return performHapticFeedback(feedbackConstant, 0);
22285     }
22286
22287     /**
22288      * BZZZTT!!1!
22289      *
22290      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22291      *
22292      * @param feedbackConstant One of the constants defined in
22293      * {@link HapticFeedbackConstants}
22294      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22295      */
22296     public boolean performHapticFeedback(int feedbackConstant, int flags) {
22297         if (mAttachInfo == null) {
22298             return false;
22299         }
22300         //noinspection SimplifiableIfStatement
22301         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22302                 && !isHapticFeedbackEnabled()) {
22303             return false;
22304         }
22305         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22306                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22307     }
22308
22309     /**
22310      * Request that the visibility of the status bar or other screen/window
22311      * decorations be changed.
22312      *
22313      * <p>This method is used to put the over device UI into temporary modes
22314      * where the user's attention is focused more on the application content,
22315      * by dimming or hiding surrounding system affordances.  This is typically
22316      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22317      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22318      * to be placed behind the action bar (and with these flags other system
22319      * affordances) so that smooth transitions between hiding and showing them
22320      * can be done.
22321      *
22322      * <p>Two representative examples of the use of system UI visibility is
22323      * implementing a content browsing application (like a magazine reader)
22324      * and a video playing application.
22325      *
22326      * <p>The first code shows a typical implementation of a View in a content
22327      * browsing application.  In this implementation, the application goes
22328      * into a content-oriented mode by hiding the status bar and action bar,
22329      * and putting the navigation elements into lights out mode.  The user can
22330      * then interact with content while in this mode.  Such an application should
22331      * provide an easy way for the user to toggle out of the mode (such as to
22332      * check information in the status bar or access notifications).  In the
22333      * implementation here, this is done simply by tapping on the content.
22334      *
22335      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22336      *      content}
22337      *
22338      * <p>This second code sample shows a typical implementation of a View
22339      * in a video playing application.  In this situation, while the video is
22340      * playing the application would like to go into a complete full-screen mode,
22341      * to use as much of the display as possible for the video.  When in this state
22342      * the user can not interact with the application; the system intercepts
22343      * touching on the screen to pop the UI out of full screen mode.  See
22344      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22345      *
22346      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22347      *      content}
22348      *
22349      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22350      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22351      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22352      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22353      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22354      */
22355     public void setSystemUiVisibility(int visibility) {
22356         if (visibility != mSystemUiVisibility) {
22357             mSystemUiVisibility = visibility;
22358             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22359                 mParent.recomputeViewAttributes(this);
22360             }
22361         }
22362     }
22363
22364     /**
22365      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22366      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22367      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22368      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22369      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22370      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22371      */
22372     public int getSystemUiVisibility() {
22373         return mSystemUiVisibility;
22374     }
22375
22376     /**
22377      * Returns the current system UI visibility that is currently set for
22378      * the entire window.  This is the combination of the
22379      * {@link #setSystemUiVisibility(int)} values supplied by all of the
22380      * views in the window.
22381      */
22382     public int getWindowSystemUiVisibility() {
22383         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22384     }
22385
22386     /**
22387      * Override to find out when the window's requested system UI visibility
22388      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22389      * This is different from the callbacks received through
22390      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22391      * in that this is only telling you about the local request of the window,
22392      * not the actual values applied by the system.
22393      */
22394     public void onWindowSystemUiVisibilityChanged(int visible) {
22395     }
22396
22397     /**
22398      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22399      * the view hierarchy.
22400      */
22401     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22402         onWindowSystemUiVisibilityChanged(visible);
22403     }
22404
22405     /**
22406      * Set a listener to receive callbacks when the visibility of the system bar changes.
22407      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22408      */
22409     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22410         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22411         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22412             mParent.recomputeViewAttributes(this);
22413         }
22414     }
22415
22416     /**
22417      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22418      * the view hierarchy.
22419      */
22420     public void dispatchSystemUiVisibilityChanged(int visibility) {
22421         ListenerInfo li = mListenerInfo;
22422         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22423             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22424                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22425         }
22426     }
22427
22428     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22429         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22430         if (val != mSystemUiVisibility) {
22431             setSystemUiVisibility(val);
22432             return true;
22433         }
22434         return false;
22435     }
22436
22437     /** @hide */
22438     public void setDisabledSystemUiVisibility(int flags) {
22439         if (mAttachInfo != null) {
22440             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22441                 mAttachInfo.mDisabledSystemUiVisibility = flags;
22442                 if (mParent != null) {
22443                     mParent.recomputeViewAttributes(this);
22444                 }
22445             }
22446         }
22447     }
22448
22449     /**
22450      * Creates an image that the system displays during the drag and drop
22451      * operation. This is called a &quot;drag shadow&quot;. The default implementation
22452      * for a DragShadowBuilder based on a View returns an image that has exactly the same
22453      * appearance as the given View. The default also positions the center of the drag shadow
22454      * directly under the touch point. If no View is provided (the constructor with no parameters
22455      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22456      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22457      * default is an invisible drag shadow.
22458      * <p>
22459      * You are not required to use the View you provide to the constructor as the basis of the
22460      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22461      * anything you want as the drag shadow.
22462      * </p>
22463      * <p>
22464      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22465      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22466      *  size and position of the drag shadow. It uses this data to construct a
22467      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22468      *  so that your application can draw the shadow image in the Canvas.
22469      * </p>
22470      *
22471      * <div class="special reference">
22472      * <h3>Developer Guides</h3>
22473      * <p>For a guide to implementing drag and drop features, read the
22474      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22475      * </div>
22476      */
22477     public static class DragShadowBuilder {
22478         private final WeakReference<View> mView;
22479
22480         /**
22481          * Constructs a shadow image builder based on a View. By default, the resulting drag
22482          * shadow will have the same appearance and dimensions as the View, with the touch point
22483          * over the center of the View.
22484          * @param view A View. Any View in scope can be used.
22485          */
22486         public DragShadowBuilder(View view) {
22487             mView = new WeakReference<View>(view);
22488         }
22489
22490         /**
22491          * Construct a shadow builder object with no associated View.  This
22492          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22493          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22494          * to supply the drag shadow's dimensions and appearance without
22495          * reference to any View object. If they are not overridden, then the result is an
22496          * invisible drag shadow.
22497          */
22498         public DragShadowBuilder() {
22499             mView = new WeakReference<View>(null);
22500         }
22501
22502         /**
22503          * Returns the View object that had been passed to the
22504          * {@link #View.DragShadowBuilder(View)}
22505          * constructor.  If that View parameter was {@code null} or if the
22506          * {@link #View.DragShadowBuilder()}
22507          * constructor was used to instantiate the builder object, this method will return
22508          * null.
22509          *
22510          * @return The View object associate with this builder object.
22511          */
22512         @SuppressWarnings({"JavadocReference"})
22513         final public View getView() {
22514             return mView.get();
22515         }
22516
22517         /**
22518          * Provides the metrics for the shadow image. These include the dimensions of
22519          * the shadow image, and the point within that shadow that should
22520          * be centered under the touch location while dragging.
22521          * <p>
22522          * The default implementation sets the dimensions of the shadow to be the
22523          * same as the dimensions of the View itself and centers the shadow under
22524          * the touch point.
22525          * </p>
22526          *
22527          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22528          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22529          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22530          * image.
22531          *
22532          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22533          * shadow image that should be underneath the touch point during the drag and drop
22534          * operation. Your application must set {@link android.graphics.Point#x} to the
22535          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22536          */
22537         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22538             final View view = mView.get();
22539             if (view != null) {
22540                 outShadowSize.set(view.getWidth(), view.getHeight());
22541                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22542             } else {
22543                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22544             }
22545         }
22546
22547         /**
22548          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22549          * based on the dimensions it received from the
22550          * {@link #onProvideShadowMetrics(Point, Point)} callback.
22551          *
22552          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22553          */
22554         public void onDrawShadow(Canvas canvas) {
22555             final View view = mView.get();
22556             if (view != null) {
22557                 view.draw(canvas);
22558             } else {
22559                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22560             }
22561         }
22562     }
22563
22564     /**
22565      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22566      * startDragAndDrop()} for newer platform versions.
22567      */
22568     @Deprecated
22569     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22570                                    Object myLocalState, int flags) {
22571         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22572     }
22573
22574     /**
22575      * Starts a drag and drop operation. When your application calls this method, it passes a
22576      * {@link android.view.View.DragShadowBuilder} object to the system. The
22577      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22578      * to get metrics for the drag shadow, and then calls the object's
22579      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22580      * <p>
22581      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22582      *  drag events to all the View objects in your application that are currently visible. It does
22583      *  this either by calling the View object's drag listener (an implementation of
22584      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22585      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22586      *  Both are passed a {@link android.view.DragEvent} object that has a
22587      *  {@link android.view.DragEvent#getAction()} value of
22588      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22589      * </p>
22590      * <p>
22591      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22592      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22593      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22594      * to the View the user selected for dragging.
22595      * </p>
22596      * @param data A {@link android.content.ClipData} object pointing to the data to be
22597      * transferred by the drag and drop operation.
22598      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22599      * drag shadow.
22600      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22601      * drop operation. When dispatching drag events to views in the same activity this object
22602      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22603      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22604      * will return null).
22605      * <p>
22606      * myLocalState is a lightweight mechanism for the sending information from the dragged View
22607      * to the target Views. For example, it can contain flags that differentiate between a
22608      * a copy operation and a move operation.
22609      * </p>
22610      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22611      * flags, or any combination of the following:
22612      *     <ul>
22613      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22614      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22615      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22616      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22617      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22618      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22619      *     </ul>
22620      * @return {@code true} if the method completes successfully, or
22621      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22622      * do a drag, and so no drag operation is in progress.
22623      */
22624     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22625             Object myLocalState, int flags) {
22626         if (ViewDebug.DEBUG_DRAG) {
22627             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22628         }
22629         if (mAttachInfo == null) {
22630             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22631             return false;
22632         }
22633
22634         if (data != null) {
22635             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22636         }
22637
22638         boolean okay = false;
22639
22640         Point shadowSize = new Point();
22641         Point shadowTouchPoint = new Point();
22642         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22643
22644         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22645                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22646             throw new IllegalStateException("Drag shadow dimensions must not be negative");
22647         }
22648
22649         if (ViewDebug.DEBUG_DRAG) {
22650             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22651                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22652         }
22653         if (mAttachInfo.mDragSurface != null) {
22654             mAttachInfo.mDragSurface.release();
22655         }
22656         mAttachInfo.mDragSurface = new Surface();
22657         try {
22658             mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22659                     flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22660             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22661                     + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22662             if (mAttachInfo.mDragToken != null) {
22663                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22664                 try {
22665                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22666                     shadowBuilder.onDrawShadow(canvas);
22667                 } finally {
22668                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22669                 }
22670
22671                 final ViewRootImpl root = getViewRootImpl();
22672
22673                 // Cache the local state object for delivery with DragEvents
22674                 root.setLocalDragState(myLocalState);
22675
22676                 // repurpose 'shadowSize' for the last touch point
22677                 root.getLastTouchPoint(shadowSize);
22678
22679                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22680                         root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22681                         shadowTouchPoint.x, shadowTouchPoint.y, data);
22682                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22683             }
22684         } catch (Exception e) {
22685             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22686             mAttachInfo.mDragSurface.destroy();
22687             mAttachInfo.mDragSurface = null;
22688         }
22689
22690         return okay;
22691     }
22692
22693     /**
22694      * Cancels an ongoing drag and drop operation.
22695      * <p>
22696      * A {@link android.view.DragEvent} object with
22697      * {@link android.view.DragEvent#getAction()} value of
22698      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22699      * {@link android.view.DragEvent#getResult()} value of {@code false}
22700      * will be sent to every
22701      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22702      * even if they are not currently visible.
22703      * </p>
22704      * <p>
22705      * This method can be called on any View in the same window as the View on which
22706      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22707      * was called.
22708      * </p>
22709      */
22710     public final void cancelDragAndDrop() {
22711         if (ViewDebug.DEBUG_DRAG) {
22712             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22713         }
22714         if (mAttachInfo == null) {
22715             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22716             return;
22717         }
22718         if (mAttachInfo.mDragToken != null) {
22719             try {
22720                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22721             } catch (Exception e) {
22722                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22723             }
22724             mAttachInfo.mDragToken = null;
22725         } else {
22726             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22727         }
22728     }
22729
22730     /**
22731      * Updates the drag shadow for the ongoing drag and drop operation.
22732      *
22733      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22734      * new drag shadow.
22735      */
22736     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22737         if (ViewDebug.DEBUG_DRAG) {
22738             Log.d(VIEW_LOG_TAG, "updateDragShadow");
22739         }
22740         if (mAttachInfo == null) {
22741             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22742             return;
22743         }
22744         if (mAttachInfo.mDragToken != null) {
22745             try {
22746                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22747                 try {
22748                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22749                     shadowBuilder.onDrawShadow(canvas);
22750                 } finally {
22751                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22752                 }
22753             } catch (Exception e) {
22754                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22755             }
22756         } else {
22757             Log.e(VIEW_LOG_TAG, "No active drag");
22758         }
22759     }
22760
22761     /**
22762      * Starts a move from {startX, startY}, the amount of the movement will be the offset
22763      * between {startX, startY} and the new cursor positon.
22764      * @param startX horizontal coordinate where the move started.
22765      * @param startY vertical coordinate where the move started.
22766      * @return whether moving was started successfully.
22767      * @hide
22768      */
22769     public final boolean startMovingTask(float startX, float startY) {
22770         if (ViewDebug.DEBUG_POSITIONING) {
22771             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22772         }
22773         try {
22774             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22775         } catch (RemoteException e) {
22776             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22777         }
22778         return false;
22779     }
22780
22781     /**
22782      * Handles drag events sent by the system following a call to
22783      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22784      * startDragAndDrop()}.
22785      *<p>
22786      * When the system calls this method, it passes a
22787      * {@link android.view.DragEvent} object. A call to
22788      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22789      * in DragEvent. The method uses these to determine what is happening in the drag and drop
22790      * operation.
22791      * @param event The {@link android.view.DragEvent} sent by the system.
22792      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22793      * in DragEvent, indicating the type of drag event represented by this object.
22794      * @return {@code true} if the method was successful, otherwise {@code false}.
22795      * <p>
22796      *  The method should return {@code true} in response to an action type of
22797      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22798      *  operation.
22799      * </p>
22800      * <p>
22801      *  The method should also return {@code true} in response to an action type of
22802      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22803      *  {@code false} if it didn't.
22804      * </p>
22805      * <p>
22806      *  For all other events, the return value is ignored.
22807      * </p>
22808      */
22809     public boolean onDragEvent(DragEvent event) {
22810         return false;
22811     }
22812
22813     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22814     boolean dispatchDragEnterExitInPreN(DragEvent event) {
22815         return callDragEventHandler(event);
22816     }
22817
22818     /**
22819      * Detects if this View is enabled and has a drag event listener.
22820      * If both are true, then it calls the drag event listener with the
22821      * {@link android.view.DragEvent} it received. If the drag event listener returns
22822      * {@code true}, then dispatchDragEvent() returns {@code true}.
22823      * <p>
22824      * For all other cases, the method calls the
22825      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22826      * method and returns its result.
22827      * </p>
22828      * <p>
22829      * This ensures that a drag event is always consumed, even if the View does not have a drag
22830      * event listener. However, if the View has a listener and the listener returns true, then
22831      * onDragEvent() is not called.
22832      * </p>
22833      */
22834     public boolean dispatchDragEvent(DragEvent event) {
22835         event.mEventHandlerWasCalled = true;
22836         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22837             event.mAction == DragEvent.ACTION_DROP) {
22838             // About to deliver an event with coordinates to this view. Notify that now this view
22839             // has drag focus. This will send exit/enter events as needed.
22840             getViewRootImpl().setDragFocus(this, event);
22841         }
22842         return callDragEventHandler(event);
22843     }
22844
22845     final boolean callDragEventHandler(DragEvent event) {
22846         final boolean result;
22847
22848         ListenerInfo li = mListenerInfo;
22849         //noinspection SimplifiableIfStatement
22850         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22851                 && li.mOnDragListener.onDrag(this, event)) {
22852             result = true;
22853         } else {
22854             result = onDragEvent(event);
22855         }
22856
22857         switch (event.mAction) {
22858             case DragEvent.ACTION_DRAG_ENTERED: {
22859                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22860                 refreshDrawableState();
22861             } break;
22862             case DragEvent.ACTION_DRAG_EXITED: {
22863                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22864                 refreshDrawableState();
22865             } break;
22866             case DragEvent.ACTION_DRAG_ENDED: {
22867                 mPrivateFlags2 &= ~View.DRAG_MASK;
22868                 refreshDrawableState();
22869             } break;
22870         }
22871
22872         return result;
22873     }
22874
22875     boolean canAcceptDrag() {
22876         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22877     }
22878
22879     /**
22880      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22881      * it is ever exposed at all.
22882      * @hide
22883      */
22884     public void onCloseSystemDialogs(String reason) {
22885     }
22886
22887     /**
22888      * Given a Drawable whose bounds have been set to draw into this view,
22889      * update a Region being computed for
22890      * {@link #gatherTransparentRegion(android.graphics.Region)} so
22891      * that any non-transparent parts of the Drawable are removed from the
22892      * given transparent region.
22893      *
22894      * @param dr The Drawable whose transparency is to be applied to the region.
22895      * @param region A Region holding the current transparency information,
22896      * where any parts of the region that are set are considered to be
22897      * transparent.  On return, this region will be modified to have the
22898      * transparency information reduced by the corresponding parts of the
22899      * Drawable that are not transparent.
22900      * {@hide}
22901      */
22902     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22903         if (DBG) {
22904             Log.i("View", "Getting transparent region for: " + this);
22905         }
22906         final Region r = dr.getTransparentRegion();
22907         final Rect db = dr.getBounds();
22908         final AttachInfo attachInfo = mAttachInfo;
22909         if (r != null && attachInfo != null) {
22910             final int w = getRight()-getLeft();
22911             final int h = getBottom()-getTop();
22912             if (db.left > 0) {
22913                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22914                 r.op(0, 0, db.left, h, Region.Op.UNION);
22915             }
22916             if (db.right < w) {
22917                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22918                 r.op(db.right, 0, w, h, Region.Op.UNION);
22919             }
22920             if (db.top > 0) {
22921                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22922                 r.op(0, 0, w, db.top, Region.Op.UNION);
22923             }
22924             if (db.bottom < h) {
22925                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22926                 r.op(0, db.bottom, w, h, Region.Op.UNION);
22927             }
22928             final int[] location = attachInfo.mTransparentLocation;
22929             getLocationInWindow(location);
22930             r.translate(location[0], location[1]);
22931             region.op(r, Region.Op.INTERSECT);
22932         } else {
22933             region.op(db, Region.Op.DIFFERENCE);
22934         }
22935     }
22936
22937     private void checkForLongClick(int delayOffset, float x, float y) {
22938         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22939             mHasPerformedLongPress = false;
22940
22941             if (mPendingCheckForLongPress == null) {
22942                 mPendingCheckForLongPress = new CheckForLongPress();
22943             }
22944             mPendingCheckForLongPress.setAnchor(x, y);
22945             mPendingCheckForLongPress.rememberWindowAttachCount();
22946             mPendingCheckForLongPress.rememberPressedState();
22947             postDelayed(mPendingCheckForLongPress,
22948                     ViewConfiguration.getLongPressTimeout() - delayOffset);
22949         }
22950     }
22951
22952     /**
22953      * Inflate a view from an XML resource.  This convenience method wraps the {@link
22954      * LayoutInflater} class, which provides a full range of options for view inflation.
22955      *
22956      * @param context The Context object for your activity or application.
22957      * @param resource The resource ID to inflate
22958      * @param root A view group that will be the parent.  Used to properly inflate the
22959      * layout_* parameters.
22960      * @see LayoutInflater
22961      */
22962     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22963         LayoutInflater factory = LayoutInflater.from(context);
22964         return factory.inflate(resource, root);
22965     }
22966
22967     /**
22968      * Scroll the view with standard behavior for scrolling beyond the normal
22969      * content boundaries. Views that call this method should override
22970      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22971      * results of an over-scroll operation.
22972      *
22973      * Views can use this method to handle any touch or fling-based scrolling.
22974      *
22975      * @param deltaX Change in X in pixels
22976      * @param deltaY Change in Y in pixels
22977      * @param scrollX Current X scroll value in pixels before applying deltaX
22978      * @param scrollY Current Y scroll value in pixels before applying deltaY
22979      * @param scrollRangeX Maximum content scroll range along the X axis
22980      * @param scrollRangeY Maximum content scroll range along the Y axis
22981      * @param maxOverScrollX Number of pixels to overscroll by in either direction
22982      *          along the X axis.
22983      * @param maxOverScrollY Number of pixels to overscroll by in either direction
22984      *          along the Y axis.
22985      * @param isTouchEvent true if this scroll operation is the result of a touch event.
22986      * @return true if scrolling was clamped to an over-scroll boundary along either
22987      *          axis, false otherwise.
22988      */
22989     @SuppressWarnings({"UnusedParameters"})
22990     protected boolean overScrollBy(int deltaX, int deltaY,
22991             int scrollX, int scrollY,
22992             int scrollRangeX, int scrollRangeY,
22993             int maxOverScrollX, int maxOverScrollY,
22994             boolean isTouchEvent) {
22995         final int overScrollMode = mOverScrollMode;
22996         final boolean canScrollHorizontal =
22997                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22998         final boolean canScrollVertical =
22999                 computeVerticalScrollRange() > computeVerticalScrollExtent();
23000         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
23001                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
23002         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
23003                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
23004
23005         int newScrollX = scrollX + deltaX;
23006         if (!overScrollHorizontal) {
23007             maxOverScrollX = 0;
23008         }
23009
23010         int newScrollY = scrollY + deltaY;
23011         if (!overScrollVertical) {
23012             maxOverScrollY = 0;
23013         }
23014
23015         // Clamp values if at the limits and record
23016         final int left = -maxOverScrollX;
23017         final int right = maxOverScrollX + scrollRangeX;
23018         final int top = -maxOverScrollY;
23019         final int bottom = maxOverScrollY + scrollRangeY;
23020
23021         boolean clampedX = false;
23022         if (newScrollX > right) {
23023             newScrollX = right;
23024             clampedX = true;
23025         } else if (newScrollX < left) {
23026             newScrollX = left;
23027             clampedX = true;
23028         }
23029
23030         boolean clampedY = false;
23031         if (newScrollY > bottom) {
23032             newScrollY = bottom;
23033             clampedY = true;
23034         } else if (newScrollY < top) {
23035             newScrollY = top;
23036             clampedY = true;
23037         }
23038
23039         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
23040
23041         return clampedX || clampedY;
23042     }
23043
23044     /**
23045      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
23046      * respond to the results of an over-scroll operation.
23047      *
23048      * @param scrollX New X scroll value in pixels
23049      * @param scrollY New Y scroll value in pixels
23050      * @param clampedX True if scrollX was clamped to an over-scroll boundary
23051      * @param clampedY True if scrollY was clamped to an over-scroll boundary
23052      */
23053     protected void onOverScrolled(int scrollX, int scrollY,
23054             boolean clampedX, boolean clampedY) {
23055         // Intentionally empty.
23056     }
23057
23058     /**
23059      * Returns the over-scroll mode for this view. The result will be
23060      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23061      * (allow over-scrolling only if the view content is larger than the container),
23062      * or {@link #OVER_SCROLL_NEVER}.
23063      *
23064      * @return This view's over-scroll mode.
23065      */
23066     public int getOverScrollMode() {
23067         return mOverScrollMode;
23068     }
23069
23070     /**
23071      * Set the over-scroll mode for this view. Valid over-scroll modes are
23072      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23073      * (allow over-scrolling only if the view content is larger than the container),
23074      * or {@link #OVER_SCROLL_NEVER}.
23075      *
23076      * Setting the over-scroll mode of a view will have an effect only if the
23077      * view is capable of scrolling.
23078      *
23079      * @param overScrollMode The new over-scroll mode for this view.
23080      */
23081     public void setOverScrollMode(int overScrollMode) {
23082         if (overScrollMode != OVER_SCROLL_ALWAYS &&
23083                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
23084                 overScrollMode != OVER_SCROLL_NEVER) {
23085             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
23086         }
23087         mOverScrollMode = overScrollMode;
23088     }
23089
23090     /**
23091      * Enable or disable nested scrolling for this view.
23092      *
23093      * <p>If this property is set to true the view will be permitted to initiate nested
23094      * scrolling operations with a compatible parent view in the current hierarchy. If this
23095      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
23096      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
23097      * the nested scroll.</p>
23098      *
23099      * @param enabled true to enable nested scrolling, false to disable
23100      *
23101      * @see #isNestedScrollingEnabled()
23102      */
23103     public void setNestedScrollingEnabled(boolean enabled) {
23104         if (enabled) {
23105             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
23106         } else {
23107             stopNestedScroll();
23108             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
23109         }
23110     }
23111
23112     /**
23113      * Returns true if nested scrolling is enabled for this view.
23114      *
23115      * <p>If nested scrolling is enabled and this View class implementation supports it,
23116      * this view will act as a nested scrolling child view when applicable, forwarding data
23117      * about the scroll operation in progress to a compatible and cooperating nested scrolling
23118      * parent.</p>
23119      *
23120      * @return true if nested scrolling is enabled
23121      *
23122      * @see #setNestedScrollingEnabled(boolean)
23123      */
23124     public boolean isNestedScrollingEnabled() {
23125         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
23126                 PFLAG3_NESTED_SCROLLING_ENABLED;
23127     }
23128
23129     /**
23130      * Begin a nestable scroll operation along the given axes.
23131      *
23132      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
23133      *
23134      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
23135      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
23136      * In the case of touch scrolling the nested scroll will be terminated automatically in
23137      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
23138      * In the event of programmatic scrolling the caller must explicitly call
23139      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
23140      *
23141      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
23142      * If it returns false the caller may ignore the rest of this contract until the next scroll.
23143      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
23144      *
23145      * <p>At each incremental step of the scroll the caller should invoke
23146      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
23147      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
23148      * parent at least partially consumed the scroll and the caller should adjust the amount it
23149      * scrolls by.</p>
23150      *
23151      * <p>After applying the remainder of the scroll delta the caller should invoke
23152      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
23153      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
23154      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
23155      * </p>
23156      *
23157      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
23158      *             {@link #SCROLL_AXIS_VERTICAL}.
23159      * @return true if a cooperative parent was found and nested scrolling has been enabled for
23160      *         the current gesture.
23161      *
23162      * @see #stopNestedScroll()
23163      * @see #dispatchNestedPreScroll(int, int, int[], int[])
23164      * @see #dispatchNestedScroll(int, int, int, int, int[])
23165      */
23166     public boolean startNestedScroll(int axes) {
23167         if (hasNestedScrollingParent()) {
23168             // Already in progress
23169             return true;
23170         }
23171         if (isNestedScrollingEnabled()) {
23172             ViewParent p = getParent();
23173             View child = this;
23174             while (p != null) {
23175                 try {
23176                     if (p.onStartNestedScroll(child, this, axes)) {
23177                         mNestedScrollingParent = p;
23178                         p.onNestedScrollAccepted(child, this, axes);
23179                         return true;
23180                     }
23181                 } catch (AbstractMethodError e) {
23182                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
23183                             "method onStartNestedScroll", e);
23184                     // Allow the search upward to continue
23185                 }
23186                 if (p instanceof View) {
23187                     child = (View) p;
23188                 }
23189                 p = p.getParent();
23190             }
23191         }
23192         return false;
23193     }
23194
23195     /**
23196      * Stop a nested scroll in progress.
23197      *
23198      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
23199      *
23200      * @see #startNestedScroll(int)
23201      */
23202     public void stopNestedScroll() {
23203         if (mNestedScrollingParent != null) {
23204             mNestedScrollingParent.onStopNestedScroll(this);
23205             mNestedScrollingParent = null;
23206         }
23207     }
23208
23209     /**
23210      * Returns true if this view has a nested scrolling parent.
23211      *
23212      * <p>The presence of a nested scrolling parent indicates that this view has initiated
23213      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
23214      *
23215      * @return whether this view has a nested scrolling parent
23216      */
23217     public boolean hasNestedScrollingParent() {
23218         return mNestedScrollingParent != null;
23219     }
23220
23221     /**
23222      * Dispatch one step of a nested scroll in progress.
23223      *
23224      * <p>Implementations of views that support nested scrolling should call this to report
23225      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23226      * is not currently in progress or nested scrolling is not
23227      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23228      *
23229      * <p>Compatible View implementations should also call
23230      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23231      * consuming a component of the scroll event themselves.</p>
23232      *
23233      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23234      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23235      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23236      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23237      * @param offsetInWindow Optional. If not null, on return this will contain the offset
23238      *                       in local view coordinates of this view from before this operation
23239      *                       to after it completes. View implementations may use this to adjust
23240      *                       expected input coordinate tracking.
23241      * @return true if the event was dispatched, false if it could not be dispatched.
23242      * @see #dispatchNestedPreScroll(int, int, int[], int[])
23243      */
23244     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23245             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23246         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23247             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23248                 int startX = 0;
23249                 int startY = 0;
23250                 if (offsetInWindow != null) {
23251                     getLocationInWindow(offsetInWindow);
23252                     startX = offsetInWindow[0];
23253                     startY = offsetInWindow[1];
23254                 }
23255
23256                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23257                         dxUnconsumed, dyUnconsumed);
23258
23259                 if (offsetInWindow != null) {
23260                     getLocationInWindow(offsetInWindow);
23261                     offsetInWindow[0] -= startX;
23262                     offsetInWindow[1] -= startY;
23263                 }
23264                 return true;
23265             } else if (offsetInWindow != null) {
23266                 // No motion, no dispatch. Keep offsetInWindow up to date.
23267                 offsetInWindow[0] = 0;
23268                 offsetInWindow[1] = 0;
23269             }
23270         }
23271         return false;
23272     }
23273
23274     /**
23275      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23276      *
23277      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23278      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23279      * scrolling operation to consume some or all of the scroll operation before the child view
23280      * consumes it.</p>
23281      *
23282      * @param dx Horizontal scroll distance in pixels
23283      * @param dy Vertical scroll distance in pixels
23284      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23285      *                 and consumed[1] the consumed dy.
23286      * @param offsetInWindow Optional. If not null, on return this will contain the offset
23287      *                       in local view coordinates of this view from before this operation
23288      *                       to after it completes. View implementations may use this to adjust
23289      *                       expected input coordinate tracking.
23290      * @return true if the parent consumed some or all of the scroll delta
23291      * @see #dispatchNestedScroll(int, int, int, int, int[])
23292      */
23293     public boolean dispatchNestedPreScroll(int dx, int dy,
23294             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23295         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23296             if (dx != 0 || dy != 0) {
23297                 int startX = 0;
23298                 int startY = 0;
23299                 if (offsetInWindow != null) {
23300                     getLocationInWindow(offsetInWindow);
23301                     startX = offsetInWindow[0];
23302                     startY = offsetInWindow[1];
23303                 }
23304
23305                 if (consumed == null) {
23306                     if (mTempNestedScrollConsumed == null) {
23307                         mTempNestedScrollConsumed = new int[2];
23308                     }
23309                     consumed = mTempNestedScrollConsumed;
23310                 }
23311                 consumed[0] = 0;
23312                 consumed[1] = 0;
23313                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23314
23315                 if (offsetInWindow != null) {
23316                     getLocationInWindow(offsetInWindow);
23317                     offsetInWindow[0] -= startX;
23318                     offsetInWindow[1] -= startY;
23319                 }
23320                 return consumed[0] != 0 || consumed[1] != 0;
23321             } else if (offsetInWindow != null) {
23322                 offsetInWindow[0] = 0;
23323                 offsetInWindow[1] = 0;
23324             }
23325         }
23326         return false;
23327     }
23328
23329     /**
23330      * Dispatch a fling to a nested scrolling parent.
23331      *
23332      * <p>This method should be used to indicate that a nested scrolling child has detected
23333      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23334      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23335      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23336      * along a scrollable axis.</p>
23337      *
23338      * <p>If a nested scrolling child view would normally fling but it is at the edge of
23339      * its own content, it can use this method to delegate the fling to its nested scrolling
23340      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23341      *
23342      * @param velocityX Horizontal fling velocity in pixels per second
23343      * @param velocityY Vertical fling velocity in pixels per second
23344      * @param consumed true if the child consumed the fling, false otherwise
23345      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23346      */
23347     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23348         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23349             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23350         }
23351         return false;
23352     }
23353
23354     /**
23355      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23356      *
23357      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23358      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23359      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23360      * before the child view consumes it. If this method returns <code>true</code>, a nested
23361      * parent view consumed the fling and this view should not scroll as a result.</p>
23362      *
23363      * <p>For a better user experience, only one view in a nested scrolling chain should consume
23364      * the fling at a time. If a parent view consumed the fling this method will return false.
23365      * Custom view implementations should account for this in two ways:</p>
23366      *
23367      * <ul>
23368      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23369      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23370      *     position regardless.</li>
23371      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23372      *     even to settle back to a valid idle position.</li>
23373      * </ul>
23374      *
23375      * <p>Views should also not offer fling velocities to nested parent views along an axis
23376      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23377      * should not offer a horizontal fling velocity to its parents since scrolling along that
23378      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23379      *
23380      * @param velocityX Horizontal fling velocity in pixels per second
23381      * @param velocityY Vertical fling velocity in pixels per second
23382      * @return true if a nested scrolling parent consumed the fling
23383      */
23384     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23385         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23386             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23387         }
23388         return false;
23389     }
23390
23391     /**
23392      * Gets a scale factor that determines the distance the view should scroll
23393      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23394      * @return The vertical scroll scale factor.
23395      * @hide
23396      */
23397     protected float getVerticalScrollFactor() {
23398         if (mVerticalScrollFactor == 0) {
23399             TypedValue outValue = new TypedValue();
23400             if (!mContext.getTheme().resolveAttribute(
23401                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23402                 throw new IllegalStateException(
23403                         "Expected theme to define listPreferredItemHeight.");
23404             }
23405             mVerticalScrollFactor = outValue.getDimension(
23406                     mContext.getResources().getDisplayMetrics());
23407         }
23408         return mVerticalScrollFactor;
23409     }
23410
23411     /**
23412      * Gets a scale factor that determines the distance the view should scroll
23413      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23414      * @return The horizontal scroll scale factor.
23415      * @hide
23416      */
23417     protected float getHorizontalScrollFactor() {
23418         // TODO: Should use something else.
23419         return getVerticalScrollFactor();
23420     }
23421
23422     /**
23423      * Return the value specifying the text direction or policy that was set with
23424      * {@link #setTextDirection(int)}.
23425      *
23426      * @return the defined text direction. It can be one of:
23427      *
23428      * {@link #TEXT_DIRECTION_INHERIT},
23429      * {@link #TEXT_DIRECTION_FIRST_STRONG},
23430      * {@link #TEXT_DIRECTION_ANY_RTL},
23431      * {@link #TEXT_DIRECTION_LTR},
23432      * {@link #TEXT_DIRECTION_RTL},
23433      * {@link #TEXT_DIRECTION_LOCALE},
23434      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23435      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23436      *
23437      * @attr ref android.R.styleable#View_textDirection
23438      *
23439      * @hide
23440      */
23441     @ViewDebug.ExportedProperty(category = "text", mapping = {
23442             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23443             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23444             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23445             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23446             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23447             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23448             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23449             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23450     })
23451     public int getRawTextDirection() {
23452         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23453     }
23454
23455     /**
23456      * Set the text direction.
23457      *
23458      * @param textDirection the direction to set. Should be one of:
23459      *
23460      * {@link #TEXT_DIRECTION_INHERIT},
23461      * {@link #TEXT_DIRECTION_FIRST_STRONG},
23462      * {@link #TEXT_DIRECTION_ANY_RTL},
23463      * {@link #TEXT_DIRECTION_LTR},
23464      * {@link #TEXT_DIRECTION_RTL},
23465      * {@link #TEXT_DIRECTION_LOCALE}
23466      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23467      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23468      *
23469      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23470      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23471      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23472      *
23473      * @attr ref android.R.styleable#View_textDirection
23474      */
23475     public void setTextDirection(int textDirection) {
23476         if (getRawTextDirection() != textDirection) {
23477             // Reset the current text direction and the resolved one
23478             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23479             resetResolvedTextDirection();
23480             // Set the new text direction
23481             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23482             // Do resolution
23483             resolveTextDirection();
23484             // Notify change
23485             onRtlPropertiesChanged(getLayoutDirection());
23486             // Refresh
23487             requestLayout();
23488             invalidate(true);
23489         }
23490     }
23491
23492     /**
23493      * Return the resolved text direction.
23494      *
23495      * @return the resolved text direction. Returns one of:
23496      *
23497      * {@link #TEXT_DIRECTION_FIRST_STRONG},
23498      * {@link #TEXT_DIRECTION_ANY_RTL},
23499      * {@link #TEXT_DIRECTION_LTR},
23500      * {@link #TEXT_DIRECTION_RTL},
23501      * {@link #TEXT_DIRECTION_LOCALE},
23502      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23503      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23504      *
23505      * @attr ref android.R.styleable#View_textDirection
23506      */
23507     @ViewDebug.ExportedProperty(category = "text", mapping = {
23508             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23509             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23510             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23511             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23512             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23513             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23514             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23515             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23516     })
23517     public int getTextDirection() {
23518         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23519     }
23520
23521     /**
23522      * Resolve the text direction.
23523      *
23524      * @return true if resolution has been done, false otherwise.
23525      *
23526      * @hide
23527      */
23528     public boolean resolveTextDirection() {
23529         // Reset any previous text direction resolution
23530         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23531
23532         if (hasRtlSupport()) {
23533             // Set resolved text direction flag depending on text direction flag
23534             final int textDirection = getRawTextDirection();
23535             switch(textDirection) {
23536                 case TEXT_DIRECTION_INHERIT:
23537                     if (!canResolveTextDirection()) {
23538                         // We cannot do the resolution if there is no parent, so use the default one
23539                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23540                         // Resolution will need to happen again later
23541                         return false;
23542                     }
23543
23544                     // Parent has not yet resolved, so we still return the default
23545                     try {
23546                         if (!mParent.isTextDirectionResolved()) {
23547                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23548                             // Resolution will need to happen again later
23549                             return false;
23550                         }
23551                     } catch (AbstractMethodError e) {
23552                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23553                                 " does not fully implement ViewParent", e);
23554                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23555                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23556                         return true;
23557                     }
23558
23559                     // Set current resolved direction to the same value as the parent's one
23560                     int parentResolvedDirection;
23561                     try {
23562                         parentResolvedDirection = mParent.getTextDirection();
23563                     } catch (AbstractMethodError e) {
23564                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23565                                 " does not fully implement ViewParent", e);
23566                         parentResolvedDirection = TEXT_DIRECTION_LTR;
23567                     }
23568                     switch (parentResolvedDirection) {
23569                         case TEXT_DIRECTION_FIRST_STRONG:
23570                         case TEXT_DIRECTION_ANY_RTL:
23571                         case TEXT_DIRECTION_LTR:
23572                         case TEXT_DIRECTION_RTL:
23573                         case TEXT_DIRECTION_LOCALE:
23574                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
23575                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
23576                             mPrivateFlags2 |=
23577                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23578                             break;
23579                         default:
23580                             // Default resolved direction is "first strong" heuristic
23581                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23582                     }
23583                     break;
23584                 case TEXT_DIRECTION_FIRST_STRONG:
23585                 case TEXT_DIRECTION_ANY_RTL:
23586                 case TEXT_DIRECTION_LTR:
23587                 case TEXT_DIRECTION_RTL:
23588                 case TEXT_DIRECTION_LOCALE:
23589                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
23590                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
23591                     // Resolved direction is the same as text direction
23592                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23593                     break;
23594                 default:
23595                     // Default resolved direction is "first strong" heuristic
23596                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23597             }
23598         } else {
23599             // Default resolved direction is "first strong" heuristic
23600             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23601         }
23602
23603         // Set to resolved
23604         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23605         return true;
23606     }
23607
23608     /**
23609      * Check if text direction resolution can be done.
23610      *
23611      * @return true if text direction resolution can be done otherwise return false.
23612      */
23613     public boolean canResolveTextDirection() {
23614         switch (getRawTextDirection()) {
23615             case TEXT_DIRECTION_INHERIT:
23616                 if (mParent != null) {
23617                     try {
23618                         return mParent.canResolveTextDirection();
23619                     } catch (AbstractMethodError e) {
23620                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23621                                 " does not fully implement ViewParent", e);
23622                     }
23623                 }
23624                 return false;
23625
23626             default:
23627                 return true;
23628         }
23629     }
23630
23631     /**
23632      * Reset resolved text direction. Text direction will be resolved during a call to
23633      * {@link #onMeasure(int, int)}.
23634      *
23635      * @hide
23636      */
23637     public void resetResolvedTextDirection() {
23638         // Reset any previous text direction resolution
23639         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23640         // Set to default value
23641         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23642     }
23643
23644     /**
23645      * @return true if text direction is inherited.
23646      *
23647      * @hide
23648      */
23649     public boolean isTextDirectionInherited() {
23650         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23651     }
23652
23653     /**
23654      * @return true if text direction is resolved.
23655      */
23656     public boolean isTextDirectionResolved() {
23657         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23658     }
23659
23660     /**
23661      * Return the value specifying the text alignment or policy that was set with
23662      * {@link #setTextAlignment(int)}.
23663      *
23664      * @return the defined text alignment. It can be one of:
23665      *
23666      * {@link #TEXT_ALIGNMENT_INHERIT},
23667      * {@link #TEXT_ALIGNMENT_GRAVITY},
23668      * {@link #TEXT_ALIGNMENT_CENTER},
23669      * {@link #TEXT_ALIGNMENT_TEXT_START},
23670      * {@link #TEXT_ALIGNMENT_TEXT_END},
23671      * {@link #TEXT_ALIGNMENT_VIEW_START},
23672      * {@link #TEXT_ALIGNMENT_VIEW_END}
23673      *
23674      * @attr ref android.R.styleable#View_textAlignment
23675      *
23676      * @hide
23677      */
23678     @ViewDebug.ExportedProperty(category = "text", mapping = {
23679             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23680             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23681             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23682             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23683             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23684             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23685             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23686     })
23687     @TextAlignment
23688     public int getRawTextAlignment() {
23689         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23690     }
23691
23692     /**
23693      * Set the text alignment.
23694      *
23695      * @param textAlignment The text alignment to set. Should be one of
23696      *
23697      * {@link #TEXT_ALIGNMENT_INHERIT},
23698      * {@link #TEXT_ALIGNMENT_GRAVITY},
23699      * {@link #TEXT_ALIGNMENT_CENTER},
23700      * {@link #TEXT_ALIGNMENT_TEXT_START},
23701      * {@link #TEXT_ALIGNMENT_TEXT_END},
23702      * {@link #TEXT_ALIGNMENT_VIEW_START},
23703      * {@link #TEXT_ALIGNMENT_VIEW_END}
23704      *
23705      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23706      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23707      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23708      *
23709      * @attr ref android.R.styleable#View_textAlignment
23710      */
23711     public void setTextAlignment(@TextAlignment int textAlignment) {
23712         if (textAlignment != getRawTextAlignment()) {
23713             // Reset the current and resolved text alignment
23714             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23715             resetResolvedTextAlignment();
23716             // Set the new text alignment
23717             mPrivateFlags2 |=
23718                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23719             // Do resolution
23720             resolveTextAlignment();
23721             // Notify change
23722             onRtlPropertiesChanged(getLayoutDirection());
23723             // Refresh
23724             requestLayout();
23725             invalidate(true);
23726         }
23727     }
23728
23729     /**
23730      * Return the resolved text alignment.
23731      *
23732      * @return the resolved text alignment. Returns one of:
23733      *
23734      * {@link #TEXT_ALIGNMENT_GRAVITY},
23735      * {@link #TEXT_ALIGNMENT_CENTER},
23736      * {@link #TEXT_ALIGNMENT_TEXT_START},
23737      * {@link #TEXT_ALIGNMENT_TEXT_END},
23738      * {@link #TEXT_ALIGNMENT_VIEW_START},
23739      * {@link #TEXT_ALIGNMENT_VIEW_END}
23740      *
23741      * @attr ref android.R.styleable#View_textAlignment
23742      */
23743     @ViewDebug.ExportedProperty(category = "text", mapping = {
23744             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23745             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23746             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23747             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23748             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23749             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23750             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23751     })
23752     @TextAlignment
23753     public int getTextAlignment() {
23754         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23755                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23756     }
23757
23758     /**
23759      * Resolve the text alignment.
23760      *
23761      * @return true if resolution has been done, false otherwise.
23762      *
23763      * @hide
23764      */
23765     public boolean resolveTextAlignment() {
23766         // Reset any previous text alignment resolution
23767         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23768
23769         if (hasRtlSupport()) {
23770             // Set resolved text alignment flag depending on text alignment flag
23771             final int textAlignment = getRawTextAlignment();
23772             switch (textAlignment) {
23773                 case TEXT_ALIGNMENT_INHERIT:
23774                     // Check if we can resolve the text alignment
23775                     if (!canResolveTextAlignment()) {
23776                         // We cannot do the resolution if there is no parent so use the default
23777                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23778                         // Resolution will need to happen again later
23779                         return false;
23780                     }
23781
23782                     // Parent has not yet resolved, so we still return the default
23783                     try {
23784                         if (!mParent.isTextAlignmentResolved()) {
23785                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23786                             // Resolution will need to happen again later
23787                             return false;
23788                         }
23789                     } catch (AbstractMethodError e) {
23790                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23791                                 " does not fully implement ViewParent", e);
23792                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23793                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23794                         return true;
23795                     }
23796
23797                     int parentResolvedTextAlignment;
23798                     try {
23799                         parentResolvedTextAlignment = mParent.getTextAlignment();
23800                     } catch (AbstractMethodError e) {
23801                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23802                                 " does not fully implement ViewParent", e);
23803                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23804                     }
23805                     switch (parentResolvedTextAlignment) {
23806                         case TEXT_ALIGNMENT_GRAVITY:
23807                         case TEXT_ALIGNMENT_TEXT_START:
23808                         case TEXT_ALIGNMENT_TEXT_END:
23809                         case TEXT_ALIGNMENT_CENTER:
23810                         case TEXT_ALIGNMENT_VIEW_START:
23811                         case TEXT_ALIGNMENT_VIEW_END:
23812                             // Resolved text alignment is the same as the parent resolved
23813                             // text alignment
23814                             mPrivateFlags2 |=
23815                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23816                             break;
23817                         default:
23818                             // Use default resolved text alignment
23819                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23820                     }
23821                     break;
23822                 case TEXT_ALIGNMENT_GRAVITY:
23823                 case TEXT_ALIGNMENT_TEXT_START:
23824                 case TEXT_ALIGNMENT_TEXT_END:
23825                 case TEXT_ALIGNMENT_CENTER:
23826                 case TEXT_ALIGNMENT_VIEW_START:
23827                 case TEXT_ALIGNMENT_VIEW_END:
23828                     // Resolved text alignment is the same as text alignment
23829                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23830                     break;
23831                 default:
23832                     // Use default resolved text alignment
23833                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23834             }
23835         } else {
23836             // Use default resolved text alignment
23837             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23838         }
23839
23840         // Set the resolved
23841         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23842         return true;
23843     }
23844
23845     /**
23846      * Check if text alignment resolution can be done.
23847      *
23848      * @return true if text alignment resolution can be done otherwise return false.
23849      */
23850     public boolean canResolveTextAlignment() {
23851         switch (getRawTextAlignment()) {
23852             case TEXT_DIRECTION_INHERIT:
23853                 if (mParent != null) {
23854                     try {
23855                         return mParent.canResolveTextAlignment();
23856                     } catch (AbstractMethodError e) {
23857                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23858                                 " does not fully implement ViewParent", e);
23859                     }
23860                 }
23861                 return false;
23862
23863             default:
23864                 return true;
23865         }
23866     }
23867
23868     /**
23869      * Reset resolved text alignment. Text alignment will be resolved during a call to
23870      * {@link #onMeasure(int, int)}.
23871      *
23872      * @hide
23873      */
23874     public void resetResolvedTextAlignment() {
23875         // Reset any previous text alignment resolution
23876         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23877         // Set to default
23878         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23879     }
23880
23881     /**
23882      * @return true if text alignment is inherited.
23883      *
23884      * @hide
23885      */
23886     public boolean isTextAlignmentInherited() {
23887         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23888     }
23889
23890     /**
23891      * @return true if text alignment is resolved.
23892      */
23893     public boolean isTextAlignmentResolved() {
23894         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23895     }
23896
23897     /**
23898      * Generate a value suitable for use in {@link #setId(int)}.
23899      * This value will not collide with ID values generated at build time by aapt for R.id.
23900      *
23901      * @return a generated ID value
23902      */
23903     public static int generateViewId() {
23904         for (;;) {
23905             final int result = sNextGeneratedId.get();
23906             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23907             int newValue = result + 1;
23908             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23909             if (sNextGeneratedId.compareAndSet(result, newValue)) {
23910                 return result;
23911             }
23912         }
23913     }
23914
23915     private static boolean isViewIdGenerated(int id) {
23916         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23917     }
23918
23919     /**
23920      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23921      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23922      *                           a normal View or a ViewGroup with
23923      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23924      * @hide
23925      */
23926     public void captureTransitioningViews(List<View> transitioningViews) {
23927         if (getVisibility() == View.VISIBLE) {
23928             transitioningViews.add(this);
23929         }
23930     }
23931
23932     /**
23933      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23934      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23935      * @hide
23936      */
23937     public void findNamedViews(Map<String, View> namedElements) {
23938         if (getVisibility() == VISIBLE || mGhostView != null) {
23939             String transitionName = getTransitionName();
23940             if (transitionName != null) {
23941                 namedElements.put(transitionName, this);
23942             }
23943         }
23944     }
23945
23946     /**
23947      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23948      * The default implementation does not care the location or event types, but some subclasses
23949      * may use it (such as WebViews).
23950      * @param event The MotionEvent from a mouse
23951      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23952      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23953      * @see PointerIcon
23954      */
23955     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23956         final float x = event.getX(pointerIndex);
23957         final float y = event.getY(pointerIndex);
23958         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23959             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23960         }
23961         return mPointerIcon;
23962     }
23963
23964     /**
23965      * Set the pointer icon for the current view.
23966      * Passing {@code null} will restore the pointer icon to its default value.
23967      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23968      */
23969     public void setPointerIcon(PointerIcon pointerIcon) {
23970         mPointerIcon = pointerIcon;
23971         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23972             return;
23973         }
23974         try {
23975             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23976         } catch (RemoteException e) {
23977         }
23978     }
23979
23980     /**
23981      * Gets the pointer icon for the current view.
23982      */
23983     public PointerIcon getPointerIcon() {
23984         return mPointerIcon;
23985     }
23986
23987     /**
23988      * Checks pointer capture status.
23989      *
23990      * @return true if the view has pointer capture.
23991      * @see #requestPointerCapture()
23992      * @see #hasPointerCapture()
23993      */
23994     public boolean hasPointerCapture() {
23995         final ViewRootImpl viewRootImpl = getViewRootImpl();
23996         if (viewRootImpl == null) {
23997             return false;
23998         }
23999         return viewRootImpl.hasPointerCapture();
24000     }
24001
24002     /**
24003      * Requests pointer capture mode.
24004      * <p>
24005      * When the window has pointer capture, the mouse pointer icon will disappear and will not
24006      * change its position. Further mouse will be dispatched with the source
24007      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
24008      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
24009      * (touchscreens, or stylus) will not be affected.
24010      * <p>
24011      * If the window already has pointer capture, this call does nothing.
24012      * <p>
24013      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
24014      * automatically when the window loses focus.
24015      *
24016      * @see #releasePointerCapture()
24017      * @see #hasPointerCapture()
24018      */
24019     public void requestPointerCapture() {
24020         final ViewRootImpl viewRootImpl = getViewRootImpl();
24021         if (viewRootImpl != null) {
24022             viewRootImpl.requestPointerCapture(true);
24023         }
24024     }
24025
24026
24027     /**
24028      * Releases the pointer capture.
24029      * <p>
24030      * If the window does not have pointer capture, this call will do nothing.
24031      * @see #requestPointerCapture()
24032      * @see #hasPointerCapture()
24033      */
24034     public void releasePointerCapture() {
24035         final ViewRootImpl viewRootImpl = getViewRootImpl();
24036         if (viewRootImpl != null) {
24037             viewRootImpl.requestPointerCapture(false);
24038         }
24039     }
24040
24041     /**
24042      * Called when the window has just acquired or lost pointer capture.
24043      *
24044      * @param hasCapture True if the view now has pointerCapture, false otherwise.
24045      */
24046     @CallSuper
24047     public void onPointerCaptureChange(boolean hasCapture) {
24048     }
24049
24050     /**
24051      * @see #onPointerCaptureChange
24052      */
24053     public void dispatchPointerCaptureChanged(boolean hasCapture) {
24054         onPointerCaptureChange(hasCapture);
24055     }
24056
24057     /**
24058      * Implement this method to handle captured pointer events
24059      *
24060      * @param event The captured pointer event.
24061      * @return True if the event was handled, false otherwise.
24062      * @see #requestPointerCapture()
24063      */
24064     public boolean onCapturedPointerEvent(MotionEvent event) {
24065         return false;
24066     }
24067
24068     /**
24069      * Interface definition for a callback to be invoked when a captured pointer event
24070      * is being dispatched this view. The callback will be invoked before the event is
24071      * given to the view.
24072      */
24073     public interface OnCapturedPointerListener {
24074         /**
24075          * Called when a captured pointer event is dispatched to a view.
24076          * @param view The view this event has been dispatched to.
24077          * @param event The captured event.
24078          * @return True if the listener has consumed the event, false otherwise.
24079          */
24080         boolean onCapturedPointer(View view, MotionEvent event);
24081     }
24082
24083     /**
24084      * Set a listener to receive callbacks when the pointer capture state of a view changes.
24085      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
24086      */
24087     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
24088         getListenerInfo().mOnCapturedPointerListener = l;
24089     }
24090
24091     // Properties
24092     //
24093     /**
24094      * A Property wrapper around the <code>alpha</code> functionality handled by the
24095      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
24096      */
24097     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
24098         @Override
24099         public void setValue(View object, float value) {
24100             object.setAlpha(value);
24101         }
24102
24103         @Override
24104         public Float get(View object) {
24105             return object.getAlpha();
24106         }
24107     };
24108
24109     /**
24110      * A Property wrapper around the <code>translationX</code> functionality handled by the
24111      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
24112      */
24113     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
24114         @Override
24115         public void setValue(View object, float value) {
24116             object.setTranslationX(value);
24117         }
24118
24119                 @Override
24120         public Float get(View object) {
24121             return object.getTranslationX();
24122         }
24123     };
24124
24125     /**
24126      * A Property wrapper around the <code>translationY</code> functionality handled by the
24127      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
24128      */
24129     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
24130         @Override
24131         public void setValue(View object, float value) {
24132             object.setTranslationY(value);
24133         }
24134
24135         @Override
24136         public Float get(View object) {
24137             return object.getTranslationY();
24138         }
24139     };
24140
24141     /**
24142      * A Property wrapper around the <code>translationZ</code> functionality handled by the
24143      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
24144      */
24145     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
24146         @Override
24147         public void setValue(View object, float value) {
24148             object.setTranslationZ(value);
24149         }
24150
24151         @Override
24152         public Float get(View object) {
24153             return object.getTranslationZ();
24154         }
24155     };
24156
24157     /**
24158      * A Property wrapper around the <code>x</code> functionality handled by the
24159      * {@link View#setX(float)} and {@link View#getX()} methods.
24160      */
24161     public static final Property<View, Float> X = new FloatProperty<View>("x") {
24162         @Override
24163         public void setValue(View object, float value) {
24164             object.setX(value);
24165         }
24166
24167         @Override
24168         public Float get(View object) {
24169             return object.getX();
24170         }
24171     };
24172
24173     /**
24174      * A Property wrapper around the <code>y</code> functionality handled by the
24175      * {@link View#setY(float)} and {@link View#getY()} methods.
24176      */
24177     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
24178         @Override
24179         public void setValue(View object, float value) {
24180             object.setY(value);
24181         }
24182
24183         @Override
24184         public Float get(View object) {
24185             return object.getY();
24186         }
24187     };
24188
24189     /**
24190      * A Property wrapper around the <code>z</code> functionality handled by the
24191      * {@link View#setZ(float)} and {@link View#getZ()} methods.
24192      */
24193     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
24194         @Override
24195         public void setValue(View object, float value) {
24196             object.setZ(value);
24197         }
24198
24199         @Override
24200         public Float get(View object) {
24201             return object.getZ();
24202         }
24203     };
24204
24205     /**
24206      * A Property wrapper around the <code>rotation</code> functionality handled by the
24207      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
24208      */
24209     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
24210         @Override
24211         public void setValue(View object, float value) {
24212             object.setRotation(value);
24213         }
24214
24215         @Override
24216         public Float get(View object) {
24217             return object.getRotation();
24218         }
24219     };
24220
24221     /**
24222      * A Property wrapper around the <code>rotationX</code> functionality handled by the
24223      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24224      */
24225     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24226         @Override
24227         public void setValue(View object, float value) {
24228             object.setRotationX(value);
24229         }
24230
24231         @Override
24232         public Float get(View object) {
24233             return object.getRotationX();
24234         }
24235     };
24236
24237     /**
24238      * A Property wrapper around the <code>rotationY</code> functionality handled by the
24239      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24240      */
24241     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24242         @Override
24243         public void setValue(View object, float value) {
24244             object.setRotationY(value);
24245         }
24246
24247         @Override
24248         public Float get(View object) {
24249             return object.getRotationY();
24250         }
24251     };
24252
24253     /**
24254      * A Property wrapper around the <code>scaleX</code> functionality handled by the
24255      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24256      */
24257     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24258         @Override
24259         public void setValue(View object, float value) {
24260             object.setScaleX(value);
24261         }
24262
24263         @Override
24264         public Float get(View object) {
24265             return object.getScaleX();
24266         }
24267     };
24268
24269     /**
24270      * A Property wrapper around the <code>scaleY</code> functionality handled by the
24271      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24272      */
24273     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24274         @Override
24275         public void setValue(View object, float value) {
24276             object.setScaleY(value);
24277         }
24278
24279         @Override
24280         public Float get(View object) {
24281             return object.getScaleY();
24282         }
24283     };
24284
24285     /**
24286      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24287      * Each MeasureSpec represents a requirement for either the width or the height.
24288      * A MeasureSpec is comprised of a size and a mode. There are three possible
24289      * modes:
24290      * <dl>
24291      * <dt>UNSPECIFIED</dt>
24292      * <dd>
24293      * The parent has not imposed any constraint on the child. It can be whatever size
24294      * it wants.
24295      * </dd>
24296      *
24297      * <dt>EXACTLY</dt>
24298      * <dd>
24299      * The parent has determined an exact size for the child. The child is going to be
24300      * given those bounds regardless of how big it wants to be.
24301      * </dd>
24302      *
24303      * <dt>AT_MOST</dt>
24304      * <dd>
24305      * The child can be as large as it wants up to the specified size.
24306      * </dd>
24307      * </dl>
24308      *
24309      * MeasureSpecs are implemented as ints to reduce object allocation. This class
24310      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24311      */
24312     public static class MeasureSpec {
24313         private static final int MODE_SHIFT = 30;
24314         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24315
24316         /** @hide */
24317         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24318         @Retention(RetentionPolicy.SOURCE)
24319         public @interface MeasureSpecMode {}
24320
24321         /**
24322          * Measure specification mode: The parent has not imposed any constraint
24323          * on the child. It can be whatever size it wants.
24324          */
24325         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24326
24327         /**
24328          * Measure specification mode: The parent has determined an exact size
24329          * for the child. The child is going to be given those bounds regardless
24330          * of how big it wants to be.
24331          */
24332         public static final int EXACTLY     = 1 << MODE_SHIFT;
24333
24334         /**
24335          * Measure specification mode: The child can be as large as it wants up
24336          * to the specified size.
24337          */
24338         public static final int AT_MOST     = 2 << MODE_SHIFT;
24339
24340         /**
24341          * Creates a measure specification based on the supplied size and mode.
24342          *
24343          * The mode must always be one of the following:
24344          * <ul>
24345          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24346          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24347          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24348          * </ul>
24349          *
24350          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24351          * implementation was such that the order of arguments did not matter
24352          * and overflow in either value could impact the resulting MeasureSpec.
24353          * {@link android.widget.RelativeLayout} was affected by this bug.
24354          * Apps targeting API levels greater than 17 will get the fixed, more strict
24355          * behavior.</p>
24356          *
24357          * @param size the size of the measure specification
24358          * @param mode the mode of the measure specification
24359          * @return the measure specification based on size and mode
24360          */
24361         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24362                                           @MeasureSpecMode int mode) {
24363             if (sUseBrokenMakeMeasureSpec) {
24364                 return size + mode;
24365             } else {
24366                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
24367             }
24368         }
24369
24370         /**
24371          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24372          * will automatically get a size of 0. Older apps expect this.
24373          *
24374          * @hide internal use only for compatibility with system widgets and older apps
24375          */
24376         public static int makeSafeMeasureSpec(int size, int mode) {
24377             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24378                 return 0;
24379             }
24380             return makeMeasureSpec(size, mode);
24381         }
24382
24383         /**
24384          * Extracts the mode from the supplied measure specification.
24385          *
24386          * @param measureSpec the measure specification to extract the mode from
24387          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24388          *         {@link android.view.View.MeasureSpec#AT_MOST} or
24389          *         {@link android.view.View.MeasureSpec#EXACTLY}
24390          */
24391         @MeasureSpecMode
24392         public static int getMode(int measureSpec) {
24393             //noinspection ResourceType
24394             return (measureSpec & MODE_MASK);
24395         }
24396
24397         /**
24398          * Extracts the size from the supplied measure specification.
24399          *
24400          * @param measureSpec the measure specification to extract the size from
24401          * @return the size in pixels defined in the supplied measure specification
24402          */
24403         public static int getSize(int measureSpec) {
24404             return (measureSpec & ~MODE_MASK);
24405         }
24406
24407         static int adjust(int measureSpec, int delta) {
24408             final int mode = getMode(measureSpec);
24409             int size = getSize(measureSpec);
24410             if (mode == UNSPECIFIED) {
24411                 // No need to adjust size for UNSPECIFIED mode.
24412                 return makeMeasureSpec(size, UNSPECIFIED);
24413             }
24414             size += delta;
24415             if (size < 0) {
24416                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24417                         ") spec: " + toString(measureSpec) + " delta: " + delta);
24418                 size = 0;
24419             }
24420             return makeMeasureSpec(size, mode);
24421         }
24422
24423         /**
24424          * Returns a String representation of the specified measure
24425          * specification.
24426          *
24427          * @param measureSpec the measure specification to convert to a String
24428          * @return a String with the following format: "MeasureSpec: MODE SIZE"
24429          */
24430         public static String toString(int measureSpec) {
24431             int mode = getMode(measureSpec);
24432             int size = getSize(measureSpec);
24433
24434             StringBuilder sb = new StringBuilder("MeasureSpec: ");
24435
24436             if (mode == UNSPECIFIED)
24437                 sb.append("UNSPECIFIED ");
24438             else if (mode == EXACTLY)
24439                 sb.append("EXACTLY ");
24440             else if (mode == AT_MOST)
24441                 sb.append("AT_MOST ");
24442             else
24443                 sb.append(mode).append(" ");
24444
24445             sb.append(size);
24446             return sb.toString();
24447         }
24448     }
24449
24450     private final class CheckForLongPress implements Runnable {
24451         private int mOriginalWindowAttachCount;
24452         private float mX;
24453         private float mY;
24454         private boolean mOriginalPressedState;
24455
24456         @Override
24457         public void run() {
24458             if ((mOriginalPressedState == isPressed()) && (mParent != null)
24459                     && mOriginalWindowAttachCount == mWindowAttachCount) {
24460                 if (performLongClick(mX, mY)) {
24461                     mHasPerformedLongPress = true;
24462                 }
24463             }
24464         }
24465
24466         public void setAnchor(float x, float y) {
24467             mX = x;
24468             mY = y;
24469         }
24470
24471         public void rememberWindowAttachCount() {
24472             mOriginalWindowAttachCount = mWindowAttachCount;
24473         }
24474
24475         public void rememberPressedState() {
24476             mOriginalPressedState = isPressed();
24477         }
24478     }
24479
24480     private final class CheckForTap implements Runnable {
24481         public float x;
24482         public float y;
24483
24484         @Override
24485         public void run() {
24486             mPrivateFlags &= ~PFLAG_PREPRESSED;
24487             setPressed(true, x, y);
24488             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24489         }
24490     }
24491
24492     private final class PerformClick implements Runnable {
24493         @Override
24494         public void run() {
24495             performClick();
24496         }
24497     }
24498
24499     /**
24500      * This method returns a ViewPropertyAnimator object, which can be used to animate
24501      * specific properties on this View.
24502      *
24503      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24504      */
24505     public ViewPropertyAnimator animate() {
24506         if (mAnimator == null) {
24507             mAnimator = new ViewPropertyAnimator(this);
24508         }
24509         return mAnimator;
24510     }
24511
24512     /**
24513      * Sets the name of the View to be used to identify Views in Transitions.
24514      * Names should be unique in the View hierarchy.
24515      *
24516      * @param transitionName The name of the View to uniquely identify it for Transitions.
24517      */
24518     public final void setTransitionName(String transitionName) {
24519         mTransitionName = transitionName;
24520     }
24521
24522     /**
24523      * Returns the name of the View to be used to identify Views in Transitions.
24524      * Names should be unique in the View hierarchy.
24525      *
24526      * <p>This returns null if the View has not been given a name.</p>
24527      *
24528      * @return The name used of the View to be used to identify Views in Transitions or null
24529      * if no name has been given.
24530      */
24531     @ViewDebug.ExportedProperty
24532     public String getTransitionName() {
24533         return mTransitionName;
24534     }
24535
24536     /**
24537      * @hide
24538      */
24539     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24540         // Do nothing.
24541     }
24542
24543     /**
24544      * Interface definition for a callback to be invoked when a hardware key event is
24545      * dispatched to this view. The callback will be invoked before the key event is
24546      * given to the view. This is only useful for hardware keyboards; a software input
24547      * method has no obligation to trigger this listener.
24548      */
24549     public interface OnKeyListener {
24550         /**
24551          * Called when a hardware key is dispatched to a view. This allows listeners to
24552          * get a chance to respond before the target view.
24553          * <p>Key presses in software keyboards will generally NOT trigger this method,
24554          * although some may elect to do so in some situations. Do not assume a
24555          * software input method has to be key-based; even if it is, it may use key presses
24556          * in a different way than you expect, so there is no way to reliably catch soft
24557          * input key presses.
24558          *
24559          * @param v The view the key has been dispatched to.
24560          * @param keyCode The code for the physical key that was pressed
24561          * @param event The KeyEvent object containing full information about
24562          *        the event.
24563          * @return True if the listener has consumed the event, false otherwise.
24564          */
24565         boolean onKey(View v, int keyCode, KeyEvent event);
24566     }
24567
24568     /**
24569      * Interface definition for a callback to be invoked when a touch event is
24570      * dispatched to this view. The callback will be invoked before the touch
24571      * event is given to the view.
24572      */
24573     public interface OnTouchListener {
24574         /**
24575          * Called when a touch event is dispatched to a view. This allows listeners to
24576          * get a chance to respond before the target view.
24577          *
24578          * @param v The view the touch event has been dispatched to.
24579          * @param event The MotionEvent object containing full information about
24580          *        the event.
24581          * @return True if the listener has consumed the event, false otherwise.
24582          */
24583         boolean onTouch(View v, MotionEvent event);
24584     }
24585
24586     /**
24587      * Interface definition for a callback to be invoked when a hover event is
24588      * dispatched to this view. The callback will be invoked before the hover
24589      * event is given to the view.
24590      */
24591     public interface OnHoverListener {
24592         /**
24593          * Called when a hover event is dispatched to a view. This allows listeners to
24594          * get a chance to respond before the target view.
24595          *
24596          * @param v The view the hover event has been dispatched to.
24597          * @param event The MotionEvent object containing full information about
24598          *        the event.
24599          * @return True if the listener has consumed the event, false otherwise.
24600          */
24601         boolean onHover(View v, MotionEvent event);
24602     }
24603
24604     /**
24605      * Interface definition for a callback to be invoked when a generic motion event is
24606      * dispatched to this view. The callback will be invoked before the generic motion
24607      * event is given to the view.
24608      */
24609     public interface OnGenericMotionListener {
24610         /**
24611          * Called when a generic motion event is dispatched to a view. This allows listeners to
24612          * get a chance to respond before the target view.
24613          *
24614          * @param v The view the generic motion event has been dispatched to.
24615          * @param event The MotionEvent object containing full information about
24616          *        the event.
24617          * @return True if the listener has consumed the event, false otherwise.
24618          */
24619         boolean onGenericMotion(View v, MotionEvent event);
24620     }
24621
24622     /**
24623      * Interface definition for a callback to be invoked when a view has been clicked and held.
24624      */
24625     public interface OnLongClickListener {
24626         /**
24627          * Called when a view has been clicked and held.
24628          *
24629          * @param v The view that was clicked and held.
24630          *
24631          * @return true if the callback consumed the long click, false otherwise.
24632          */
24633         boolean onLongClick(View v);
24634     }
24635
24636     /**
24637      * Interface definition for a callback to be invoked when a drag is being dispatched
24638      * to this view.  The callback will be invoked before the hosting view's own
24639      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24640      * onDrag(event) behavior, it should return 'false' from this callback.
24641      *
24642      * <div class="special reference">
24643      * <h3>Developer Guides</h3>
24644      * <p>For a guide to implementing drag and drop features, read the
24645      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24646      * </div>
24647      */
24648     public interface OnDragListener {
24649         /**
24650          * Called when a drag event is dispatched to a view. This allows listeners
24651          * to get a chance to override base View behavior.
24652          *
24653          * @param v The View that received the drag event.
24654          * @param event The {@link android.view.DragEvent} object for the drag event.
24655          * @return {@code true} if the drag event was handled successfully, or {@code false}
24656          * if the drag event was not handled. Note that {@code false} will trigger the View
24657          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24658          */
24659         boolean onDrag(View v, DragEvent event);
24660     }
24661
24662     /**
24663      * Interface definition for a callback to be invoked when the focus state of
24664      * a view changed.
24665      */
24666     public interface OnFocusChangeListener {
24667         /**
24668          * Called when the focus state of a view has changed.
24669          *
24670          * @param v The view whose state has changed.
24671          * @param hasFocus The new focus state of v.
24672          */
24673         void onFocusChange(View v, boolean hasFocus);
24674     }
24675
24676     /**
24677      * Interface definition for a callback to be invoked when a view is clicked.
24678      */
24679     public interface OnClickListener {
24680         /**
24681          * Called when a view has been clicked.
24682          *
24683          * @param v The view that was clicked.
24684          */
24685         void onClick(View v);
24686     }
24687
24688     /**
24689      * Interface definition for a callback to be invoked when a view is context clicked.
24690      */
24691     public interface OnContextClickListener {
24692         /**
24693          * Called when a view is context clicked.
24694          *
24695          * @param v The view that has been context clicked.
24696          * @return true if the callback consumed the context click, false otherwise.
24697          */
24698         boolean onContextClick(View v);
24699     }
24700
24701     /**
24702      * Interface definition for a callback to be invoked when the context menu
24703      * for this view is being built.
24704      */
24705     public interface OnCreateContextMenuListener {
24706         /**
24707          * Called when the context menu for this view is being built. It is not
24708          * safe to hold onto the menu after this method returns.
24709          *
24710          * @param menu The context menu that is being built
24711          * @param v The view for which the context menu is being built
24712          * @param menuInfo Extra information about the item for which the
24713          *            context menu should be shown. This information will vary
24714          *            depending on the class of v.
24715          */
24716         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24717     }
24718
24719     /**
24720      * Interface definition for a callback to be invoked when the status bar changes
24721      * visibility.  This reports <strong>global</strong> changes to the system UI
24722      * state, not what the application is requesting.
24723      *
24724      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24725      */
24726     public interface OnSystemUiVisibilityChangeListener {
24727         /**
24728          * Called when the status bar changes visibility because of a call to
24729          * {@link View#setSystemUiVisibility(int)}.
24730          *
24731          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24732          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24733          * This tells you the <strong>global</strong> state of these UI visibility
24734          * flags, not what your app is currently applying.
24735          */
24736         public void onSystemUiVisibilityChange(int visibility);
24737     }
24738
24739     /**
24740      * Interface definition for a callback to be invoked when this view is attached
24741      * or detached from its window.
24742      */
24743     public interface OnAttachStateChangeListener {
24744         /**
24745          * Called when the view is attached to a window.
24746          * @param v The view that was attached
24747          */
24748         public void onViewAttachedToWindow(View v);
24749         /**
24750          * Called when the view is detached from a window.
24751          * @param v The view that was detached
24752          */
24753         public void onViewDetachedFromWindow(View v);
24754     }
24755
24756     /**
24757      * Listener for applying window insets on a view in a custom way.
24758      *
24759      * <p>Apps may choose to implement this interface if they want to apply custom policy
24760      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24761      * is set, its
24762      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24763      * method will be called instead of the View's own
24764      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24765      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24766      * the View's normal behavior as part of its own.</p>
24767      */
24768     public interface OnApplyWindowInsetsListener {
24769         /**
24770          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24771          * on a View, this listener method will be called instead of the view's own
24772          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24773          *
24774          * @param v The view applying window insets
24775          * @param insets The insets to apply
24776          * @return The insets supplied, minus any insets that were consumed
24777          */
24778         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24779     }
24780
24781     private final class UnsetPressedState implements Runnable {
24782         @Override
24783         public void run() {
24784             setPressed(false);
24785         }
24786     }
24787
24788     /**
24789      * When a view becomes invisible checks if autofill considers the view invisible too. This
24790      * happens after the regular removal operation to make sure the operation is finished by the
24791      * time this is called.
24792      */
24793     private static class VisibilityChangeForAutofillHandler extends Handler {
24794         private final AutofillManager mAfm;
24795         private final View mView;
24796
24797         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
24798                 @NonNull View view) {
24799             mAfm = afm;
24800             mView = view;
24801         }
24802
24803         @Override
24804         public void handleMessage(Message msg) {
24805             mAfm.notifyViewVisibilityChange(mView, mView.isShown());
24806         }
24807     }
24808
24809     /**
24810      * Base class for derived classes that want to save and restore their own
24811      * state in {@link android.view.View#onSaveInstanceState()}.
24812      */
24813     public static class BaseSavedState extends AbsSavedState {
24814         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
24815         static final int IS_AUTOFILLED = 0b10;
24816         static final int ACCESSIBILITY_ID = 0b100;
24817
24818         // Flags that describe what data in this state is valid
24819         int mSavedData;
24820         String mStartActivityRequestWhoSaved;
24821         boolean mIsAutofilled;
24822         int mAccessibilityViewId;
24823
24824         /**
24825          * Constructor used when reading from a parcel. Reads the state of the superclass.
24826          *
24827          * @param source parcel to read from
24828          */
24829         public BaseSavedState(Parcel source) {
24830             this(source, null);
24831         }
24832
24833         /**
24834          * Constructor used when reading from a parcel using a given class loader.
24835          * Reads the state of the superclass.
24836          *
24837          * @param source parcel to read from
24838          * @param loader ClassLoader to use for reading
24839          */
24840         public BaseSavedState(Parcel source, ClassLoader loader) {
24841             super(source, loader);
24842             mSavedData = source.readInt();
24843             mStartActivityRequestWhoSaved = source.readString();
24844             mIsAutofilled = source.readBoolean();
24845             mAccessibilityViewId = source.readInt();
24846         }
24847
24848         /**
24849          * Constructor called by derived classes when creating their SavedState objects
24850          *
24851          * @param superState The state of the superclass of this view
24852          */
24853         public BaseSavedState(Parcelable superState) {
24854             super(superState);
24855         }
24856
24857         @Override
24858         public void writeToParcel(Parcel out, int flags) {
24859             super.writeToParcel(out, flags);
24860
24861             out.writeInt(mSavedData);
24862             out.writeString(mStartActivityRequestWhoSaved);
24863             out.writeBoolean(mIsAutofilled);
24864             out.writeInt(mAccessibilityViewId);
24865         }
24866
24867         public static final Parcelable.Creator<BaseSavedState> CREATOR
24868                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24869             @Override
24870             public BaseSavedState createFromParcel(Parcel in) {
24871                 return new BaseSavedState(in);
24872             }
24873
24874             @Override
24875             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24876                 return new BaseSavedState(in, loader);
24877             }
24878
24879             @Override
24880             public BaseSavedState[] newArray(int size) {
24881                 return new BaseSavedState[size];
24882             }
24883         };
24884     }
24885
24886     /**
24887      * A set of information given to a view when it is attached to its parent
24888      * window.
24889      */
24890     final static class AttachInfo {
24891         interface Callbacks {
24892             void playSoundEffect(int effectId);
24893             boolean performHapticFeedback(int effectId, boolean always);
24894         }
24895
24896         /**
24897          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24898          * to a Handler. This class contains the target (View) to invalidate and
24899          * the coordinates of the dirty rectangle.
24900          *
24901          * For performance purposes, this class also implements a pool of up to
24902          * POOL_LIMIT objects that get reused. This reduces memory allocations
24903          * whenever possible.
24904          */
24905         static class InvalidateInfo {
24906             private static final int POOL_LIMIT = 10;
24907
24908             private static final SynchronizedPool<InvalidateInfo> sPool =
24909                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24910
24911             View target;
24912
24913             int left;
24914             int top;
24915             int right;
24916             int bottom;
24917
24918             public static InvalidateInfo obtain() {
24919                 InvalidateInfo instance = sPool.acquire();
24920                 return (instance != null) ? instance : new InvalidateInfo();
24921             }
24922
24923             public void recycle() {
24924                 target = null;
24925                 sPool.release(this);
24926             }
24927         }
24928
24929         final IWindowSession mSession;
24930
24931         final IWindow mWindow;
24932
24933         final IBinder mWindowToken;
24934
24935         Display mDisplay;
24936
24937         final Callbacks mRootCallbacks;
24938
24939         IWindowId mIWindowId;
24940         WindowId mWindowId;
24941
24942         /**
24943          * The top view of the hierarchy.
24944          */
24945         View mRootView;
24946
24947         IBinder mPanelParentWindowToken;
24948
24949         boolean mHardwareAccelerated;
24950         boolean mHardwareAccelerationRequested;
24951         ThreadedRenderer mThreadedRenderer;
24952         List<RenderNode> mPendingAnimatingRenderNodes;
24953
24954         /**
24955          * The state of the display to which the window is attached, as reported
24956          * by {@link Display#getState()}.  Note that the display state constants
24957          * declared by {@link Display} do not exactly line up with the screen state
24958          * constants declared by {@link View} (there are more display states than
24959          * screen states).
24960          */
24961         int mDisplayState = Display.STATE_UNKNOWN;
24962
24963         /**
24964          * Scale factor used by the compatibility mode
24965          */
24966         float mApplicationScale;
24967
24968         /**
24969          * Indicates whether the application is in compatibility mode
24970          */
24971         boolean mScalingRequired;
24972
24973         /**
24974          * Left position of this view's window
24975          */
24976         int mWindowLeft;
24977
24978         /**
24979          * Top position of this view's window
24980          */
24981         int mWindowTop;
24982
24983         /**
24984          * Indicates whether views need to use 32-bit drawing caches
24985          */
24986         boolean mUse32BitDrawingCache;
24987
24988         /**
24989          * For windows that are full-screen but using insets to layout inside
24990          * of the screen areas, these are the current insets to appear inside
24991          * the overscan area of the display.
24992          */
24993         final Rect mOverscanInsets = new Rect();
24994
24995         /**
24996          * For windows that are full-screen but using insets to layout inside
24997          * of the screen decorations, these are the current insets for the
24998          * content of the window.
24999          */
25000         final Rect mContentInsets = new Rect();
25001
25002         /**
25003          * For windows that are full-screen but using insets to layout inside
25004          * of the screen decorations, these are the current insets for the
25005          * actual visible parts of the window.
25006          */
25007         final Rect mVisibleInsets = new Rect();
25008
25009         /**
25010          * For windows that are full-screen but using insets to layout inside
25011          * of the screen decorations, these are the current insets for the
25012          * stable system windows.
25013          */
25014         final Rect mStableInsets = new Rect();
25015
25016         /**
25017          * For windows that include areas that are not covered by real surface these are the outsets
25018          * for real surface.
25019          */
25020         final Rect mOutsets = new Rect();
25021
25022         /**
25023          * In multi-window we force show the navigation bar. Because we don't want that the surface
25024          * size changes in this mode, we instead have a flag whether the navigation bar size should
25025          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
25026          */
25027         boolean mAlwaysConsumeNavBar;
25028
25029         /**
25030          * The internal insets given by this window.  This value is
25031          * supplied by the client (through
25032          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
25033          * be given to the window manager when changed to be used in laying
25034          * out windows behind it.
25035          */
25036         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
25037                 = new ViewTreeObserver.InternalInsetsInfo();
25038
25039         /**
25040          * Set to true when mGivenInternalInsets is non-empty.
25041          */
25042         boolean mHasNonEmptyGivenInternalInsets;
25043
25044         /**
25045          * All views in the window's hierarchy that serve as scroll containers,
25046          * used to determine if the window can be resized or must be panned
25047          * to adjust for a soft input area.
25048          */
25049         final ArrayList<View> mScrollContainers = new ArrayList<View>();
25050
25051         final KeyEvent.DispatcherState mKeyDispatchState
25052                 = new KeyEvent.DispatcherState();
25053
25054         /**
25055          * Indicates whether the view's window currently has the focus.
25056          */
25057         boolean mHasWindowFocus;
25058
25059         /**
25060          * The current visibility of the window.
25061          */
25062         int mWindowVisibility;
25063
25064         /**
25065          * Indicates the time at which drawing started to occur.
25066          */
25067         long mDrawingTime;
25068
25069         /**
25070          * Indicates whether or not ignoring the DIRTY_MASK flags.
25071          */
25072         boolean mIgnoreDirtyState;
25073
25074         /**
25075          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
25076          * to avoid clearing that flag prematurely.
25077          */
25078         boolean mSetIgnoreDirtyState = false;
25079
25080         /**
25081          * Indicates whether the view's window is currently in touch mode.
25082          */
25083         boolean mInTouchMode;
25084
25085         /**
25086          * Indicates whether the view has requested unbuffered input dispatching for the current
25087          * event stream.
25088          */
25089         boolean mUnbufferedDispatchRequested;
25090
25091         /**
25092          * Indicates that ViewAncestor should trigger a global layout change
25093          * the next time it performs a traversal
25094          */
25095         boolean mRecomputeGlobalAttributes;
25096
25097         /**
25098          * Always report new attributes at next traversal.
25099          */
25100         boolean mForceReportNewAttributes;
25101
25102         /**
25103          * Set during a traveral if any views want to keep the screen on.
25104          */
25105         boolean mKeepScreenOn;
25106
25107         /**
25108          * Set during a traveral if the light center needs to be updated.
25109          */
25110         boolean mNeedsUpdateLightCenter;
25111
25112         /**
25113          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
25114          */
25115         int mSystemUiVisibility;
25116
25117         /**
25118          * Hack to force certain system UI visibility flags to be cleared.
25119          */
25120         int mDisabledSystemUiVisibility;
25121
25122         /**
25123          * Last global system UI visibility reported by the window manager.
25124          */
25125         int mGlobalSystemUiVisibility = -1;
25126
25127         /**
25128          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
25129          * attached.
25130          */
25131         boolean mHasSystemUiListeners;
25132
25133         /**
25134          * Set if the window has requested to extend into the overscan region
25135          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
25136          */
25137         boolean mOverscanRequested;
25138
25139         /**
25140          * Set if the visibility of any views has changed.
25141          */
25142         boolean mViewVisibilityChanged;
25143
25144         /**
25145          * Set to true if a view has been scrolled.
25146          */
25147         boolean mViewScrollChanged;
25148
25149         /**
25150          * Set to true if high contrast mode enabled
25151          */
25152         boolean mHighContrastText;
25153
25154         /**
25155          * Set to true if a pointer event is currently being handled.
25156          */
25157         boolean mHandlingPointerEvent;
25158
25159         /**
25160          * Global to the view hierarchy used as a temporary for dealing with
25161          * x/y points in the transparent region computations.
25162          */
25163         final int[] mTransparentLocation = new int[2];
25164
25165         /**
25166          * Global to the view hierarchy used as a temporary for dealing with
25167          * x/y points in the ViewGroup.invalidateChild implementation.
25168          */
25169         final int[] mInvalidateChildLocation = new int[2];
25170
25171         /**
25172          * Global to the view hierarchy used as a temporary for dealing with
25173          * computing absolute on-screen location.
25174          */
25175         final int[] mTmpLocation = new int[2];
25176
25177         /**
25178          * Global to the view hierarchy used as a temporary for dealing with
25179          * x/y location when view is transformed.
25180          */
25181         final float[] mTmpTransformLocation = new float[2];
25182
25183         /**
25184          * The view tree observer used to dispatch global events like
25185          * layout, pre-draw, touch mode change, etc.
25186          */
25187         final ViewTreeObserver mTreeObserver;
25188
25189         /**
25190          * A Canvas used by the view hierarchy to perform bitmap caching.
25191          */
25192         Canvas mCanvas;
25193
25194         /**
25195          * The view root impl.
25196          */
25197         final ViewRootImpl mViewRootImpl;
25198
25199         /**
25200          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
25201          * handler can be used to pump events in the UI events queue.
25202          */
25203         final Handler mHandler;
25204
25205         /**
25206          * Temporary for use in computing invalidate rectangles while
25207          * calling up the hierarchy.
25208          */
25209         final Rect mTmpInvalRect = new Rect();
25210
25211         /**
25212          * Temporary for use in computing hit areas with transformed views
25213          */
25214         final RectF mTmpTransformRect = new RectF();
25215
25216         /**
25217          * Temporary for use in computing hit areas with transformed views
25218          */
25219         final RectF mTmpTransformRect1 = new RectF();
25220
25221         /**
25222          * Temporary list of rectanges.
25223          */
25224         final List<RectF> mTmpRectList = new ArrayList<>();
25225
25226         /**
25227          * Temporary for use in transforming invalidation rect
25228          */
25229         final Matrix mTmpMatrix = new Matrix();
25230
25231         /**
25232          * Temporary for use in transforming invalidation rect
25233          */
25234         final Transformation mTmpTransformation = new Transformation();
25235
25236         /**
25237          * Temporary for use in querying outlines from OutlineProviders
25238          */
25239         final Outline mTmpOutline = new Outline();
25240
25241         /**
25242          * Temporary list for use in collecting focusable descendents of a view.
25243          */
25244         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25245
25246         /**
25247          * The id of the window for accessibility purposes.
25248          */
25249         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25250
25251         /**
25252          * Flags related to accessibility processing.
25253          *
25254          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25255          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25256          */
25257         int mAccessibilityFetchFlags;
25258
25259         /**
25260          * The drawable for highlighting accessibility focus.
25261          */
25262         Drawable mAccessibilityFocusDrawable;
25263
25264         /**
25265          * The drawable for highlighting autofilled views.
25266          *
25267          * @see #isAutofilled()
25268          */
25269         Drawable mAutofilledDrawable;
25270
25271         /**
25272          * Show where the margins, bounds and layout bounds are for each view.
25273          */
25274         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25275
25276         /**
25277          * Point used to compute visible regions.
25278          */
25279         final Point mPoint = new Point();
25280
25281         /**
25282          * Used to track which View originated a requestLayout() call, used when
25283          * requestLayout() is called during layout.
25284          */
25285         View mViewRequestingLayout;
25286
25287         /**
25288          * Used to track views that need (at least) a partial relayout at their current size
25289          * during the next traversal.
25290          */
25291         List<View> mPartialLayoutViews = new ArrayList<>();
25292
25293         /**
25294          * Swapped with mPartialLayoutViews during layout to avoid concurrent
25295          * modification. Lazily assigned during ViewRootImpl layout.
25296          */
25297         List<View> mEmptyPartialLayoutViews;
25298
25299         /**
25300          * Used to track the identity of the current drag operation.
25301          */
25302         IBinder mDragToken;
25303
25304         /**
25305          * The drag shadow surface for the current drag operation.
25306          */
25307         public Surface mDragSurface;
25308
25309
25310         /**
25311          * The view that currently has a tooltip displayed.
25312          */
25313         View mTooltipHost;
25314
25315         /**
25316          * Creates a new set of attachment information with the specified
25317          * events handler and thread.
25318          *
25319          * @param handler the events handler the view must use
25320          */
25321         AttachInfo(IWindowSession session, IWindow window, Display display,
25322                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25323                 Context context) {
25324             mSession = session;
25325             mWindow = window;
25326             mWindowToken = window.asBinder();
25327             mDisplay = display;
25328             mViewRootImpl = viewRootImpl;
25329             mHandler = handler;
25330             mRootCallbacks = effectPlayer;
25331             mTreeObserver = new ViewTreeObserver(context);
25332         }
25333     }
25334
25335     /**
25336      * <p>ScrollabilityCache holds various fields used by a View when scrolling
25337      * is supported. This avoids keeping too many unused fields in most
25338      * instances of View.</p>
25339      */
25340     private static class ScrollabilityCache implements Runnable {
25341
25342         /**
25343          * Scrollbars are not visible
25344          */
25345         public static final int OFF = 0;
25346
25347         /**
25348          * Scrollbars are visible
25349          */
25350         public static final int ON = 1;
25351
25352         /**
25353          * Scrollbars are fading away
25354          */
25355         public static final int FADING = 2;
25356
25357         public boolean fadeScrollBars;
25358
25359         public int fadingEdgeLength;
25360         public int scrollBarDefaultDelayBeforeFade;
25361         public int scrollBarFadeDuration;
25362
25363         public int scrollBarSize;
25364         public int scrollBarMinTouchTarget;
25365         public ScrollBarDrawable scrollBar;
25366         public float[] interpolatorValues;
25367         public View host;
25368
25369         public final Paint paint;
25370         public final Matrix matrix;
25371         public Shader shader;
25372
25373         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25374
25375         private static final float[] OPAQUE = { 255 };
25376         private static final float[] TRANSPARENT = { 0.0f };
25377
25378         /**
25379          * When fading should start. This time moves into the future every time
25380          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25381          */
25382         public long fadeStartTime;
25383
25384
25385         /**
25386          * The current state of the scrollbars: ON, OFF, or FADING
25387          */
25388         public int state = OFF;
25389
25390         private int mLastColor;
25391
25392         public final Rect mScrollBarBounds = new Rect();
25393         public final Rect mScrollBarTouchBounds = new Rect();
25394
25395         public static final int NOT_DRAGGING = 0;
25396         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25397         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25398         public int mScrollBarDraggingState = NOT_DRAGGING;
25399
25400         public float mScrollBarDraggingPos = 0;
25401
25402         public ScrollabilityCache(ViewConfiguration configuration, View host) {
25403             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25404             scrollBarSize = configuration.getScaledScrollBarSize();
25405             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25406             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25407             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25408
25409             paint = new Paint();
25410             matrix = new Matrix();
25411             // use use a height of 1, and then wack the matrix each time we
25412             // actually use it.
25413             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25414             paint.setShader(shader);
25415             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25416
25417             this.host = host;
25418         }
25419
25420         public void setFadeColor(int color) {
25421             if (color != mLastColor) {
25422                 mLastColor = color;
25423
25424                 if (color != 0) {
25425                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25426                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25427                     paint.setShader(shader);
25428                     // Restore the default transfer mode (src_over)
25429                     paint.setXfermode(null);
25430                 } else {
25431                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25432                     paint.setShader(shader);
25433                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25434                 }
25435             }
25436         }
25437
25438         public void run() {
25439             long now = AnimationUtils.currentAnimationTimeMillis();
25440             if (now >= fadeStartTime) {
25441
25442                 // the animation fades the scrollbars out by changing
25443                 // the opacity (alpha) from fully opaque to fully
25444                 // transparent
25445                 int nextFrame = (int) now;
25446                 int framesCount = 0;
25447
25448                 Interpolator interpolator = scrollBarInterpolator;
25449
25450                 // Start opaque
25451                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25452
25453                 // End transparent
25454                 nextFrame += scrollBarFadeDuration;
25455                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25456
25457                 state = FADING;
25458
25459                 // Kick off the fade animation
25460                 host.invalidate(true);
25461             }
25462         }
25463     }
25464
25465     /**
25466      * Resuable callback for sending
25467      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25468      */
25469     private class SendViewScrolledAccessibilityEvent implements Runnable {
25470         public volatile boolean mIsPending;
25471
25472         public void run() {
25473             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25474             mIsPending = false;
25475         }
25476     }
25477
25478     /**
25479      * <p>
25480      * This class represents a delegate that can be registered in a {@link View}
25481      * to enhance accessibility support via composition rather via inheritance.
25482      * It is specifically targeted to widget developers that extend basic View
25483      * classes i.e. classes in package android.view, that would like their
25484      * applications to be backwards compatible.
25485      * </p>
25486      * <div class="special reference">
25487      * <h3>Developer Guides</h3>
25488      * <p>For more information about making applications accessible, read the
25489      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25490      * developer guide.</p>
25491      * </div>
25492      * <p>
25493      * A scenario in which a developer would like to use an accessibility delegate
25494      * is overriding a method introduced in a later API version than the minimal API
25495      * version supported by the application. For example, the method
25496      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25497      * in API version 4 when the accessibility APIs were first introduced. If a
25498      * developer would like his application to run on API version 4 devices (assuming
25499      * all other APIs used by the application are version 4 or lower) and take advantage
25500      * of this method, instead of overriding the method which would break the application's
25501      * backwards compatibility, he can override the corresponding method in this
25502      * delegate and register the delegate in the target View if the API version of
25503      * the system is high enough, i.e. the API version is the same as or higher than the API
25504      * version that introduced
25505      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25506      * </p>
25507      * <p>
25508      * Here is an example implementation:
25509      * </p>
25510      * <code><pre><p>
25511      * if (Build.VERSION.SDK_INT >= 14) {
25512      *     // If the API version is equal of higher than the version in
25513      *     // which onInitializeAccessibilityNodeInfo was introduced we
25514      *     // register a delegate with a customized implementation.
25515      *     View view = findViewById(R.id.view_id);
25516      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25517      *         public void onInitializeAccessibilityNodeInfo(View host,
25518      *                 AccessibilityNodeInfo info) {
25519      *             // Let the default implementation populate the info.
25520      *             super.onInitializeAccessibilityNodeInfo(host, info);
25521      *             // Set some other information.
25522      *             info.setEnabled(host.isEnabled());
25523      *         }
25524      *     });
25525      * }
25526      * </code></pre></p>
25527      * <p>
25528      * This delegate contains methods that correspond to the accessibility methods
25529      * in View. If a delegate has been specified the implementation in View hands
25530      * off handling to the corresponding method in this delegate. The default
25531      * implementation the delegate methods behaves exactly as the corresponding
25532      * method in View for the case of no accessibility delegate been set. Hence,
25533      * to customize the behavior of a View method, clients can override only the
25534      * corresponding delegate method without altering the behavior of the rest
25535      * accessibility related methods of the host view.
25536      * </p>
25537      * <p>
25538      * <strong>Note:</strong> On platform versions prior to
25539      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25540      * views in the {@code android.widget.*} package are called <i>before</i>
25541      * host methods. This prevents certain properties such as class name from
25542      * being modified by overriding
25543      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25544      * as any changes will be overwritten by the host class.
25545      * <p>
25546      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25547      * methods are called <i>after</i> host methods, which all properties to be
25548      * modified without being overwritten by the host class.
25549      */
25550     public static class AccessibilityDelegate {
25551
25552         /**
25553          * Sends an accessibility event of the given type. If accessibility is not
25554          * enabled this method has no effect.
25555          * <p>
25556          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25557          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25558          * been set.
25559          * </p>
25560          *
25561          * @param host The View hosting the delegate.
25562          * @param eventType The type of the event to send.
25563          *
25564          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25565          */
25566         public void sendAccessibilityEvent(View host, int eventType) {
25567             host.sendAccessibilityEventInternal(eventType);
25568         }
25569
25570         /**
25571          * Performs the specified accessibility action on the view. For
25572          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25573          * <p>
25574          * The default implementation behaves as
25575          * {@link View#performAccessibilityAction(int, Bundle)
25576          *  View#performAccessibilityAction(int, Bundle)} for the case of
25577          *  no accessibility delegate been set.
25578          * </p>
25579          *
25580          * @param action The action to perform.
25581          * @return Whether the action was performed.
25582          *
25583          * @see View#performAccessibilityAction(int, Bundle)
25584          *      View#performAccessibilityAction(int, Bundle)
25585          */
25586         public boolean performAccessibilityAction(View host, int action, Bundle args) {
25587             return host.performAccessibilityActionInternal(action, args);
25588         }
25589
25590         /**
25591          * Sends an accessibility event. This method behaves exactly as
25592          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25593          * empty {@link AccessibilityEvent} and does not perform a check whether
25594          * accessibility is enabled.
25595          * <p>
25596          * The default implementation behaves as
25597          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25598          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25599          * the case of no accessibility delegate been set.
25600          * </p>
25601          *
25602          * @param host The View hosting the delegate.
25603          * @param event The event to send.
25604          *
25605          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25606          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25607          */
25608         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25609             host.sendAccessibilityEventUncheckedInternal(event);
25610         }
25611
25612         /**
25613          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25614          * to its children for adding their text content to the event.
25615          * <p>
25616          * The default implementation behaves as
25617          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25618          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25619          * the case of no accessibility delegate been set.
25620          * </p>
25621          *
25622          * @param host The View hosting the delegate.
25623          * @param event The event.
25624          * @return True if the event population was completed.
25625          *
25626          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25627          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25628          */
25629         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25630             return host.dispatchPopulateAccessibilityEventInternal(event);
25631         }
25632
25633         /**
25634          * Gives a chance to the host View to populate the accessibility event with its
25635          * text content.
25636          * <p>
25637          * The default implementation behaves as
25638          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25639          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25640          * the case of no accessibility delegate been set.
25641          * </p>
25642          *
25643          * @param host The View hosting the delegate.
25644          * @param event The accessibility event which to populate.
25645          *
25646          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25647          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25648          */
25649         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25650             host.onPopulateAccessibilityEventInternal(event);
25651         }
25652
25653         /**
25654          * Initializes an {@link AccessibilityEvent} with information about the
25655          * the host View which is the event source.
25656          * <p>
25657          * The default implementation behaves as
25658          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25659          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25660          * the case of no accessibility delegate been set.
25661          * </p>
25662          *
25663          * @param host The View hosting the delegate.
25664          * @param event The event to initialize.
25665          *
25666          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25667          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25668          */
25669         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25670             host.onInitializeAccessibilityEventInternal(event);
25671         }
25672
25673         /**
25674          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25675          * <p>
25676          * The default implementation behaves as
25677          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25678          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25679          * the case of no accessibility delegate been set.
25680          * </p>
25681          *
25682          * @param host The View hosting the delegate.
25683          * @param info The instance to initialize.
25684          *
25685          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25686          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25687          */
25688         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25689             host.onInitializeAccessibilityNodeInfoInternal(info);
25690         }
25691
25692         /**
25693          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25694          * additional data.
25695          * <p>
25696          * This method only needs to be implemented if the View offers to provide additional data.
25697          * </p>
25698          * <p>
25699          * The default implementation behaves as
25700          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25701          * the case where no accessibility delegate is set.
25702          * </p>
25703          *
25704          * @param host The View hosting the delegate. Never {@code null}.
25705          * @param info The info to which to add the extra data. Never {@code null}.
25706          * @param extraDataKey A key specifying the type of extra data to add to the info. The
25707          *                     extra data should be added to the {@link Bundle} returned by
25708          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25709          *                     {@code null}.
25710          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25711          *                  May be {@code null} if the if the service provided no arguments.
25712          *
25713          * @see AccessibilityNodeInfo#setExtraAvailableData
25714          */
25715         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25716                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25717                 @Nullable Bundle arguments) {
25718             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25719         }
25720
25721         /**
25722          * Called when a child of the host View has requested sending an
25723          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25724          * to augment the event.
25725          * <p>
25726          * The default implementation behaves as
25727          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25728          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25729          * the case of no accessibility delegate been set.
25730          * </p>
25731          *
25732          * @param host The View hosting the delegate.
25733          * @param child The child which requests sending the event.
25734          * @param event The event to be sent.
25735          * @return True if the event should be sent
25736          *
25737          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25738          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25739          */
25740         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25741                 AccessibilityEvent event) {
25742             return host.onRequestSendAccessibilityEventInternal(child, event);
25743         }
25744
25745         /**
25746          * Gets the provider for managing a virtual view hierarchy rooted at this View
25747          * and reported to {@link android.accessibilityservice.AccessibilityService}s
25748          * that explore the window content.
25749          * <p>
25750          * The default implementation behaves as
25751          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25752          * the case of no accessibility delegate been set.
25753          * </p>
25754          *
25755          * @return The provider.
25756          *
25757          * @see AccessibilityNodeProvider
25758          */
25759         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25760             return null;
25761         }
25762
25763         /**
25764          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25765          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25766          * This method is responsible for obtaining an accessibility node info from a
25767          * pool of reusable instances and calling
25768          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25769          * view to initialize the former.
25770          * <p>
25771          * <strong>Note:</strong> The client is responsible for recycling the obtained
25772          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25773          * creation.
25774          * </p>
25775          * <p>
25776          * The default implementation behaves as
25777          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25778          * the case of no accessibility delegate been set.
25779          * </p>
25780          * @return A populated {@link AccessibilityNodeInfo}.
25781          *
25782          * @see AccessibilityNodeInfo
25783          *
25784          * @hide
25785          */
25786         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25787             return host.createAccessibilityNodeInfoInternal();
25788         }
25789     }
25790
25791     private static class MatchIdPredicate implements Predicate<View> {
25792         public int mId;
25793
25794         @Override
25795         public boolean test(View view) {
25796             return (view.mID == mId);
25797         }
25798     }
25799
25800     private static class MatchLabelForPredicate implements Predicate<View> {
25801         private int mLabeledId;
25802
25803         @Override
25804         public boolean test(View view) {
25805             return (view.mLabelForId == mLabeledId);
25806         }
25807     }
25808
25809     private class SendViewStateChangedAccessibilityEvent implements Runnable {
25810         private int mChangeTypes = 0;
25811         private boolean mPosted;
25812         private boolean mPostedWithDelay;
25813         private long mLastEventTimeMillis;
25814
25815         @Override
25816         public void run() {
25817             mPosted = false;
25818             mPostedWithDelay = false;
25819             mLastEventTimeMillis = SystemClock.uptimeMillis();
25820             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25821                 final AccessibilityEvent event = AccessibilityEvent.obtain();
25822                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25823                 event.setContentChangeTypes(mChangeTypes);
25824                 sendAccessibilityEventUnchecked(event);
25825             }
25826             mChangeTypes = 0;
25827         }
25828
25829         public void runOrPost(int changeType) {
25830             mChangeTypes |= changeType;
25831
25832             // If this is a live region or the child of a live region, collect
25833             // all events from this frame and send them on the next frame.
25834             if (inLiveRegion()) {
25835                 // If we're already posted with a delay, remove that.
25836                 if (mPostedWithDelay) {
25837                     removeCallbacks(this);
25838                     mPostedWithDelay = false;
25839                 }
25840                 // Only post if we're not already posted.
25841                 if (!mPosted) {
25842                     post(this);
25843                     mPosted = true;
25844                 }
25845                 return;
25846             }
25847
25848             if (mPosted) {
25849                 return;
25850             }
25851
25852             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25853             final long minEventIntevalMillis =
25854                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25855             if (timeSinceLastMillis >= minEventIntevalMillis) {
25856                 removeCallbacks(this);
25857                 run();
25858             } else {
25859                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25860                 mPostedWithDelay = true;
25861             }
25862         }
25863     }
25864
25865     private boolean inLiveRegion() {
25866         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25867             return true;
25868         }
25869
25870         ViewParent parent = getParent();
25871         while (parent instanceof View) {
25872             if (((View) parent).getAccessibilityLiveRegion()
25873                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25874                 return true;
25875             }
25876             parent = parent.getParent();
25877         }
25878
25879         return false;
25880     }
25881
25882     /**
25883      * Dump all private flags in readable format, useful for documentation and
25884      * sanity checking.
25885      */
25886     private static void dumpFlags() {
25887         final HashMap<String, String> found = Maps.newHashMap();
25888         try {
25889             for (Field field : View.class.getDeclaredFields()) {
25890                 final int modifiers = field.getModifiers();
25891                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25892                     if (field.getType().equals(int.class)) {
25893                         final int value = field.getInt(null);
25894                         dumpFlag(found, field.getName(), value);
25895                     } else if (field.getType().equals(int[].class)) {
25896                         final int[] values = (int[]) field.get(null);
25897                         for (int i = 0; i < values.length; i++) {
25898                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25899                         }
25900                     }
25901                 }
25902             }
25903         } catch (IllegalAccessException e) {
25904             throw new RuntimeException(e);
25905         }
25906
25907         final ArrayList<String> keys = Lists.newArrayList();
25908         keys.addAll(found.keySet());
25909         Collections.sort(keys);
25910         for (String key : keys) {
25911             Log.d(VIEW_LOG_TAG, found.get(key));
25912         }
25913     }
25914
25915     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25916         // Sort flags by prefix, then by bits, always keeping unique keys
25917         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25918         final int prefix = name.indexOf('_');
25919         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25920         final String output = bits + " " + name;
25921         found.put(key, output);
25922     }
25923
25924     /** {@hide} */
25925     public void encode(@NonNull ViewHierarchyEncoder stream) {
25926         stream.beginObject(this);
25927         encodeProperties(stream);
25928         stream.endObject();
25929     }
25930
25931     /** {@hide} */
25932     @CallSuper
25933     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25934         Object resolveId = ViewDebug.resolveId(getContext(), mID);
25935         if (resolveId instanceof String) {
25936             stream.addProperty("id", (String) resolveId);
25937         } else {
25938             stream.addProperty("id", mID);
25939         }
25940
25941         stream.addProperty("misc:transformation.alpha",
25942                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25943         stream.addProperty("misc:transitionName", getTransitionName());
25944
25945         // layout
25946         stream.addProperty("layout:left", mLeft);
25947         stream.addProperty("layout:right", mRight);
25948         stream.addProperty("layout:top", mTop);
25949         stream.addProperty("layout:bottom", mBottom);
25950         stream.addProperty("layout:width", getWidth());
25951         stream.addProperty("layout:height", getHeight());
25952         stream.addProperty("layout:layoutDirection", getLayoutDirection());
25953         stream.addProperty("layout:layoutRtl", isLayoutRtl());
25954         stream.addProperty("layout:hasTransientState", hasTransientState());
25955         stream.addProperty("layout:baseline", getBaseline());
25956
25957         // layout params
25958         ViewGroup.LayoutParams layoutParams = getLayoutParams();
25959         if (layoutParams != null) {
25960             stream.addPropertyKey("layoutParams");
25961             layoutParams.encode(stream);
25962         }
25963
25964         // scrolling
25965         stream.addProperty("scrolling:scrollX", mScrollX);
25966         stream.addProperty("scrolling:scrollY", mScrollY);
25967
25968         // padding
25969         stream.addProperty("padding:paddingLeft", mPaddingLeft);
25970         stream.addProperty("padding:paddingRight", mPaddingRight);
25971         stream.addProperty("padding:paddingTop", mPaddingTop);
25972         stream.addProperty("padding:paddingBottom", mPaddingBottom);
25973         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25974         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25975         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25976         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25977         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25978
25979         // measurement
25980         stream.addProperty("measurement:minHeight", mMinHeight);
25981         stream.addProperty("measurement:minWidth", mMinWidth);
25982         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25983         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25984
25985         // drawing
25986         stream.addProperty("drawing:elevation", getElevation());
25987         stream.addProperty("drawing:translationX", getTranslationX());
25988         stream.addProperty("drawing:translationY", getTranslationY());
25989         stream.addProperty("drawing:translationZ", getTranslationZ());
25990         stream.addProperty("drawing:rotation", getRotation());
25991         stream.addProperty("drawing:rotationX", getRotationX());
25992         stream.addProperty("drawing:rotationY", getRotationY());
25993         stream.addProperty("drawing:scaleX", getScaleX());
25994         stream.addProperty("drawing:scaleY", getScaleY());
25995         stream.addProperty("drawing:pivotX", getPivotX());
25996         stream.addProperty("drawing:pivotY", getPivotY());
25997         stream.addProperty("drawing:opaque", isOpaque());
25998         stream.addProperty("drawing:alpha", getAlpha());
25999         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
26000         stream.addProperty("drawing:shadow", hasShadow());
26001         stream.addProperty("drawing:solidColor", getSolidColor());
26002         stream.addProperty("drawing:layerType", mLayerType);
26003         stream.addProperty("drawing:willNotDraw", willNotDraw());
26004         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
26005         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
26006         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
26007         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
26008
26009         // focus
26010         stream.addProperty("focus:hasFocus", hasFocus());
26011         stream.addProperty("focus:isFocused", isFocused());
26012         stream.addProperty("focus:focusable", getFocusable());
26013         stream.addProperty("focus:isFocusable", isFocusable());
26014         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
26015
26016         stream.addProperty("misc:clickable", isClickable());
26017         stream.addProperty("misc:pressed", isPressed());
26018         stream.addProperty("misc:selected", isSelected());
26019         stream.addProperty("misc:touchMode", isInTouchMode());
26020         stream.addProperty("misc:hovered", isHovered());
26021         stream.addProperty("misc:activated", isActivated());
26022
26023         stream.addProperty("misc:visibility", getVisibility());
26024         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
26025         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
26026
26027         stream.addProperty("misc:enabled", isEnabled());
26028         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
26029         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
26030
26031         // theme attributes
26032         Resources.Theme theme = getContext().getTheme();
26033         if (theme != null) {
26034             stream.addPropertyKey("theme");
26035             theme.encode(stream);
26036         }
26037
26038         // view attribute information
26039         int n = mAttributes != null ? mAttributes.length : 0;
26040         stream.addProperty("meta:__attrCount__", n/2);
26041         for (int i = 0; i < n; i += 2) {
26042             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
26043         }
26044
26045         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
26046
26047         // text
26048         stream.addProperty("text:textDirection", getTextDirection());
26049         stream.addProperty("text:textAlignment", getTextAlignment());
26050
26051         // accessibility
26052         CharSequence contentDescription = getContentDescription();
26053         stream.addProperty("accessibility:contentDescription",
26054                 contentDescription == null ? "" : contentDescription.toString());
26055         stream.addProperty("accessibility:labelFor", getLabelFor());
26056         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
26057     }
26058
26059     /**
26060      * Determine if this view is rendered on a round wearable device and is the main view
26061      * on the screen.
26062      */
26063     boolean shouldDrawRoundScrollbar() {
26064         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
26065             return false;
26066         }
26067
26068         final View rootView = getRootView();
26069         final WindowInsets insets = getRootWindowInsets();
26070
26071         int height = getHeight();
26072         int width = getWidth();
26073         int displayHeight = rootView.getHeight();
26074         int displayWidth = rootView.getWidth();
26075
26076         if (height != displayHeight || width != displayWidth) {
26077             return false;
26078         }
26079
26080         getLocationInWindow(mAttachInfo.mTmpLocation);
26081         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
26082                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
26083     }
26084
26085     /**
26086      * Sets the tooltip text which will be displayed in a small popup next to the view.
26087      * <p>
26088      * The tooltip will be displayed:
26089      * <ul>
26090      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
26091      * menu). </li>
26092      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
26093      * </ul>
26094      * <p>
26095      * <strong>Note:</strong> Do not override this method, as it will have no
26096      * effect on the text displayed in the tooltip.
26097      *
26098      * @param tooltipText the tooltip text, or null if no tooltip is required
26099      * @see #getTooltipText()
26100      * @attr ref android.R.styleable#View_tooltipText
26101      */
26102     public void setTooltipText(@Nullable CharSequence tooltipText) {
26103         if (TextUtils.isEmpty(tooltipText)) {
26104             setFlags(0, TOOLTIP);
26105             hideTooltip();
26106             mTooltipInfo = null;
26107         } else {
26108             setFlags(TOOLTIP, TOOLTIP);
26109             if (mTooltipInfo == null) {
26110                 mTooltipInfo = new TooltipInfo();
26111                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
26112                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
26113             }
26114             mTooltipInfo.mTooltipText = tooltipText;
26115             if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
26116                 mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
26117             }
26118         }
26119     }
26120
26121     /**
26122      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26123      */
26124     public void setTooltip(@Nullable CharSequence tooltipText) {
26125         setTooltipText(tooltipText);
26126     }
26127
26128     /**
26129      * Returns the view's tooltip text.
26130      *
26131      * <strong>Note:</strong> Do not override this method, as it will have no
26132      * effect on the text displayed in the tooltip. You must call
26133      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
26134      *
26135      * @return the tooltip text
26136      * @see #setTooltipText(CharSequence)
26137      * @attr ref android.R.styleable#View_tooltipText
26138      */
26139     @Nullable
26140     public CharSequence getTooltipText() {
26141         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
26142     }
26143
26144     /**
26145      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26146      */
26147     @Nullable
26148     public CharSequence getTooltip() {
26149         return getTooltipText();
26150     }
26151
26152     private boolean showTooltip(int x, int y, boolean fromLongClick) {
26153         if (mAttachInfo == null || mTooltipInfo == null) {
26154             return false;
26155         }
26156         if ((mViewFlags & ENABLED_MASK) != ENABLED) {
26157             return false;
26158         }
26159         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
26160             return false;
26161         }
26162         hideTooltip();
26163         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
26164         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
26165         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
26166         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
26167         mAttachInfo.mTooltipHost = this;
26168         return true;
26169     }
26170
26171     void hideTooltip() {
26172         if (mTooltipInfo == null) {
26173             return;
26174         }
26175         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26176         if (mTooltipInfo.mTooltipPopup == null) {
26177             return;
26178         }
26179         mTooltipInfo.mTooltipPopup.hide();
26180         mTooltipInfo.mTooltipPopup = null;
26181         mTooltipInfo.mTooltipFromLongClick = false;
26182         if (mAttachInfo != null) {
26183             mAttachInfo.mTooltipHost = null;
26184         }
26185     }
26186
26187     private boolean showLongClickTooltip(int x, int y) {
26188         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26189         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26190         return showTooltip(x, y, true);
26191     }
26192
26193     private void showHoverTooltip() {
26194         showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
26195     }
26196
26197     boolean dispatchTooltipHoverEvent(MotionEvent event) {
26198         if (mTooltipInfo == null) {
26199             return false;
26200         }
26201         switch(event.getAction()) {
26202             case MotionEvent.ACTION_HOVER_MOVE:
26203                 if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
26204                     break;
26205                 }
26206                 if (!mTooltipInfo.mTooltipFromLongClick) {
26207                     if (mTooltipInfo.mTooltipPopup == null) {
26208                         // Schedule showing the tooltip after a timeout.
26209                         mTooltipInfo.mAnchorX = (int) event.getX();
26210                         mTooltipInfo.mAnchorY = (int) event.getY();
26211                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26212                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
26213                                 ViewConfiguration.getHoverTooltipShowTimeout());
26214                     }
26215
26216                     // Hide hover-triggered tooltip after a period of inactivity.
26217                     // Match the timeout used by NativeInputManager to hide the mouse pointer
26218                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26219                     final int timeout;
26220                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26221                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
26222                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26223                     } else {
26224                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26225                     }
26226                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26227                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26228                 }
26229                 return true;
26230
26231             case MotionEvent.ACTION_HOVER_EXIT:
26232                 if (!mTooltipInfo.mTooltipFromLongClick) {
26233                     hideTooltip();
26234                 }
26235                 break;
26236         }
26237         return false;
26238     }
26239
26240     void handleTooltipKey(KeyEvent event) {
26241         switch (event.getAction()) {
26242             case KeyEvent.ACTION_DOWN:
26243                 if (event.getRepeatCount() == 0) {
26244                     hideTooltip();
26245                 }
26246                 break;
26247
26248             case KeyEvent.ACTION_UP:
26249                 handleTooltipUp();
26250                 break;
26251         }
26252     }
26253
26254     private void handleTooltipUp() {
26255         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26256             return;
26257         }
26258         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26259         postDelayed(mTooltipInfo.mHideTooltipRunnable,
26260                 ViewConfiguration.getLongPressTooltipHideTimeout());
26261     }
26262
26263     private int getFocusableAttribute(TypedArray attributes) {
26264         TypedValue val = new TypedValue();
26265         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26266             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26267                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26268             } else {
26269                 return val.data;
26270             }
26271         } else {
26272             return FOCUSABLE_AUTO;
26273         }
26274     }
26275
26276     /**
26277      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26278      * is not showing.
26279      * @hide
26280      */
26281     @TestApi
26282     public View getTooltipView() {
26283         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26284             return null;
26285         }
26286         return mTooltipInfo.mTooltipPopup.getContentView();
26287     }
26288 }