• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import android.animation.AnimatorInflater;
20 import android.animation.StateListAnimator;
21 import android.annotation.CallSuper;
22 import android.annotation.ColorInt;
23 import android.annotation.DrawableRes;
24 import android.annotation.FloatRange;
25 import android.annotation.IdRes;
26 import android.annotation.IntDef;
27 import android.annotation.IntRange;
28 import android.annotation.LayoutRes;
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.annotation.Size;
32 import android.annotation.UiThread;
33 import android.content.ClipData;
34 import android.content.Context;
35 import android.content.ContextWrapper;
36 import android.content.Intent;
37 import android.content.res.ColorStateList;
38 import android.content.res.Configuration;
39 import android.content.res.Resources;
40 import android.content.res.TypedArray;
41 import android.graphics.Bitmap;
42 import android.graphics.Canvas;
43 import android.graphics.Insets;
44 import android.graphics.Interpolator;
45 import android.graphics.LinearGradient;
46 import android.graphics.Matrix;
47 import android.graphics.Outline;
48 import android.graphics.Paint;
49 import android.graphics.PixelFormat;
50 import android.graphics.Point;
51 import android.graphics.PorterDuff;
52 import android.graphics.PorterDuffXfermode;
53 import android.graphics.Rect;
54 import android.graphics.RectF;
55 import android.graphics.Region;
56 import android.graphics.Shader;
57 import android.graphics.drawable.ColorDrawable;
58 import android.graphics.drawable.Drawable;
59 import android.hardware.display.DisplayManagerGlobal;
60 import android.os.Build.VERSION_CODES;
61 import android.os.Bundle;
62 import android.os.Handler;
63 import android.os.IBinder;
64 import android.os.Parcel;
65 import android.os.Parcelable;
66 import android.os.RemoteException;
67 import android.os.SystemClock;
68 import android.os.SystemProperties;
69 import android.os.Trace;
70 import android.text.TextUtils;
71 import android.util.AttributeSet;
72 import android.util.FloatProperty;
73 import android.util.LayoutDirection;
74 import android.util.Log;
75 import android.util.LongSparseLongArray;
76 import android.util.Pools.SynchronizedPool;
77 import android.util.Property;
78 import android.util.SparseArray;
79 import android.util.StateSet;
80 import android.util.SuperNotCalledException;
81 import android.util.TypedValue;
82 import android.view.ContextMenu.ContextMenuInfo;
83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
85 import android.view.AccessibilityIterators.TextSegmentIterator;
86 import android.view.AccessibilityIterators.WordTextSegmentIterator;
87 import android.view.accessibility.AccessibilityEvent;
88 import android.view.accessibility.AccessibilityEventSource;
89 import android.view.accessibility.AccessibilityManager;
90 import android.view.accessibility.AccessibilityNodeInfo;
91 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
92 import android.view.accessibility.AccessibilityNodeProvider;
93 import android.view.animation.Animation;
94 import android.view.animation.AnimationUtils;
95 import android.view.animation.Transformation;
96 import android.view.inputmethod.EditorInfo;
97 import android.view.inputmethod.InputConnection;
98 import android.view.inputmethod.InputMethodManager;
99 import android.widget.Checkable;
100 import android.widget.FrameLayout;
101 import android.widget.ScrollBarDrawable;
102 import static android.os.Build.VERSION_CODES.*;
103 import static java.lang.Math.max;
104 
105 import com.android.internal.R;
106 import com.android.internal.util.Predicate;
107 import com.android.internal.view.menu.MenuBuilder;
108 import com.android.internal.widget.ScrollBarUtils;
109 import com.google.android.collect.Lists;
110 import com.google.android.collect.Maps;
111 
112 import java.lang.NullPointerException;
113 import java.lang.annotation.Retention;
114 import java.lang.annotation.RetentionPolicy;
115 import java.lang.ref.WeakReference;
116 import java.lang.reflect.Field;
117 import java.lang.reflect.InvocationTargetException;
118 import java.lang.reflect.Method;
119 import java.lang.reflect.Modifier;
120 import java.util.ArrayList;
121 import java.util.Arrays;
122 import java.util.Collections;
123 import java.util.HashMap;
124 import java.util.List;
125 import java.util.Locale;
126 import java.util.Map;
127 import java.util.concurrent.CopyOnWriteArrayList;
128 import java.util.concurrent.atomic.AtomicInteger;
129 
130 /**
131  * <p>
132  * This class represents the basic building block for user interface components. A View
133  * occupies a rectangular area on the screen and is responsible for drawing and
134  * event handling. View is the base class for <em>widgets</em>, which are
135  * used to create interactive UI components (buttons, text fields, etc.). The
136  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
137  * are invisible containers that hold other Views (or other ViewGroups) and define
138  * their layout properties.
139  * </p>
140  *
141  * <div class="special reference">
142  * <h3>Developer Guides</h3>
143  * <p>For information about using this class to develop your application's user interface,
144  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
145  * </div>
146  *
147  * <a name="Using"></a>
148  * <h3>Using Views</h3>
149  * <p>
150  * All of the views in a window are arranged in a single tree. You can add views
151  * either from code or by specifying a tree of views in one or more XML layout
152  * files. There are many specialized subclasses of views that act as controls or
153  * are capable of displaying text, images, or other content.
154  * </p>
155  * <p>
156  * Once you have created a tree of views, there are typically a few types of
157  * common operations you may wish to perform:
158  * <ul>
159  * <li><strong>Set properties:</strong> for example setting the text of a
160  * {@link android.widget.TextView}. The available properties and the methods
161  * that set them will vary among the different subclasses of views. Note that
162  * properties that are known at build time can be set in the XML layout
163  * files.</li>
164  * <li><strong>Set focus:</strong> The framework will handle moving focus in
165  * response to user input. To force focus to a specific view, call
166  * {@link #requestFocus}.</li>
167  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
168  * that will be notified when something interesting happens to the view. For
169  * example, all views will let you set a listener to be notified when the view
170  * gains or loses focus. You can register such a listener using
171  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
172  * Other view subclasses offer more specialized listeners. For example, a Button
173  * exposes a listener to notify clients when the button is clicked.</li>
174  * <li><strong>Set visibility:</strong> You can hide or show views using
175  * {@link #setVisibility(int)}.</li>
176  * </ul>
177  * </p>
178  * <p><em>
179  * Note: The Android framework is responsible for measuring, laying out and
180  * drawing views. You should not call methods that perform these actions on
181  * views yourself unless you are actually implementing a
182  * {@link android.view.ViewGroup}.
183  * </em></p>
184  *
185  * <a name="Lifecycle"></a>
186  * <h3>Implementing a Custom View</h3>
187  *
188  * <p>
189  * To implement a custom view, you will usually begin by providing overrides for
190  * some of the standard methods that the framework calls on all views. You do
191  * not need to override all of these methods. In fact, you can start by just
192  * overriding {@link #onDraw(android.graphics.Canvas)}.
193  * <table border="2" width="85%" align="center" cellpadding="5">
194  *     <thead>
195  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
196  *     </thead>
197  *
198  *     <tbody>
199  *     <tr>
200  *         <td rowspan="2">Creation</td>
201  *         <td>Constructors</td>
202  *         <td>There is a form of the constructor that are called when the view
203  *         is created from code and a form that is called when the view is
204  *         inflated from a layout file. The second form should parse and apply
205  *         any attributes defined in the layout file.
206  *         </td>
207  *     </tr>
208  *     <tr>
209  *         <td><code>{@link #onFinishInflate()}</code></td>
210  *         <td>Called after a view and all of its children has been inflated
211  *         from XML.</td>
212  *     </tr>
213  *
214  *     <tr>
215  *         <td rowspan="3">Layout</td>
216  *         <td><code>{@link #onMeasure(int, int)}</code></td>
217  *         <td>Called to determine the size requirements for this view and all
218  *         of its children.
219  *         </td>
220  *     </tr>
221  *     <tr>
222  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
223  *         <td>Called when this view should assign a size and position to all
224  *         of its children.
225  *         </td>
226  *     </tr>
227  *     <tr>
228  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
229  *         <td>Called when the size of this view has changed.
230  *         </td>
231  *     </tr>
232  *
233  *     <tr>
234  *         <td>Drawing</td>
235  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
236  *         <td>Called when the view should render its content.
237  *         </td>
238  *     </tr>
239  *
240  *     <tr>
241  *         <td rowspan="4">Event processing</td>
242  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
243  *         <td>Called when a new hardware key event occurs.
244  *         </td>
245  *     </tr>
246  *     <tr>
247  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
248  *         <td>Called when a hardware key up event occurs.
249  *         </td>
250  *     </tr>
251  *     <tr>
252  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
253  *         <td>Called when a trackball motion event occurs.
254  *         </td>
255  *     </tr>
256  *     <tr>
257  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
258  *         <td>Called when a touch screen motion event occurs.
259  *         </td>
260  *     </tr>
261  *
262  *     <tr>
263  *         <td rowspan="2">Focus</td>
264  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
265  *         <td>Called when the view gains or loses focus.
266  *         </td>
267  *     </tr>
268  *
269  *     <tr>
270  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
271  *         <td>Called when the window containing the view gains or loses focus.
272  *         </td>
273  *     </tr>
274  *
275  *     <tr>
276  *         <td rowspan="3">Attaching</td>
277  *         <td><code>{@link #onAttachedToWindow()}</code></td>
278  *         <td>Called when the view is attached to a window.
279  *         </td>
280  *     </tr>
281  *
282  *     <tr>
283  *         <td><code>{@link #onDetachedFromWindow}</code></td>
284  *         <td>Called when the view is detached from its window.
285  *         </td>
286  *     </tr>
287  *
288  *     <tr>
289  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
290  *         <td>Called when the visibility of the window containing the view
291  *         has changed.
292  *         </td>
293  *     </tr>
294  *     </tbody>
295  *
296  * </table>
297  * </p>
298  *
299  * <a name="IDs"></a>
300  * <h3>IDs</h3>
301  * Views may have an integer id associated with them. These ids are typically
302  * assigned in the layout XML files, and are used to find specific views within
303  * the view tree. A common pattern is to:
304  * <ul>
305  * <li>Define a Button in the layout file and assign it a unique ID.
306  * <pre>
307  * &lt;Button
308  *     android:id="@+id/my_button"
309  *     android:layout_width="wrap_content"
310  *     android:layout_height="wrap_content"
311  *     android:text="@string/my_button_text"/&gt;
312  * </pre></li>
313  * <li>From the onCreate method of an Activity, find the Button
314  * <pre class="prettyprint">
315  *      Button myButton = (Button) findViewById(R.id.my_button);
316  * </pre></li>
317  * </ul>
318  * <p>
319  * View IDs need not be unique throughout the tree, but it is good practice to
320  * ensure that they are at least unique within the part of the tree you are
321  * searching.
322  * </p>
323  *
324  * <a name="Position"></a>
325  * <h3>Position</h3>
326  * <p>
327  * The geometry of a view is that of a rectangle. A view has a location,
328  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
329  * two dimensions, expressed as a width and a height. The unit for location
330  * and dimensions is the pixel.
331  * </p>
332  *
333  * <p>
334  * It is possible to retrieve the location of a view by invoking the methods
335  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
336  * coordinate of the rectangle representing the view. The latter returns the
337  * top, or Y, coordinate of the rectangle representing the view. These methods
338  * both return the location of the view relative to its parent. For instance,
339  * when getLeft() returns 20, that means the view is located 20 pixels to the
340  * right of the left edge of its direct parent.
341  * </p>
342  *
343  * <p>
344  * In addition, several convenience methods are offered to avoid unnecessary
345  * computations, namely {@link #getRight()} and {@link #getBottom()}.
346  * These methods return the coordinates of the right and bottom edges of the
347  * rectangle representing the view. For instance, calling {@link #getRight()}
348  * is similar to the following computation: <code>getLeft() + getWidth()</code>
349  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
350  * </p>
351  *
352  * <a name="SizePaddingMargins"></a>
353  * <h3>Size, padding and margins</h3>
354  * <p>
355  * The size of a view is expressed with a width and a height. A view actually
356  * possess two pairs of width and height values.
357  * </p>
358  *
359  * <p>
360  * The first pair is known as <em>measured width</em> and
361  * <em>measured height</em>. These dimensions define how big a view wants to be
362  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
363  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
364  * and {@link #getMeasuredHeight()}.
365  * </p>
366  *
367  * <p>
368  * The second pair is simply known as <em>width</em> and <em>height</em>, or
369  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
370  * dimensions define the actual size of the view on screen, at drawing time and
371  * after layout. These values may, but do not have to, be different from the
372  * measured width and height. The width and height can be obtained by calling
373  * {@link #getWidth()} and {@link #getHeight()}.
374  * </p>
375  *
376  * <p>
377  * To measure its dimensions, a view takes into account its padding. The padding
378  * is expressed in pixels for the left, top, right and bottom parts of the view.
379  * Padding can be used to offset the content of the view by a specific amount of
380  * pixels. For instance, a left padding of 2 will push the view's content by
381  * 2 pixels to the right of the left edge. Padding can be set using the
382  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
383  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
384  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
385  * {@link #getPaddingEnd()}.
386  * </p>
387  *
388  * <p>
389  * Even though a view can define a padding, it does not provide any support for
390  * margins. However, view groups provide such a support. Refer to
391  * {@link android.view.ViewGroup} and
392  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
393  * </p>
394  *
395  * <a name="Layout"></a>
396  * <h3>Layout</h3>
397  * <p>
398  * Layout is a two pass process: a measure pass and a layout pass. The measuring
399  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
400  * of the view tree. Each view pushes dimension specifications down the tree
401  * during the recursion. At the end of the measure pass, every view has stored
402  * its measurements. The second pass happens in
403  * {@link #layout(int,int,int,int)} and is also top-down. During
404  * this pass each parent is responsible for positioning all of its children
405  * using the sizes computed in the measure pass.
406  * </p>
407  *
408  * <p>
409  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
410  * {@link #getMeasuredHeight()} values must be set, along with those for all of
411  * that view's descendants. A view's measured width and measured height values
412  * must respect the constraints imposed by the view's parents. This guarantees
413  * that at the end of the measure pass, all parents accept all of their
414  * children's measurements. A parent view may call measure() more than once on
415  * its children. For example, the parent may measure each child once with
416  * unspecified dimensions to find out how big they want to be, then call
417  * measure() on them again with actual numbers if the sum of all the children's
418  * unconstrained sizes is too big or too small.
419  * </p>
420  *
421  * <p>
422  * The measure pass uses two classes to communicate dimensions. The
423  * {@link MeasureSpec} class is used by views to tell their parents how they
424  * want to be measured and positioned. The base LayoutParams class just
425  * describes how big the view wants to be for both width and height. For each
426  * dimension, it can specify one of:
427  * <ul>
428  * <li> an exact number
429  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
430  * (minus padding)
431  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
432  * enclose its content (plus padding).
433  * </ul>
434  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
435  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
436  * an X and Y value.
437  * </p>
438  *
439  * <p>
440  * MeasureSpecs are used to push requirements down the tree from parent to
441  * child. A MeasureSpec can be in one of three modes:
442  * <ul>
443  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
444  * of a child view. For example, a LinearLayout may call measure() on its child
445  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
446  * tall the child view wants to be given a width of 240 pixels.
447  * <li>EXACTLY: This is used by the parent to impose an exact size on the
448  * child. The child must use this size, and guarantee that all of its
449  * descendants will fit within this size.
450  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
451  * child. The child must guarantee that it and all of its descendants will fit
452  * within this size.
453  * </ul>
454  * </p>
455  *
456  * <p>
457  * To initiate a layout, call {@link #requestLayout}. This method is typically
458  * called by a view on itself when it believes that is can no longer fit within
459  * its current bounds.
460  * </p>
461  *
462  * <a name="Drawing"></a>
463  * <h3>Drawing</h3>
464  * <p>
465  * Drawing is handled by walking the tree and recording the drawing commands of
466  * any View that needs to update. After this, the drawing commands of the
467  * entire tree are issued to screen, clipped to the newly damaged area.
468  * </p>
469  *
470  * <p>
471  * The tree is largely recorded and drawn in order, with parents drawn before
472  * (i.e., behind) their children, with siblings drawn in the order they appear
473  * in the tree. If you set a background drawable for a View, then the View will
474  * draw it before calling back to its <code>onDraw()</code> method. The child
475  * drawing order can be overridden with
476  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
477  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
478  * </p>
479  *
480  * <p>
481  * To force a view to draw, call {@link #invalidate()}.
482  * </p>
483  *
484  * <a name="EventHandlingThreading"></a>
485  * <h3>Event Handling and Threading</h3>
486  * <p>
487  * The basic cycle of a view is as follows:
488  * <ol>
489  * <li>An event comes in and is dispatched to the appropriate view. The view
490  * handles the event and notifies any listeners.</li>
491  * <li>If in the course of processing the event, the view's bounds may need
492  * to be changed, the view will call {@link #requestLayout()}.</li>
493  * <li>Similarly, if in the course of processing the event the view's appearance
494  * may need to be changed, the view will call {@link #invalidate()}.</li>
495  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
496  * the framework will take care of measuring, laying out, and drawing the tree
497  * as appropriate.</li>
498  * </ol>
499  * </p>
500  *
501  * <p><em>Note: The entire view tree is single threaded. You must always be on
502  * the UI thread when calling any method on any view.</em>
503  * If you are doing work on other threads and want to update the state of a view
504  * from that thread, you should use a {@link Handler}.
505  * </p>
506  *
507  * <a name="FocusHandling"></a>
508  * <h3>Focus Handling</h3>
509  * <p>
510  * The framework will handle routine focus movement in response to user input.
511  * This includes changing the focus as views are removed or hidden, or as new
512  * views become available. Views indicate their willingness to take focus
513  * through the {@link #isFocusable} method. To change whether a view can take
514  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
515  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
516  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
517  * </p>
518  * <p>
519  * Focus movement is based on an algorithm which finds the nearest neighbor in a
520  * given direction. In rare cases, the default algorithm may not match the
521  * intended behavior of the developer. In these situations, you can provide
522  * explicit overrides by using these XML attributes in the layout file:
523  * <pre>
524  * nextFocusDown
525  * nextFocusLeft
526  * nextFocusRight
527  * nextFocusUp
528  * </pre>
529  * </p>
530  *
531  *
532  * <p>
533  * To get a particular view to take focus, call {@link #requestFocus()}.
534  * </p>
535  *
536  * <a name="TouchMode"></a>
537  * <h3>Touch Mode</h3>
538  * <p>
539  * When a user is navigating a user interface via directional keys such as a D-pad, it is
540  * necessary to give focus to actionable items such as buttons so the user can see
541  * what will take input.  If the device has touch capabilities, however, and the user
542  * begins interacting with the interface by touching it, it is no longer necessary to
543  * always highlight, or give focus to, a particular view.  This motivates a mode
544  * for interaction named 'touch mode'.
545  * </p>
546  * <p>
547  * For a touch capable device, once the user touches the screen, the device
548  * will enter touch mode.  From this point onward, only views for which
549  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
550  * Other views that are touchable, like buttons, will not take focus when touched; they will
551  * only fire the on click listeners.
552  * </p>
553  * <p>
554  * Any time a user hits a directional key, such as a D-pad direction, the view device will
555  * exit touch mode, and find a view to take focus, so that the user may resume interacting
556  * with the user interface without touching the screen again.
557  * </p>
558  * <p>
559  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
560  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
561  * </p>
562  *
563  * <a name="Scrolling"></a>
564  * <h3>Scrolling</h3>
565  * <p>
566  * The framework provides basic support for views that wish to internally
567  * scroll their content. This includes keeping track of the X and Y scroll
568  * offset as well as mechanisms for drawing scrollbars. See
569  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
570  * {@link #awakenScrollBars()} for more details.
571  * </p>
572  *
573  * <a name="Tags"></a>
574  * <h3>Tags</h3>
575  * <p>
576  * Unlike IDs, tags are not used to identify views. Tags are essentially an
577  * extra piece of information that can be associated with a view. They are most
578  * often used as a convenience to store data related to views in the views
579  * themselves rather than by putting them in a separate structure.
580  * </p>
581  * <p>
582  * Tags may be specified with character sequence values in layout XML as either
583  * a single tag using the {@link android.R.styleable#View_tag android:tag}
584  * attribute or multiple tags using the {@code <tag>} child element:
585  * <pre>
586  *     &ltView ...
587  *           android:tag="@string/mytag_value" /&gt;
588  *     &ltView ...&gt;
589  *         &lttag android:id="@+id/mytag"
590  *              android:value="@string/mytag_value" /&gt;
591  *     &lt/View>
592  * </pre>
593  * </p>
594  * <p>
595  * Tags may also be specified with arbitrary objects from code using
596  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
597  * </p>
598  *
599  * <a name="Themes"></a>
600  * <h3>Themes</h3>
601  * <p>
602  * By default, Views are created using the theme of the Context object supplied
603  * to their constructor; however, a different theme may be specified by using
604  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
605  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
606  * code.
607  * </p>
608  * <p>
609  * When the {@link android.R.styleable#View_theme android:theme} attribute is
610  * used in XML, the specified theme is applied on top of the inflation
611  * context's theme (see {@link LayoutInflater}) and used for the view itself as
612  * well as any child elements.
613  * </p>
614  * <p>
615  * In the following example, both views will be created using the Material dark
616  * color scheme; however, because an overlay theme is used which only defines a
617  * subset of attributes, the value of
618  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
619  * the inflation context's theme (e.g. the Activity theme) will be preserved.
620  * <pre>
621  *     &ltLinearLayout
622  *             ...
623  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
624  *         &ltView ...&gt;
625  *     &lt/LinearLayout&gt;
626  * </pre>
627  * </p>
628  *
629  * <a name="Properties"></a>
630  * <h3>Properties</h3>
631  * <p>
632  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
633  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
634  * available both in the {@link Property} form as well as in similarly-named setter/getter
635  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
636  * be used to set persistent state associated with these rendering-related properties on the view.
637  * The properties and methods can also be used in conjunction with
638  * {@link android.animation.Animator Animator}-based animations, described more in the
639  * <a href="#Animation">Animation</a> section.
640  * </p>
641  *
642  * <a name="Animation"></a>
643  * <h3>Animation</h3>
644  * <p>
645  * Starting with Android 3.0, the preferred way of animating views is to use the
646  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
647  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
648  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
649  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
650  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
651  * makes animating these View properties particularly easy and efficient.
652  * </p>
653  * <p>
654  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
655  * You can attach an {@link Animation} object to a view using
656  * {@link #setAnimation(Animation)} or
657  * {@link #startAnimation(Animation)}. The animation can alter the scale,
658  * rotation, translation and alpha of a view over time. If the animation is
659  * attached to a view that has children, the animation will affect the entire
660  * subtree rooted by that node. When an animation is started, the framework will
661  * take care of redrawing the appropriate views until the animation completes.
662  * </p>
663  *
664  * <a name="Security"></a>
665  * <h3>Security</h3>
666  * <p>
667  * Sometimes it is essential that an application be able to verify that an action
668  * is being performed with the full knowledge and consent of the user, such as
669  * granting a permission request, making a purchase or clicking on an advertisement.
670  * Unfortunately, a malicious application could try to spoof the user into
671  * performing these actions, unaware, by concealing the intended purpose of the view.
672  * As a remedy, the framework offers a touch filtering mechanism that can be used to
673  * improve the security of views that provide access to sensitive functionality.
674  * </p><p>
675  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
676  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
677  * will discard touches that are received whenever the view's window is obscured by
678  * another visible window.  As a result, the view will not receive touches whenever a
679  * toast, dialog or other window appears above the view's window.
680  * </p><p>
681  * For more fine-grained control over security, consider overriding the
682  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
683  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
684  * </p>
685  *
686  * @attr ref android.R.styleable#View_alpha
687  * @attr ref android.R.styleable#View_background
688  * @attr ref android.R.styleable#View_clickable
689  * @attr ref android.R.styleable#View_contentDescription
690  * @attr ref android.R.styleable#View_drawingCacheQuality
691  * @attr ref android.R.styleable#View_duplicateParentState
692  * @attr ref android.R.styleable#View_id
693  * @attr ref android.R.styleable#View_requiresFadingEdge
694  * @attr ref android.R.styleable#View_fadeScrollbars
695  * @attr ref android.R.styleable#View_fadingEdgeLength
696  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
697  * @attr ref android.R.styleable#View_fitsSystemWindows
698  * @attr ref android.R.styleable#View_isScrollContainer
699  * @attr ref android.R.styleable#View_focusable
700  * @attr ref android.R.styleable#View_focusableInTouchMode
701  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
702  * @attr ref android.R.styleable#View_keepScreenOn
703  * @attr ref android.R.styleable#View_layerType
704  * @attr ref android.R.styleable#View_layoutDirection
705  * @attr ref android.R.styleable#View_longClickable
706  * @attr ref android.R.styleable#View_minHeight
707  * @attr ref android.R.styleable#View_minWidth
708  * @attr ref android.R.styleable#View_nextFocusDown
709  * @attr ref android.R.styleable#View_nextFocusLeft
710  * @attr ref android.R.styleable#View_nextFocusRight
711  * @attr ref android.R.styleable#View_nextFocusUp
712  * @attr ref android.R.styleable#View_onClick
713  * @attr ref android.R.styleable#View_padding
714  * @attr ref android.R.styleable#View_paddingBottom
715  * @attr ref android.R.styleable#View_paddingLeft
716  * @attr ref android.R.styleable#View_paddingRight
717  * @attr ref android.R.styleable#View_paddingTop
718  * @attr ref android.R.styleable#View_paddingStart
719  * @attr ref android.R.styleable#View_paddingEnd
720  * @attr ref android.R.styleable#View_saveEnabled
721  * @attr ref android.R.styleable#View_rotation
722  * @attr ref android.R.styleable#View_rotationX
723  * @attr ref android.R.styleable#View_rotationY
724  * @attr ref android.R.styleable#View_scaleX
725  * @attr ref android.R.styleable#View_scaleY
726  * @attr ref android.R.styleable#View_scrollX
727  * @attr ref android.R.styleable#View_scrollY
728  * @attr ref android.R.styleable#View_scrollbarSize
729  * @attr ref android.R.styleable#View_scrollbarStyle
730  * @attr ref android.R.styleable#View_scrollbars
731  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
732  * @attr ref android.R.styleable#View_scrollbarFadeDuration
733  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
734  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
735  * @attr ref android.R.styleable#View_scrollbarThumbVertical
736  * @attr ref android.R.styleable#View_scrollbarTrackVertical
737  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
738  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
739  * @attr ref android.R.styleable#View_stateListAnimator
740  * @attr ref android.R.styleable#View_transitionName
741  * @attr ref android.R.styleable#View_soundEffectsEnabled
742  * @attr ref android.R.styleable#View_tag
743  * @attr ref android.R.styleable#View_textAlignment
744  * @attr ref android.R.styleable#View_textDirection
745  * @attr ref android.R.styleable#View_transformPivotX
746  * @attr ref android.R.styleable#View_transformPivotY
747  * @attr ref android.R.styleable#View_translationX
748  * @attr ref android.R.styleable#View_translationY
749  * @attr ref android.R.styleable#View_translationZ
750  * @attr ref android.R.styleable#View_visibility
751  * @attr ref android.R.styleable#View_theme
752  *
753  * @see android.view.ViewGroup
754  */
755 @UiThread
756 public class View implements Drawable.Callback, KeyEvent.Callback,
757         AccessibilityEventSource {
758     private static final boolean DBG = false;
759 
760     /**
761      * The logging tag used by this class with android.util.Log.
762      */
763     protected static final String VIEW_LOG_TAG = "View";
764 
765     /**
766      * When set to true, apps will draw debugging information about their layouts.
767      *
768      * @hide
769      */
770     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
771 
772     /**
773      * When set to true, this view will save its attribute data.
774      *
775      * @hide
776      */
777     public static boolean mDebugViewAttributes = false;
778 
779     /**
780      * Used to mark a View that has no ID.
781      */
782     public static final int NO_ID = -1;
783 
784     /**
785      * Signals that compatibility booleans have been initialized according to
786      * target SDK versions.
787      */
788     private static boolean sCompatibilityDone = false;
789 
790     /**
791      * Use the old (broken) way of building MeasureSpecs.
792      */
793     private static boolean sUseBrokenMakeMeasureSpec = false;
794 
795     /**
796      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
797      */
798     static boolean sUseZeroUnspecifiedMeasureSpec = false;
799 
800     /**
801      * Ignore any optimizations using the measure cache.
802      */
803     private static boolean sIgnoreMeasureCache = false;
804 
805     /**
806      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
807      */
808     private static boolean sAlwaysRemeasureExactly = false;
809 
810     /**
811      * Relax constraints around whether setLayoutParams() must be called after
812      * modifying the layout params.
813      */
814     private static boolean sLayoutParamsAlwaysChanged = false;
815 
816     /**
817      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
818      * without throwing
819      */
820     static boolean sTextureViewIgnoresDrawableSetters = false;
821 
822     /**
823      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
824      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
825      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
826      * check is implemented for backwards compatibility.
827      *
828      * {@hide}
829      */
830     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
831 
832     /**
833      * Prior to N, when drag enters into child of a view that has already received an
834      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
835      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
836      * false from its event handler for these events.
837      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
838      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
839      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
840      */
841     static boolean sCascadedDragDrop;
842 
843     /**
844      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
845      * calling setFlags.
846      */
847     private static final int NOT_FOCUSABLE = 0x00000000;
848 
849     /**
850      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
851      * setFlags.
852      */
853     private static final int FOCUSABLE = 0x00000001;
854 
855     /**
856      * Mask for use with setFlags indicating bits used for focus.
857      */
858     private static final int FOCUSABLE_MASK = 0x00000001;
859 
860     /**
861      * This view will adjust its padding to fit sytem windows (e.g. status bar)
862      */
863     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
864 
865     /** @hide */
866     @IntDef({VISIBLE, INVISIBLE, GONE})
867     @Retention(RetentionPolicy.SOURCE)
868     public @interface Visibility {}
869 
870     /**
871      * This view is visible.
872      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
873      * android:visibility}.
874      */
875     public static final int VISIBLE = 0x00000000;
876 
877     /**
878      * This view is invisible, but it still takes up space for layout purposes.
879      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
880      * android:visibility}.
881      */
882     public static final int INVISIBLE = 0x00000004;
883 
884     /**
885      * This view is invisible, and it doesn't take any space for layout
886      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
887      * android:visibility}.
888      */
889     public static final int GONE = 0x00000008;
890 
891     /**
892      * Mask for use with setFlags indicating bits used for visibility.
893      * {@hide}
894      */
895     static final int VISIBILITY_MASK = 0x0000000C;
896 
897     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
898 
899     /**
900      * This view is enabled. Interpretation varies by subclass.
901      * Use with ENABLED_MASK when calling setFlags.
902      * {@hide}
903      */
904     static final int ENABLED = 0x00000000;
905 
906     /**
907      * This view is disabled. Interpretation varies by subclass.
908      * Use with ENABLED_MASK when calling setFlags.
909      * {@hide}
910      */
911     static final int DISABLED = 0x00000020;
912 
913    /**
914     * Mask for use with setFlags indicating bits used for indicating whether
915     * this view is enabled
916     * {@hide}
917     */
918     static final int ENABLED_MASK = 0x00000020;
919 
920     /**
921      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
922      * called and further optimizations will be performed. It is okay to have
923      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
924      * {@hide}
925      */
926     static final int WILL_NOT_DRAW = 0x00000080;
927 
928     /**
929      * Mask for use with setFlags indicating bits used for indicating whether
930      * this view is will draw
931      * {@hide}
932      */
933     static final int DRAW_MASK = 0x00000080;
934 
935     /**
936      * <p>This view doesn't show scrollbars.</p>
937      * {@hide}
938      */
939     static final int SCROLLBARS_NONE = 0x00000000;
940 
941     /**
942      * <p>This view shows horizontal scrollbars.</p>
943      * {@hide}
944      */
945     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
946 
947     /**
948      * <p>This view shows vertical scrollbars.</p>
949      * {@hide}
950      */
951     static final int SCROLLBARS_VERTICAL = 0x00000200;
952 
953     /**
954      * <p>Mask for use with setFlags indicating bits used for indicating which
955      * scrollbars are enabled.</p>
956      * {@hide}
957      */
958     static final int SCROLLBARS_MASK = 0x00000300;
959 
960     /**
961      * Indicates that the view should filter touches when its window is obscured.
962      * Refer to the class comments for more information about this security feature.
963      * {@hide}
964      */
965     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
966 
967     /**
968      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
969      * that they are optional and should be skipped if the window has
970      * requested system UI flags that ignore those insets for layout.
971      */
972     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
973 
974     /**
975      * <p>This view doesn't show fading edges.</p>
976      * {@hide}
977      */
978     static final int FADING_EDGE_NONE = 0x00000000;
979 
980     /**
981      * <p>This view shows horizontal fading edges.</p>
982      * {@hide}
983      */
984     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
985 
986     /**
987      * <p>This view shows vertical fading edges.</p>
988      * {@hide}
989      */
990     static final int FADING_EDGE_VERTICAL = 0x00002000;
991 
992     /**
993      * <p>Mask for use with setFlags indicating bits used for indicating which
994      * fading edges are enabled.</p>
995      * {@hide}
996      */
997     static final int FADING_EDGE_MASK = 0x00003000;
998 
999     /**
1000      * <p>Indicates this view can be clicked. When clickable, a View reacts
1001      * to clicks by notifying the OnClickListener.<p>
1002      * {@hide}
1003      */
1004     static final int CLICKABLE = 0x00004000;
1005 
1006     /**
1007      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1008      * {@hide}
1009      */
1010     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1011 
1012     /**
1013      * <p>Indicates that no icicle should be saved for this view.<p>
1014      * {@hide}
1015      */
1016     static final int SAVE_DISABLED = 0x000010000;
1017 
1018     /**
1019      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1020      * property.</p>
1021      * {@hide}
1022      */
1023     static final int SAVE_DISABLED_MASK = 0x000010000;
1024 
1025     /**
1026      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1027      * {@hide}
1028      */
1029     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1030 
1031     /**
1032      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1033      * {@hide}
1034      */
1035     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1036 
1037     /** @hide */
1038     @Retention(RetentionPolicy.SOURCE)
1039     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1040     public @interface DrawingCacheQuality {}
1041 
1042     /**
1043      * <p>Enables low quality mode for the drawing cache.</p>
1044      */
1045     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1046 
1047     /**
1048      * <p>Enables high quality mode for the drawing cache.</p>
1049      */
1050     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1051 
1052     /**
1053      * <p>Enables automatic quality mode for the drawing cache.</p>
1054      */
1055     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1056 
1057     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1058             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1059     };
1060 
1061     /**
1062      * <p>Mask for use with setFlags indicating bits used for the cache
1063      * quality property.</p>
1064      * {@hide}
1065      */
1066     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1067 
1068     /**
1069      * <p>
1070      * Indicates this view can be long clicked. When long clickable, a View
1071      * reacts to long clicks by notifying the OnLongClickListener or showing a
1072      * context menu.
1073      * </p>
1074      * {@hide}
1075      */
1076     static final int LONG_CLICKABLE = 0x00200000;
1077 
1078     /**
1079      * <p>Indicates that this view gets its drawable states from its direct parent
1080      * and ignores its original internal states.</p>
1081      *
1082      * @hide
1083      */
1084     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1085 
1086     /**
1087      * <p>
1088      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1089      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1090      * OnContextClickListener.
1091      * </p>
1092      * {@hide}
1093      */
1094     static final int CONTEXT_CLICKABLE = 0x00800000;
1095 
1096 
1097     /** @hide */
1098     @IntDef({
1099         SCROLLBARS_INSIDE_OVERLAY,
1100         SCROLLBARS_INSIDE_INSET,
1101         SCROLLBARS_OUTSIDE_OVERLAY,
1102         SCROLLBARS_OUTSIDE_INSET
1103     })
1104     @Retention(RetentionPolicy.SOURCE)
1105     public @interface ScrollBarStyle {}
1106 
1107     /**
1108      * The scrollbar style to display the scrollbars inside the content area,
1109      * without increasing the padding. The scrollbars will be overlaid with
1110      * translucency on the view's content.
1111      */
1112     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1113 
1114     /**
1115      * The scrollbar style to display the scrollbars inside the padded area,
1116      * increasing the padding of the view. The scrollbars will not overlap the
1117      * content area of the view.
1118      */
1119     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1120 
1121     /**
1122      * The scrollbar style to display the scrollbars at the edge of the view,
1123      * without increasing the padding. The scrollbars will be overlaid with
1124      * translucency.
1125      */
1126     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1127 
1128     /**
1129      * The scrollbar style to display the scrollbars at the edge of the view,
1130      * increasing the padding of the view. The scrollbars will only overlap the
1131      * background, if any.
1132      */
1133     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1134 
1135     /**
1136      * Mask to check if the scrollbar style is overlay or inset.
1137      * {@hide}
1138      */
1139     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1140 
1141     /**
1142      * Mask to check if the scrollbar style is inside or outside.
1143      * {@hide}
1144      */
1145     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1146 
1147     /**
1148      * Mask for scrollbar style.
1149      * {@hide}
1150      */
1151     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1152 
1153     /**
1154      * View flag indicating that the screen should remain on while the
1155      * window containing this view is visible to the user.  This effectively
1156      * takes care of automatically setting the WindowManager's
1157      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1158      */
1159     public static final int KEEP_SCREEN_ON = 0x04000000;
1160 
1161     /**
1162      * View flag indicating whether this view should have sound effects enabled
1163      * for events such as clicking and touching.
1164      */
1165     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1166 
1167     /**
1168      * View flag indicating whether this view should have haptic feedback
1169      * enabled for events such as long presses.
1170      */
1171     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1172 
1173     /**
1174      * <p>Indicates that the view hierarchy should stop saving state when
1175      * it reaches this view.  If state saving is initiated immediately at
1176      * the view, it will be allowed.
1177      * {@hide}
1178      */
1179     static final int PARENT_SAVE_DISABLED = 0x20000000;
1180 
1181     /**
1182      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1183      * {@hide}
1184      */
1185     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1186 
1187     /** @hide */
1188     @IntDef(flag = true,
1189             value = {
1190                 FOCUSABLES_ALL,
1191                 FOCUSABLES_TOUCH_MODE
1192             })
1193     @Retention(RetentionPolicy.SOURCE)
1194     public @interface FocusableMode {}
1195 
1196     /**
1197      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1198      * should add all focusable Views regardless if they are focusable in touch mode.
1199      */
1200     public static final int FOCUSABLES_ALL = 0x00000000;
1201 
1202     /**
1203      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1204      * should add only Views focusable in touch mode.
1205      */
1206     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1207 
1208     /** @hide */
1209     @IntDef({
1210             FOCUS_BACKWARD,
1211             FOCUS_FORWARD,
1212             FOCUS_LEFT,
1213             FOCUS_UP,
1214             FOCUS_RIGHT,
1215             FOCUS_DOWN
1216     })
1217     @Retention(RetentionPolicy.SOURCE)
1218     public @interface FocusDirection {}
1219 
1220     /** @hide */
1221     @IntDef({
1222             FOCUS_LEFT,
1223             FOCUS_UP,
1224             FOCUS_RIGHT,
1225             FOCUS_DOWN
1226     })
1227     @Retention(RetentionPolicy.SOURCE)
1228     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1229 
1230     /**
1231      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1232      * item.
1233      */
1234     public static final int FOCUS_BACKWARD = 0x00000001;
1235 
1236     /**
1237      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1238      * item.
1239      */
1240     public static final int FOCUS_FORWARD = 0x00000002;
1241 
1242     /**
1243      * Use with {@link #focusSearch(int)}. Move focus to the left.
1244      */
1245     public static final int FOCUS_LEFT = 0x00000011;
1246 
1247     /**
1248      * Use with {@link #focusSearch(int)}. Move focus up.
1249      */
1250     public static final int FOCUS_UP = 0x00000021;
1251 
1252     /**
1253      * Use with {@link #focusSearch(int)}. Move focus to the right.
1254      */
1255     public static final int FOCUS_RIGHT = 0x00000042;
1256 
1257     /**
1258      * Use with {@link #focusSearch(int)}. Move focus down.
1259      */
1260     public static final int FOCUS_DOWN = 0x00000082;
1261 
1262     /**
1263      * Bits of {@link #getMeasuredWidthAndState()} and
1264      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1265      */
1266     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1267 
1268     /**
1269      * Bits of {@link #getMeasuredWidthAndState()} and
1270      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1271      */
1272     public static final int MEASURED_STATE_MASK = 0xff000000;
1273 
1274     /**
1275      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1276      * for functions that combine both width and height into a single int,
1277      * such as {@link #getMeasuredState()} and the childState argument of
1278      * {@link #resolveSizeAndState(int, int, int)}.
1279      */
1280     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1281 
1282     /**
1283      * Bit of {@link #getMeasuredWidthAndState()} and
1284      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1285      * is smaller that the space the view would like to have.
1286      */
1287     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1288 
1289     /**
1290      * Base View state sets
1291      */
1292     // Singles
1293     /**
1294      * Indicates the view has no states set. States are used with
1295      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1296      * view depending on its state.
1297      *
1298      * @see android.graphics.drawable.Drawable
1299      * @see #getDrawableState()
1300      */
1301     protected static final int[] EMPTY_STATE_SET;
1302     /**
1303      * Indicates the view is enabled. States are used with
1304      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1305      * view depending on its state.
1306      *
1307      * @see android.graphics.drawable.Drawable
1308      * @see #getDrawableState()
1309      */
1310     protected static final int[] ENABLED_STATE_SET;
1311     /**
1312      * Indicates the view is focused. States are used with
1313      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1314      * view depending on its state.
1315      *
1316      * @see android.graphics.drawable.Drawable
1317      * @see #getDrawableState()
1318      */
1319     protected static final int[] FOCUSED_STATE_SET;
1320     /**
1321      * Indicates the view is selected. States are used with
1322      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1323      * view depending on its state.
1324      *
1325      * @see android.graphics.drawable.Drawable
1326      * @see #getDrawableState()
1327      */
1328     protected static final int[] SELECTED_STATE_SET;
1329     /**
1330      * Indicates the view is pressed. States are used with
1331      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1332      * view depending on its state.
1333      *
1334      * @see android.graphics.drawable.Drawable
1335      * @see #getDrawableState()
1336      */
1337     protected static final int[] PRESSED_STATE_SET;
1338     /**
1339      * Indicates the view's window has focus. States are used with
1340      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1341      * view depending on its state.
1342      *
1343      * @see android.graphics.drawable.Drawable
1344      * @see #getDrawableState()
1345      */
1346     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1347     // Doubles
1348     /**
1349      * Indicates the view is enabled and has the focus.
1350      *
1351      * @see #ENABLED_STATE_SET
1352      * @see #FOCUSED_STATE_SET
1353      */
1354     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1355     /**
1356      * Indicates the view is enabled and selected.
1357      *
1358      * @see #ENABLED_STATE_SET
1359      * @see #SELECTED_STATE_SET
1360      */
1361     protected static final int[] ENABLED_SELECTED_STATE_SET;
1362     /**
1363      * Indicates the view is enabled and that its window has focus.
1364      *
1365      * @see #ENABLED_STATE_SET
1366      * @see #WINDOW_FOCUSED_STATE_SET
1367      */
1368     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1369     /**
1370      * Indicates the view is focused and selected.
1371      *
1372      * @see #FOCUSED_STATE_SET
1373      * @see #SELECTED_STATE_SET
1374      */
1375     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1376     /**
1377      * Indicates the view has the focus and that its window has the focus.
1378      *
1379      * @see #FOCUSED_STATE_SET
1380      * @see #WINDOW_FOCUSED_STATE_SET
1381      */
1382     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1383     /**
1384      * Indicates the view is selected and that its window has the focus.
1385      *
1386      * @see #SELECTED_STATE_SET
1387      * @see #WINDOW_FOCUSED_STATE_SET
1388      */
1389     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1390     // Triples
1391     /**
1392      * Indicates the view is enabled, focused and selected.
1393      *
1394      * @see #ENABLED_STATE_SET
1395      * @see #FOCUSED_STATE_SET
1396      * @see #SELECTED_STATE_SET
1397      */
1398     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1399     /**
1400      * Indicates the view is enabled, focused and its window has the focus.
1401      *
1402      * @see #ENABLED_STATE_SET
1403      * @see #FOCUSED_STATE_SET
1404      * @see #WINDOW_FOCUSED_STATE_SET
1405      */
1406     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1407     /**
1408      * Indicates the view is enabled, selected and its window has the focus.
1409      *
1410      * @see #ENABLED_STATE_SET
1411      * @see #SELECTED_STATE_SET
1412      * @see #WINDOW_FOCUSED_STATE_SET
1413      */
1414     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1415     /**
1416      * Indicates the view is focused, selected and its window has the focus.
1417      *
1418      * @see #FOCUSED_STATE_SET
1419      * @see #SELECTED_STATE_SET
1420      * @see #WINDOW_FOCUSED_STATE_SET
1421      */
1422     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1423     /**
1424      * Indicates the view is enabled, focused, selected and its window
1425      * has the focus.
1426      *
1427      * @see #ENABLED_STATE_SET
1428      * @see #FOCUSED_STATE_SET
1429      * @see #SELECTED_STATE_SET
1430      * @see #WINDOW_FOCUSED_STATE_SET
1431      */
1432     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1433     /**
1434      * Indicates the view is pressed and its window has the focus.
1435      *
1436      * @see #PRESSED_STATE_SET
1437      * @see #WINDOW_FOCUSED_STATE_SET
1438      */
1439     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1440     /**
1441      * Indicates the view is pressed and selected.
1442      *
1443      * @see #PRESSED_STATE_SET
1444      * @see #SELECTED_STATE_SET
1445      */
1446     protected static final int[] PRESSED_SELECTED_STATE_SET;
1447     /**
1448      * Indicates the view is pressed, selected and its window has the focus.
1449      *
1450      * @see #PRESSED_STATE_SET
1451      * @see #SELECTED_STATE_SET
1452      * @see #WINDOW_FOCUSED_STATE_SET
1453      */
1454     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1455     /**
1456      * Indicates the view is pressed and focused.
1457      *
1458      * @see #PRESSED_STATE_SET
1459      * @see #FOCUSED_STATE_SET
1460      */
1461     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1462     /**
1463      * Indicates the view is pressed, focused and its window has the focus.
1464      *
1465      * @see #PRESSED_STATE_SET
1466      * @see #FOCUSED_STATE_SET
1467      * @see #WINDOW_FOCUSED_STATE_SET
1468      */
1469     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1470     /**
1471      * Indicates the view is pressed, focused and selected.
1472      *
1473      * @see #PRESSED_STATE_SET
1474      * @see #SELECTED_STATE_SET
1475      * @see #FOCUSED_STATE_SET
1476      */
1477     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1478     /**
1479      * Indicates the view is pressed, focused, selected and its window has the focus.
1480      *
1481      * @see #PRESSED_STATE_SET
1482      * @see #FOCUSED_STATE_SET
1483      * @see #SELECTED_STATE_SET
1484      * @see #WINDOW_FOCUSED_STATE_SET
1485      */
1486     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1487     /**
1488      * Indicates the view is pressed and enabled.
1489      *
1490      * @see #PRESSED_STATE_SET
1491      * @see #ENABLED_STATE_SET
1492      */
1493     protected static final int[] PRESSED_ENABLED_STATE_SET;
1494     /**
1495      * Indicates the view is pressed, enabled and its window has the focus.
1496      *
1497      * @see #PRESSED_STATE_SET
1498      * @see #ENABLED_STATE_SET
1499      * @see #WINDOW_FOCUSED_STATE_SET
1500      */
1501     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1502     /**
1503      * Indicates the view is pressed, enabled and selected.
1504      *
1505      * @see #PRESSED_STATE_SET
1506      * @see #ENABLED_STATE_SET
1507      * @see #SELECTED_STATE_SET
1508      */
1509     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1510     /**
1511      * Indicates the view is pressed, enabled, selected and its window has the
1512      * focus.
1513      *
1514      * @see #PRESSED_STATE_SET
1515      * @see #ENABLED_STATE_SET
1516      * @see #SELECTED_STATE_SET
1517      * @see #WINDOW_FOCUSED_STATE_SET
1518      */
1519     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1520     /**
1521      * Indicates the view is pressed, enabled and focused.
1522      *
1523      * @see #PRESSED_STATE_SET
1524      * @see #ENABLED_STATE_SET
1525      * @see #FOCUSED_STATE_SET
1526      */
1527     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1528     /**
1529      * Indicates the view is pressed, enabled, focused and its window has the
1530      * focus.
1531      *
1532      * @see #PRESSED_STATE_SET
1533      * @see #ENABLED_STATE_SET
1534      * @see #FOCUSED_STATE_SET
1535      * @see #WINDOW_FOCUSED_STATE_SET
1536      */
1537     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1538     /**
1539      * Indicates the view is pressed, enabled, focused and selected.
1540      *
1541      * @see #PRESSED_STATE_SET
1542      * @see #ENABLED_STATE_SET
1543      * @see #SELECTED_STATE_SET
1544      * @see #FOCUSED_STATE_SET
1545      */
1546     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1547     /**
1548      * Indicates the view is pressed, enabled, focused, selected and its window
1549      * has the focus.
1550      *
1551      * @see #PRESSED_STATE_SET
1552      * @see #ENABLED_STATE_SET
1553      * @see #SELECTED_STATE_SET
1554      * @see #FOCUSED_STATE_SET
1555      * @see #WINDOW_FOCUSED_STATE_SET
1556      */
1557     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1558 
1559     static {
1560         EMPTY_STATE_SET = StateSet.get(0);
1561 
1562         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1563 
1564         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1565         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1566                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1567 
1568         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1569         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1570                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1571         FOCUSED_SELECTED_STATE_SET = StateSet.get(
1572                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1573         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1574                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1575                         | StateSet.VIEW_STATE_FOCUSED);
1576 
1577         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1578         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1580         ENABLED_SELECTED_STATE_SET = StateSet.get(
1581                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1582         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1583                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1584                         | StateSet.VIEW_STATE_ENABLED);
1585         ENABLED_FOCUSED_STATE_SET = StateSet.get(
1586                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1587         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1588                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1589                         | StateSet.VIEW_STATE_ENABLED);
1590         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1591                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1592                         | StateSet.VIEW_STATE_ENABLED);
1593         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1594                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1595                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1596 
1597         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1598         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1599                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1600         PRESSED_SELECTED_STATE_SET = StateSet.get(
1601                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1602         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1603                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1604                         | StateSet.VIEW_STATE_PRESSED);
1605         PRESSED_FOCUSED_STATE_SET = StateSet.get(
1606                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1607         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1608                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1609                         | StateSet.VIEW_STATE_PRESSED);
1610         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1611                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1612                         | StateSet.VIEW_STATE_PRESSED);
1613         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1614                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1615                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1616         PRESSED_ENABLED_STATE_SET = StateSet.get(
1617                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1618         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1619                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1620                         | StateSet.VIEW_STATE_PRESSED);
1621         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1622                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1623                         | StateSet.VIEW_STATE_PRESSED);
1624         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1625                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1626                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1627         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1628                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1629                         | StateSet.VIEW_STATE_PRESSED);
1630         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1631                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1632                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1633         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1634                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1635                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1636         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1637                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1638                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1639                         | StateSet.VIEW_STATE_PRESSED);
1640     }
1641 
1642     /**
1643      * Accessibility event types that are dispatched for text population.
1644      */
1645     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1646             AccessibilityEvent.TYPE_VIEW_CLICKED
1647             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1648             | AccessibilityEvent.TYPE_VIEW_SELECTED
1649             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1650             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1651             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1652             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1653             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1654             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1655             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1656             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1657 
1658     /**
1659      * Temporary Rect currently for use in setBackground().  This will probably
1660      * be extended in the future to hold our own class with more than just
1661      * a Rect. :)
1662      */
1663     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1664 
1665     /**
1666      * Map used to store views' tags.
1667      */
1668     private SparseArray<Object> mKeyedTags;
1669 
1670     /**
1671      * The next available accessibility id.
1672      */
1673     private static int sNextAccessibilityViewId;
1674 
1675     /**
1676      * The animation currently associated with this view.
1677      * @hide
1678      */
1679     protected Animation mCurrentAnimation = null;
1680 
1681     /**
1682      * Width as measured during measure pass.
1683      * {@hide}
1684      */
1685     @ViewDebug.ExportedProperty(category = "measurement")
1686     int mMeasuredWidth;
1687 
1688     /**
1689      * Height as measured during measure pass.
1690      * {@hide}
1691      */
1692     @ViewDebug.ExportedProperty(category = "measurement")
1693     int mMeasuredHeight;
1694 
1695     /**
1696      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1697      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1698      * its display list. This flag, used only when hw accelerated, allows us to clear the
1699      * flag while retaining this information until it's needed (at getDisplayList() time and
1700      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1701      *
1702      * {@hide}
1703      */
1704     boolean mRecreateDisplayList = false;
1705 
1706     /**
1707      * The view's identifier.
1708      * {@hide}
1709      *
1710      * @see #setId(int)
1711      * @see #getId()
1712      */
1713     @IdRes
1714     @ViewDebug.ExportedProperty(resolveId = true)
1715     int mID = NO_ID;
1716 
1717     /**
1718      * The stable ID of this view for accessibility purposes.
1719      */
1720     int mAccessibilityViewId = NO_ID;
1721 
1722     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1723 
1724     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1725 
1726     /**
1727      * The view's tag.
1728      * {@hide}
1729      *
1730      * @see #setTag(Object)
1731      * @see #getTag()
1732      */
1733     protected Object mTag = null;
1734 
1735     // for mPrivateFlags:
1736     /** {@hide} */
1737     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1738     /** {@hide} */
1739     static final int PFLAG_FOCUSED                     = 0x00000002;
1740     /** {@hide} */
1741     static final int PFLAG_SELECTED                    = 0x00000004;
1742     /** {@hide} */
1743     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1744     /** {@hide} */
1745     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1746     /** {@hide} */
1747     static final int PFLAG_DRAWN                       = 0x00000020;
1748     /**
1749      * When this flag is set, this view is running an animation on behalf of its
1750      * children and should therefore not cancel invalidate requests, even if they
1751      * lie outside of this view's bounds.
1752      *
1753      * {@hide}
1754      */
1755     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1756     /** {@hide} */
1757     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1758     /** {@hide} */
1759     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1760     /** {@hide} */
1761     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1762     /** {@hide} */
1763     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1764     /** {@hide} */
1765     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1766     /** {@hide} */
1767     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1768 
1769     private static final int PFLAG_PRESSED             = 0x00004000;
1770 
1771     /** {@hide} */
1772     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1773     /**
1774      * Flag used to indicate that this view should be drawn once more (and only once
1775      * more) after its animation has completed.
1776      * {@hide}
1777      */
1778     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1779 
1780     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1781 
1782     /**
1783      * Indicates that the View returned true when onSetAlpha() was called and that
1784      * the alpha must be restored.
1785      * {@hide}
1786      */
1787     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1788 
1789     /**
1790      * Set by {@link #setScrollContainer(boolean)}.
1791      */
1792     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1793 
1794     /**
1795      * Set by {@link #setScrollContainer(boolean)}.
1796      */
1797     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1798 
1799     /**
1800      * View flag indicating whether this view was invalidated (fully or partially.)
1801      *
1802      * @hide
1803      */
1804     static final int PFLAG_DIRTY                       = 0x00200000;
1805 
1806     /**
1807      * View flag indicating whether this view was invalidated by an opaque
1808      * invalidate request.
1809      *
1810      * @hide
1811      */
1812     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1813 
1814     /**
1815      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1816      *
1817      * @hide
1818      */
1819     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1820 
1821     /**
1822      * Indicates whether the background is opaque.
1823      *
1824      * @hide
1825      */
1826     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1827 
1828     /**
1829      * Indicates whether the scrollbars are opaque.
1830      *
1831      * @hide
1832      */
1833     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1834 
1835     /**
1836      * Indicates whether the view is opaque.
1837      *
1838      * @hide
1839      */
1840     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1841 
1842     /**
1843      * Indicates a prepressed state;
1844      * the short time between ACTION_DOWN and recognizing
1845      * a 'real' press. Prepressed is used to recognize quick taps
1846      * even when they are shorter than ViewConfiguration.getTapTimeout().
1847      *
1848      * @hide
1849      */
1850     private static final int PFLAG_PREPRESSED          = 0x02000000;
1851 
1852     /**
1853      * Indicates whether the view is temporarily detached.
1854      *
1855      * @hide
1856      */
1857     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1858 
1859     /**
1860      * Indicates that we should awaken scroll bars once attached
1861      *
1862      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1863      * during window attachment and it is no longer needed. Feel free to repurpose it.
1864      *
1865      * @hide
1866      */
1867     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1868 
1869     /**
1870      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1871      * @hide
1872      */
1873     private static final int PFLAG_HOVERED             = 0x10000000;
1874 
1875     /**
1876      * no longer needed, should be reused
1877      */
1878     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1879 
1880     /** {@hide} */
1881     static final int PFLAG_ACTIVATED                   = 0x40000000;
1882 
1883     /**
1884      * Indicates that this view was specifically invalidated, not just dirtied because some
1885      * child view was invalidated. The flag is used to determine when we need to recreate
1886      * a view's display list (as opposed to just returning a reference to its existing
1887      * display list).
1888      *
1889      * @hide
1890      */
1891     static final int PFLAG_INVALIDATED                 = 0x80000000;
1892 
1893     /**
1894      * Masks for mPrivateFlags2, as generated by dumpFlags():
1895      *
1896      * |-------|-------|-------|-------|
1897      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1898      *                                1  PFLAG2_DRAG_HOVERED
1899      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1900      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1901      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1902      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1903      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1904      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1905      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1906      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1907      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1908      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1909      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1910      *                         111       PFLAG2_TEXT_DIRECTION_MASK
1911      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1912      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1913      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1914      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1915      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1916      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1917      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1918      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1919      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1920      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1921      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1922      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1923      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1924      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1925      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1926      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1927      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1928      *     1                             PFLAG2_VIEW_QUICK_REJECTED
1929      *    1                              PFLAG2_PADDING_RESOLVED
1930      *   1                               PFLAG2_DRAWABLE_RESOLVED
1931      *  1                                PFLAG2_HAS_TRANSIENT_STATE
1932      * |-------|-------|-------|-------|
1933      */
1934 
1935     /**
1936      * Indicates that this view has reported that it can accept the current drag's content.
1937      * Cleared when the drag operation concludes.
1938      * @hide
1939      */
1940     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1941 
1942     /**
1943      * Indicates that this view is currently directly under the drag location in a
1944      * drag-and-drop operation involving content that it can accept.  Cleared when
1945      * the drag exits the view, or when the drag operation concludes.
1946      * @hide
1947      */
1948     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1949 
1950     /** @hide */
1951     @IntDef({
1952         LAYOUT_DIRECTION_LTR,
1953         LAYOUT_DIRECTION_RTL,
1954         LAYOUT_DIRECTION_INHERIT,
1955         LAYOUT_DIRECTION_LOCALE
1956     })
1957     @Retention(RetentionPolicy.SOURCE)
1958     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1959     public @interface LayoutDir {}
1960 
1961     /** @hide */
1962     @IntDef({
1963         LAYOUT_DIRECTION_LTR,
1964         LAYOUT_DIRECTION_RTL
1965     })
1966     @Retention(RetentionPolicy.SOURCE)
1967     public @interface ResolvedLayoutDir {}
1968 
1969     /**
1970      * A flag to indicate that the layout direction of this view has not been defined yet.
1971      * @hide
1972      */
1973     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1974 
1975     /**
1976      * Horizontal layout direction of this view is from Left to Right.
1977      * Use with {@link #setLayoutDirection}.
1978      */
1979     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1980 
1981     /**
1982      * Horizontal layout direction of this view is from Right to Left.
1983      * Use with {@link #setLayoutDirection}.
1984      */
1985     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1986 
1987     /**
1988      * Horizontal layout direction of this view is inherited from its parent.
1989      * Use with {@link #setLayoutDirection}.
1990      */
1991     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1992 
1993     /**
1994      * Horizontal layout direction of this view is from deduced from the default language
1995      * script for the locale. Use with {@link #setLayoutDirection}.
1996      */
1997     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1998 
1999     /**
2000      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2001      * @hide
2002      */
2003     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2004 
2005     /**
2006      * Mask for use with private flags indicating bits used for horizontal layout direction.
2007      * @hide
2008      */
2009     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2010 
2011     /**
2012      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2013      * right-to-left direction.
2014      * @hide
2015      */
2016     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2017 
2018     /**
2019      * Indicates whether the view horizontal layout direction has been resolved.
2020      * @hide
2021      */
2022     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2023 
2024     /**
2025      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2026      * @hide
2027      */
2028     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2029             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2030 
2031     /*
2032      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2033      * flag value.
2034      * @hide
2035      */
2036     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2037             LAYOUT_DIRECTION_LTR,
2038             LAYOUT_DIRECTION_RTL,
2039             LAYOUT_DIRECTION_INHERIT,
2040             LAYOUT_DIRECTION_LOCALE
2041     };
2042 
2043     /**
2044      * Default horizontal layout direction.
2045      */
2046     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2047 
2048     /**
2049      * Default horizontal layout direction.
2050      * @hide
2051      */
2052     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2053 
2054     /**
2055      * Text direction is inherited through {@link ViewGroup}
2056      */
2057     public static final int TEXT_DIRECTION_INHERIT = 0;
2058 
2059     /**
2060      * Text direction is using "first strong algorithm". The first strong directional character
2061      * determines the paragraph direction. If there is no strong directional character, the
2062      * paragraph direction is the view's resolved layout direction.
2063      */
2064     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2065 
2066     /**
2067      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2068      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2069      * If there are neither, the paragraph direction is the view's resolved layout direction.
2070      */
2071     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2072 
2073     /**
2074      * Text direction is forced to LTR.
2075      */
2076     public static final int TEXT_DIRECTION_LTR = 3;
2077 
2078     /**
2079      * Text direction is forced to RTL.
2080      */
2081     public static final int TEXT_DIRECTION_RTL = 4;
2082 
2083     /**
2084      * Text direction is coming from the system Locale.
2085      */
2086     public static final int TEXT_DIRECTION_LOCALE = 5;
2087 
2088     /**
2089      * Text direction is using "first strong algorithm". The first strong directional character
2090      * determines the paragraph direction. If there is no strong directional character, the
2091      * paragraph direction is LTR.
2092      */
2093     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2094 
2095     /**
2096      * Text direction is using "first strong algorithm". The first strong directional character
2097      * determines the paragraph direction. If there is no strong directional character, the
2098      * paragraph direction is RTL.
2099      */
2100     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2101 
2102     /**
2103      * Default text direction is inherited
2104      */
2105     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2106 
2107     /**
2108      * Default resolved text direction
2109      * @hide
2110      */
2111     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2112 
2113     /**
2114      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2115      * @hide
2116      */
2117     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2118 
2119     /**
2120      * Mask for use with private flags indicating bits used for text direction.
2121      * @hide
2122      */
2123     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2124             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2125 
2126     /**
2127      * Array of text direction flags for mapping attribute "textDirection" to correct
2128      * flag value.
2129      * @hide
2130      */
2131     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2132             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2133             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2134             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2135             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2136             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2137             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2138             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2139             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2140     };
2141 
2142     /**
2143      * Indicates whether the view text direction has been resolved.
2144      * @hide
2145      */
2146     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2147             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2148 
2149     /**
2150      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2151      * @hide
2152      */
2153     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2154 
2155     /**
2156      * Mask for use with private flags indicating bits used for resolved text direction.
2157      * @hide
2158      */
2159     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2160             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2161 
2162     /**
2163      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2164      * @hide
2165      */
2166     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2167             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2168 
2169     /** @hide */
2170     @IntDef({
2171         TEXT_ALIGNMENT_INHERIT,
2172         TEXT_ALIGNMENT_GRAVITY,
2173         TEXT_ALIGNMENT_CENTER,
2174         TEXT_ALIGNMENT_TEXT_START,
2175         TEXT_ALIGNMENT_TEXT_END,
2176         TEXT_ALIGNMENT_VIEW_START,
2177         TEXT_ALIGNMENT_VIEW_END
2178     })
2179     @Retention(RetentionPolicy.SOURCE)
2180     public @interface TextAlignment {}
2181 
2182     /**
2183      * Default text alignment. The text alignment of this View is inherited from its parent.
2184      * Use with {@link #setTextAlignment(int)}
2185      */
2186     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2187 
2188     /**
2189      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2190      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2191      *
2192      * Use with {@link #setTextAlignment(int)}
2193      */
2194     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2195 
2196     /**
2197      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2198      *
2199      * Use with {@link #setTextAlignment(int)}
2200      */
2201     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2202 
2203     /**
2204      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2205      *
2206      * Use with {@link #setTextAlignment(int)}
2207      */
2208     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2209 
2210     /**
2211      * Center the paragraph, e.g. ALIGN_CENTER.
2212      *
2213      * Use with {@link #setTextAlignment(int)}
2214      */
2215     public static final int TEXT_ALIGNMENT_CENTER = 4;
2216 
2217     /**
2218      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2219      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2220      *
2221      * Use with {@link #setTextAlignment(int)}
2222      */
2223     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2224 
2225     /**
2226      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2227      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2228      *
2229      * Use with {@link #setTextAlignment(int)}
2230      */
2231     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2232 
2233     /**
2234      * Default text alignment is inherited
2235      */
2236     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2237 
2238     /**
2239      * Default resolved text alignment
2240      * @hide
2241      */
2242     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2243 
2244     /**
2245       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2246       * @hide
2247       */
2248     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2249 
2250     /**
2251       * Mask for use with private flags indicating bits used for text alignment.
2252       * @hide
2253       */
2254     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2255 
2256     /**
2257      * Array of text direction flags for mapping attribute "textAlignment" to correct
2258      * flag value.
2259      * @hide
2260      */
2261     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2262             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2263             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2264             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2265             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2266             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2267             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2268             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2269     };
2270 
2271     /**
2272      * Indicates whether the view text alignment has been resolved.
2273      * @hide
2274      */
2275     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2276 
2277     /**
2278      * Bit shift to get the resolved text alignment.
2279      * @hide
2280      */
2281     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2282 
2283     /**
2284      * Mask for use with private flags indicating bits used for text alignment.
2285      * @hide
2286      */
2287     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2288             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2289 
2290     /**
2291      * Indicates whether if the view text alignment has been resolved to gravity
2292      */
2293     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2294             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2295 
2296     // Accessiblity constants for mPrivateFlags2
2297 
2298     /**
2299      * Shift for the bits in {@link #mPrivateFlags2} related to the
2300      * "importantForAccessibility" attribute.
2301      */
2302     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2303 
2304     /**
2305      * Automatically determine whether a view is important for accessibility.
2306      */
2307     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2308 
2309     /**
2310      * The view is important for accessibility.
2311      */
2312     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2313 
2314     /**
2315      * The view is not important for accessibility.
2316      */
2317     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2318 
2319     /**
2320      * The view is not important for accessibility, nor are any of its
2321      * descendant views.
2322      */
2323     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2324 
2325     /**
2326      * The default whether the view is important for accessibility.
2327      */
2328     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2329 
2330     /**
2331      * Mask for obtainig the bits which specify how to determine
2332      * whether a view is important for accessibility.
2333      */
2334     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2335         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2336         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2337         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2338 
2339     /**
2340      * Shift for the bits in {@link #mPrivateFlags2} related to the
2341      * "accessibilityLiveRegion" attribute.
2342      */
2343     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2344 
2345     /**
2346      * Live region mode specifying that accessibility services should not
2347      * automatically announce changes to this view. This is the default live
2348      * region mode for most views.
2349      * <p>
2350      * Use with {@link #setAccessibilityLiveRegion(int)}.
2351      */
2352     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2353 
2354     /**
2355      * Live region mode specifying that accessibility services should announce
2356      * changes to this view.
2357      * <p>
2358      * Use with {@link #setAccessibilityLiveRegion(int)}.
2359      */
2360     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2361 
2362     /**
2363      * Live region mode specifying that accessibility services should interrupt
2364      * ongoing speech to immediately announce changes to this view.
2365      * <p>
2366      * Use with {@link #setAccessibilityLiveRegion(int)}.
2367      */
2368     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2369 
2370     /**
2371      * The default whether the view is important for accessibility.
2372      */
2373     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2374 
2375     /**
2376      * Mask for obtaining the bits which specify a view's accessibility live
2377      * region mode.
2378      */
2379     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2380             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2381             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2382 
2383     /**
2384      * Flag indicating whether a view has accessibility focus.
2385      */
2386     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2387 
2388     /**
2389      * Flag whether the accessibility state of the subtree rooted at this view changed.
2390      */
2391     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2392 
2393     /**
2394      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2395      * is used to check whether later changes to the view's transform should invalidate the
2396      * view to force the quickReject test to run again.
2397      */
2398     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2399 
2400     /**
2401      * Flag indicating that start/end padding has been resolved into left/right padding
2402      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2403      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2404      * during measurement. In some special cases this is required such as when an adapter-based
2405      * view measures prospective children without attaching them to a window.
2406      */
2407     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2408 
2409     /**
2410      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2411      */
2412     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2413 
2414     /**
2415      * Indicates that the view is tracking some sort of transient state
2416      * that the app should not need to be aware of, but that the framework
2417      * should take special care to preserve.
2418      */
2419     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2420 
2421     /**
2422      * Group of bits indicating that RTL properties resolution is done.
2423      */
2424     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2425             PFLAG2_TEXT_DIRECTION_RESOLVED |
2426             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2427             PFLAG2_PADDING_RESOLVED |
2428             PFLAG2_DRAWABLE_RESOLVED;
2429 
2430     // There are a couple of flags left in mPrivateFlags2
2431 
2432     /* End of masks for mPrivateFlags2 */
2433 
2434     /**
2435      * Masks for mPrivateFlags3, as generated by dumpFlags():
2436      *
2437      * |-------|-------|-------|-------|
2438      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2439      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2440      *                               1   PFLAG3_IS_LAID_OUT
2441      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2442      *                             1     PFLAG3_CALLED_SUPER
2443      *                            1      PFLAG3_APPLYING_INSETS
2444      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2445      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2446      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2447      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2448      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2449      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2450      *                     1             PFLAG3_SCROLL_INDICATOR_START
2451      *                    1              PFLAG3_SCROLL_INDICATOR_END
2452      *                   1               PFLAG3_ASSIST_BLOCKED
2453      *                  1                PFLAG3_POINTER_ICON_NULL
2454      *                 1                 PFLAG3_POINTER_ICON_VALUE_START
2455      *           11111111                PFLAG3_POINTER_ICON_MASK
2456      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2457      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2458      *        1                          PFLAG3_TEMPORARY_DETACH
2459      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2460      * |-------|-------|-------|-------|
2461      */
2462 
2463     /**
2464      * Flag indicating that view has a transform animation set on it. This is used to track whether
2465      * an animation is cleared between successive frames, in order to tell the associated
2466      * DisplayList to clear its animation matrix.
2467      */
2468     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2469 
2470     /**
2471      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2472      * animation is cleared between successive frames, in order to tell the associated
2473      * DisplayList to restore its alpha value.
2474      */
2475     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2476 
2477     /**
2478      * Flag indicating that the view has been through at least one layout since it
2479      * was last attached to a window.
2480      */
2481     static final int PFLAG3_IS_LAID_OUT = 0x4;
2482 
2483     /**
2484      * Flag indicating that a call to measure() was skipped and should be done
2485      * instead when layout() is invoked.
2486      */
2487     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2488 
2489     /**
2490      * Flag indicating that an overridden method correctly called down to
2491      * the superclass implementation as required by the API spec.
2492      */
2493     static final int PFLAG3_CALLED_SUPER = 0x10;
2494 
2495     /**
2496      * Flag indicating that we're in the process of applying window insets.
2497      */
2498     static final int PFLAG3_APPLYING_INSETS = 0x20;
2499 
2500     /**
2501      * Flag indicating that we're in the process of fitting system windows using the old method.
2502      */
2503     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2504 
2505     /**
2506      * Flag indicating that nested scrolling is enabled for this view.
2507      * The view will optionally cooperate with views up its parent chain to allow for
2508      * integrated nested scrolling along the same axis.
2509      */
2510     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2511 
2512     /**
2513      * Flag indicating that the bottom scroll indicator should be displayed
2514      * when this view can scroll up.
2515      */
2516     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2517 
2518     /**
2519      * Flag indicating that the bottom scroll indicator should be displayed
2520      * when this view can scroll down.
2521      */
2522     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2523 
2524     /**
2525      * Flag indicating that the left scroll indicator should be displayed
2526      * when this view can scroll left.
2527      */
2528     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2529 
2530     /**
2531      * Flag indicating that the right scroll indicator should be displayed
2532      * when this view can scroll right.
2533      */
2534     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2535 
2536     /**
2537      * Flag indicating that the start scroll indicator should be displayed
2538      * when this view can scroll in the start direction.
2539      */
2540     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2541 
2542     /**
2543      * Flag indicating that the end scroll indicator should be displayed
2544      * when this view can scroll in the end direction.
2545      */
2546     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2547 
2548     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2549 
2550     static final int SCROLL_INDICATORS_NONE = 0x0000;
2551 
2552     /**
2553      * Mask for use with setFlags indicating bits used for indicating which
2554      * scroll indicators are enabled.
2555      */
2556     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2557             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2558             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2559             | PFLAG3_SCROLL_INDICATOR_END;
2560 
2561     /**
2562      * Left-shift required to translate between public scroll indicator flags
2563      * and internal PFLAGS3 flags. When used as a right-shift, translates
2564      * PFLAGS3 flags to public flags.
2565      */
2566     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2567 
2568     /** @hide */
2569     @Retention(RetentionPolicy.SOURCE)
2570     @IntDef(flag = true,
2571             value = {
2572                     SCROLL_INDICATOR_TOP,
2573                     SCROLL_INDICATOR_BOTTOM,
2574                     SCROLL_INDICATOR_LEFT,
2575                     SCROLL_INDICATOR_RIGHT,
2576                     SCROLL_INDICATOR_START,
2577                     SCROLL_INDICATOR_END,
2578             })
2579     public @interface ScrollIndicators {}
2580 
2581     /**
2582      * Scroll indicator direction for the top edge of the view.
2583      *
2584      * @see #setScrollIndicators(int)
2585      * @see #setScrollIndicators(int, int)
2586      * @see #getScrollIndicators()
2587      */
2588     public static final int SCROLL_INDICATOR_TOP =
2589             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2590 
2591     /**
2592      * Scroll indicator direction for the bottom edge of the view.
2593      *
2594      * @see #setScrollIndicators(int)
2595      * @see #setScrollIndicators(int, int)
2596      * @see #getScrollIndicators()
2597      */
2598     public static final int SCROLL_INDICATOR_BOTTOM =
2599             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2600 
2601     /**
2602      * Scroll indicator direction for the left edge of the view.
2603      *
2604      * @see #setScrollIndicators(int)
2605      * @see #setScrollIndicators(int, int)
2606      * @see #getScrollIndicators()
2607      */
2608     public static final int SCROLL_INDICATOR_LEFT =
2609             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2610 
2611     /**
2612      * Scroll indicator direction for the right edge of the view.
2613      *
2614      * @see #setScrollIndicators(int)
2615      * @see #setScrollIndicators(int, int)
2616      * @see #getScrollIndicators()
2617      */
2618     public static final int SCROLL_INDICATOR_RIGHT =
2619             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2620 
2621     /**
2622      * Scroll indicator direction for the starting edge of the view.
2623      * <p>
2624      * Resolved according to the view's layout direction, see
2625      * {@link #getLayoutDirection()} for more information.
2626      *
2627      * @see #setScrollIndicators(int)
2628      * @see #setScrollIndicators(int, int)
2629      * @see #getScrollIndicators()
2630      */
2631     public static final int SCROLL_INDICATOR_START =
2632             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2633 
2634     /**
2635      * Scroll indicator direction for the ending edge of the view.
2636      * <p>
2637      * Resolved according to the view's layout direction, see
2638      * {@link #getLayoutDirection()} for more information.
2639      *
2640      * @see #setScrollIndicators(int)
2641      * @see #setScrollIndicators(int, int)
2642      * @see #getScrollIndicators()
2643      */
2644     public static final int SCROLL_INDICATOR_END =
2645             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2646 
2647     /**
2648      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2649      * into this view.<p>
2650      */
2651     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2652 
2653     /**
2654      * The mask for use with private flags indicating bits used for pointer icon shapes.
2655      */
2656     static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2657 
2658     /**
2659      * Left-shift used for pointer icon shape values in private flags.
2660      */
2661     static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2662 
2663     /**
2664      * Value indicating no specific pointer icons.
2665      */
2666     private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2667 
2668     /**
2669      * Value indicating {@link PointerIcon.TYPE_NULL}.
2670      */
2671     private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2672 
2673     /**
2674      * The base value for other pointer icon shapes.
2675      */
2676     private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2677 
2678     /**
2679      * Whether this view has rendered elements that overlap (see {@link
2680      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2681      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2682      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2683      * determined by whatever {@link #hasOverlappingRendering()} returns.
2684      */
2685     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2686 
2687     /**
2688      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2689      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2690      */
2691     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2692 
2693     /**
2694      * Flag indicating that the view is temporarily detached from the parent view.
2695      *
2696      * @see #onStartTemporaryDetach()
2697      * @see #onFinishTemporaryDetach()
2698      */
2699     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2700 
2701     /**
2702      * Flag indicating that the view does not wish to be revealed within its parent
2703      * hierarchy when it gains focus. Expressed in the negative since the historical
2704      * default behavior is to reveal on focus; this flag suppresses that behavior.
2705      *
2706      * @see #setRevealOnFocusHint(boolean)
2707      * @see #getRevealOnFocusHint()
2708      */
2709     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2710 
2711     /* End of masks for mPrivateFlags3 */
2712 
2713     /**
2714      * Always allow a user to over-scroll this view, provided it is a
2715      * view that can scroll.
2716      *
2717      * @see #getOverScrollMode()
2718      * @see #setOverScrollMode(int)
2719      */
2720     public static final int OVER_SCROLL_ALWAYS = 0;
2721 
2722     /**
2723      * Allow a user to over-scroll this view only if the content is large
2724      * enough to meaningfully scroll, provided it is a view that can scroll.
2725      *
2726      * @see #getOverScrollMode()
2727      * @see #setOverScrollMode(int)
2728      */
2729     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2730 
2731     /**
2732      * Never allow a user to over-scroll this view.
2733      *
2734      * @see #getOverScrollMode()
2735      * @see #setOverScrollMode(int)
2736      */
2737     public static final int OVER_SCROLL_NEVER = 2;
2738 
2739     /**
2740      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2741      * requested the system UI (status bar) to be visible (the default).
2742      *
2743      * @see #setSystemUiVisibility(int)
2744      */
2745     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2746 
2747     /**
2748      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2749      * system UI to enter an unobtrusive "low profile" mode.
2750      *
2751      * <p>This is for use in games, book readers, video players, or any other
2752      * "immersive" application where the usual system chrome is deemed too distracting.
2753      *
2754      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2755      *
2756      * @see #setSystemUiVisibility(int)
2757      */
2758     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2759 
2760     /**
2761      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2762      * system navigation be temporarily hidden.
2763      *
2764      * <p>This is an even less obtrusive state than that called for by
2765      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2766      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2767      * those to disappear. This is useful (in conjunction with the
2768      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2769      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2770      * window flags) for displaying content using every last pixel on the display.
2771      *
2772      * <p>There is a limitation: because navigation controls are so important, the least user
2773      * interaction will cause them to reappear immediately.  When this happens, both
2774      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2775      * so that both elements reappear at the same time.
2776      *
2777      * @see #setSystemUiVisibility(int)
2778      */
2779     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2780 
2781     /**
2782      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2783      * into the normal fullscreen mode so that its content can take over the screen
2784      * while still allowing the user to interact with the application.
2785      *
2786      * <p>This has the same visual effect as
2787      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2788      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2789      * meaning that non-critical screen decorations (such as the status bar) will be
2790      * hidden while the user is in the View's window, focusing the experience on
2791      * that content.  Unlike the window flag, if you are using ActionBar in
2792      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2793      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2794      * hide the action bar.
2795      *
2796      * <p>This approach to going fullscreen is best used over the window flag when
2797      * it is a transient state -- that is, the application does this at certain
2798      * points in its user interaction where it wants to allow the user to focus
2799      * on content, but not as a continuous state.  For situations where the application
2800      * would like to simply stay full screen the entire time (such as a game that
2801      * wants to take over the screen), the
2802      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2803      * is usually a better approach.  The state set here will be removed by the system
2804      * in various situations (such as the user moving to another application) like
2805      * the other system UI states.
2806      *
2807      * <p>When using this flag, the application should provide some easy facility
2808      * for the user to go out of it.  A common example would be in an e-book
2809      * reader, where tapping on the screen brings back whatever screen and UI
2810      * decorations that had been hidden while the user was immersed in reading
2811      * the book.
2812      *
2813      * @see #setSystemUiVisibility(int)
2814      */
2815     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2816 
2817     /**
2818      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2819      * flags, we would like a stable view of the content insets given to
2820      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2821      * will always represent the worst case that the application can expect
2822      * as a continuous state.  In the stock Android UI this is the space for
2823      * the system bar, nav bar, and status bar, but not more transient elements
2824      * such as an input method.
2825      *
2826      * The stable layout your UI sees is based on the system UI modes you can
2827      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2828      * then you will get a stable layout for changes of the
2829      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2830      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2831      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2832      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2833      * with a stable layout.  (Note that you should avoid using
2834      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2835      *
2836      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2837      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2838      * then a hidden status bar will be considered a "stable" state for purposes
2839      * here.  This allows your UI to continually hide the status bar, while still
2840      * using the system UI flags to hide the action bar while still retaining
2841      * a stable layout.  Note that changing the window fullscreen flag will never
2842      * provide a stable layout for a clean transition.
2843      *
2844      * <p>If you are using ActionBar in
2845      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2846      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2847      * insets it adds to those given to the application.
2848      */
2849     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2850 
2851     /**
2852      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2853      * to be laid out as if it has requested
2854      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2855      * allows it to avoid artifacts when switching in and out of that mode, at
2856      * the expense that some of its user interface may be covered by screen
2857      * decorations when they are shown.  You can perform layout of your inner
2858      * UI elements to account for the navigation system UI through the
2859      * {@link #fitSystemWindows(Rect)} method.
2860      */
2861     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2862 
2863     /**
2864      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2865      * to be laid out as if it has requested
2866      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2867      * allows it to avoid artifacts when switching in and out of that mode, at
2868      * the expense that some of its user interface may be covered by screen
2869      * decorations when they are shown.  You can perform layout of your inner
2870      * UI elements to account for non-fullscreen system UI through the
2871      * {@link #fitSystemWindows(Rect)} method.
2872      */
2873     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2874 
2875     /**
2876      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2877      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2878      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2879      * user interaction.
2880      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2881      * has an effect when used in combination with that flag.</p>
2882      */
2883     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2884 
2885     /**
2886      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2887      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2888      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2889      * experience while also hiding the system bars.  If this flag is not set,
2890      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2891      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2892      * if the user swipes from the top of the screen.
2893      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2894      * system gestures, such as swiping from the top of the screen.  These transient system bars
2895      * will overlay app’s content, may have some degree of transparency, and will automatically
2896      * hide after a short timeout.
2897      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2898      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2899      * with one or both of those flags.</p>
2900      */
2901     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2902 
2903     /**
2904      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2905      * is compatible with light status bar backgrounds.
2906      *
2907      * <p>For this to take effect, the window must request
2908      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2909      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2910      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2911      *         FLAG_TRANSLUCENT_STATUS}.
2912      *
2913      * @see android.R.attr#windowLightStatusBar
2914      */
2915     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2916 
2917     /**
2918      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2919      */
2920     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2921 
2922     /**
2923      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2924      */
2925     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2926 
2927     /**
2928      * @hide
2929      *
2930      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2931      * out of the public fields to keep the undefined bits out of the developer's way.
2932      *
2933      * Flag to make the status bar not expandable.  Unless you also
2934      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2935      */
2936     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2937 
2938     /**
2939      * @hide
2940      *
2941      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2942      * out of the public fields to keep the undefined bits out of the developer's way.
2943      *
2944      * Flag to hide notification icons and scrolling ticker text.
2945      */
2946     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2947 
2948     /**
2949      * @hide
2950      *
2951      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2952      * out of the public fields to keep the undefined bits out of the developer's way.
2953      *
2954      * Flag to disable incoming notification alerts.  This will not block
2955      * icons, but it will block sound, vibrating and other visual or aural notifications.
2956      */
2957     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2958 
2959     /**
2960      * @hide
2961      *
2962      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2963      * out of the public fields to keep the undefined bits out of the developer's way.
2964      *
2965      * Flag to hide only the scrolling ticker.  Note that
2966      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2967      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2968      */
2969     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2970 
2971     /**
2972      * @hide
2973      *
2974      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2975      * out of the public fields to keep the undefined bits out of the developer's way.
2976      *
2977      * Flag to hide the center system info area.
2978      */
2979     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2980 
2981     /**
2982      * @hide
2983      *
2984      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2985      * out of the public fields to keep the undefined bits out of the developer's way.
2986      *
2987      * Flag to hide only the home button.  Don't use this
2988      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2989      */
2990     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2991 
2992     /**
2993      * @hide
2994      *
2995      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2996      * out of the public fields to keep the undefined bits out of the developer's way.
2997      *
2998      * Flag to hide only the back button. Don't use this
2999      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3000      */
3001     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3002 
3003     /**
3004      * @hide
3005      *
3006      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3007      * out of the public fields to keep the undefined bits out of the developer's way.
3008      *
3009      * Flag to hide only the clock.  You might use this if your activity has
3010      * its own clock making the status bar's clock redundant.
3011      */
3012     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3013 
3014     /**
3015      * @hide
3016      *
3017      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3018      * out of the public fields to keep the undefined bits out of the developer's way.
3019      *
3020      * Flag to hide only the recent apps button. Don't use this
3021      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3022      */
3023     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3024 
3025     /**
3026      * @hide
3027      *
3028      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3029      * out of the public fields to keep the undefined bits out of the developer's way.
3030      *
3031      * Flag to disable the global search gesture. Don't use this
3032      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3033      */
3034     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3035 
3036     /**
3037      * @hide
3038      *
3039      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3040      * out of the public fields to keep the undefined bits out of the developer's way.
3041      *
3042      * Flag to specify that the status bar is displayed in transient mode.
3043      */
3044     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3045 
3046     /**
3047      * @hide
3048      *
3049      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3050      * out of the public fields to keep the undefined bits out of the developer's way.
3051      *
3052      * Flag to specify that the navigation bar is displayed in transient mode.
3053      */
3054     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3055 
3056     /**
3057      * @hide
3058      *
3059      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3060      * out of the public fields to keep the undefined bits out of the developer's way.
3061      *
3062      * Flag to specify that the hidden status bar would like to be shown.
3063      */
3064     public static final int STATUS_BAR_UNHIDE = 0x10000000;
3065 
3066     /**
3067      * @hide
3068      *
3069      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3070      * out of the public fields to keep the undefined bits out of the developer's way.
3071      *
3072      * Flag to specify that the hidden navigation bar would like to be shown.
3073      */
3074     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3075 
3076     /**
3077      * @hide
3078      *
3079      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3080      * out of the public fields to keep the undefined bits out of the developer's way.
3081      *
3082      * Flag to specify that the status bar is displayed in translucent mode.
3083      */
3084     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3085 
3086     /**
3087      * @hide
3088      *
3089      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3090      * out of the public fields to keep the undefined bits out of the developer's way.
3091      *
3092      * Flag to specify that the navigation bar is displayed in translucent mode.
3093      */
3094     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3095 
3096     /**
3097      * @hide
3098      *
3099      * Makes navigation bar transparent (but not the status bar).
3100      */
3101     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3102 
3103     /**
3104      * @hide
3105      *
3106      * Makes status bar transparent (but not the navigation bar).
3107      */
3108     public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3109 
3110     /**
3111      * @hide
3112      *
3113      * Makes both status bar and navigation bar transparent.
3114      */
3115     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3116             | STATUS_BAR_TRANSPARENT;
3117 
3118     /**
3119      * @hide
3120      */
3121     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3122 
3123     /**
3124      * These are the system UI flags that can be cleared by events outside
3125      * of an application.  Currently this is just the ability to tap on the
3126      * screen while hiding the navigation bar to have it return.
3127      * @hide
3128      */
3129     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3130             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3131             | SYSTEM_UI_FLAG_FULLSCREEN;
3132 
3133     /**
3134      * Flags that can impact the layout in relation to system UI.
3135      */
3136     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3137             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3138             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3139 
3140     /** @hide */
3141     @IntDef(flag = true,
3142             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3143     @Retention(RetentionPolicy.SOURCE)
3144     public @interface FindViewFlags {}
3145 
3146     /**
3147      * Find views that render the specified text.
3148      *
3149      * @see #findViewsWithText(ArrayList, CharSequence, int)
3150      */
3151     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3152 
3153     /**
3154      * Find find views that contain the specified content description.
3155      *
3156      * @see #findViewsWithText(ArrayList, CharSequence, int)
3157      */
3158     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3159 
3160     /**
3161      * Find views that contain {@link AccessibilityNodeProvider}. Such
3162      * a View is a root of virtual view hierarchy and may contain the searched
3163      * text. If this flag is set Views with providers are automatically
3164      * added and it is a responsibility of the client to call the APIs of
3165      * the provider to determine whether the virtual tree rooted at this View
3166      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3167      * representing the virtual views with this text.
3168      *
3169      * @see #findViewsWithText(ArrayList, CharSequence, int)
3170      *
3171      * @hide
3172      */
3173     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3174 
3175     /**
3176      * The undefined cursor position.
3177      *
3178      * @hide
3179      */
3180     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3181 
3182     /**
3183      * Indicates that the screen has changed state and is now off.
3184      *
3185      * @see #onScreenStateChanged(int)
3186      */
3187     public static final int SCREEN_STATE_OFF = 0x0;
3188 
3189     /**
3190      * Indicates that the screen has changed state and is now on.
3191      *
3192      * @see #onScreenStateChanged(int)
3193      */
3194     public static final int SCREEN_STATE_ON = 0x1;
3195 
3196     /**
3197      * Indicates no axis of view scrolling.
3198      */
3199     public static final int SCROLL_AXIS_NONE = 0;
3200 
3201     /**
3202      * Indicates scrolling along the horizontal axis.
3203      */
3204     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3205 
3206     /**
3207      * Indicates scrolling along the vertical axis.
3208      */
3209     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3210 
3211     /**
3212      * Controls the over-scroll mode for this view.
3213      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3214      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3215      * and {@link #OVER_SCROLL_NEVER}.
3216      */
3217     private int mOverScrollMode;
3218 
3219     /**
3220      * The parent this view is attached to.
3221      * {@hide}
3222      *
3223      * @see #getParent()
3224      */
3225     protected ViewParent mParent;
3226 
3227     /**
3228      * {@hide}
3229      */
3230     AttachInfo mAttachInfo;
3231 
3232     /**
3233      * {@hide}
3234      */
3235     @ViewDebug.ExportedProperty(flagMapping = {
3236         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3237                 name = "FORCE_LAYOUT"),
3238         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3239                 name = "LAYOUT_REQUIRED"),
3240         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3241             name = "DRAWING_CACHE_INVALID", outputIf = false),
3242         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3243         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3244         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3245         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3246     }, formatToHexString = true)
3247     int mPrivateFlags;
3248     int mPrivateFlags2;
3249     int mPrivateFlags3;
3250 
3251     /**
3252      * This view's request for the visibility of the status bar.
3253      * @hide
3254      */
3255     @ViewDebug.ExportedProperty(flagMapping = {
3256         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3257                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3258                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3259         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3260                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3261                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3262         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3263                                 equals = SYSTEM_UI_FLAG_VISIBLE,
3264                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3265     }, formatToHexString = true)
3266     int mSystemUiVisibility;
3267 
3268     /**
3269      * Reference count for transient state.
3270      * @see #setHasTransientState(boolean)
3271      */
3272     int mTransientStateCount = 0;
3273 
3274     /**
3275      * Count of how many windows this view has been attached to.
3276      */
3277     int mWindowAttachCount;
3278 
3279     /**
3280      * The layout parameters associated with this view and used by the parent
3281      * {@link android.view.ViewGroup} to determine how this view should be
3282      * laid out.
3283      * {@hide}
3284      */
3285     protected ViewGroup.LayoutParams mLayoutParams;
3286 
3287     /**
3288      * The view flags hold various views states.
3289      * {@hide}
3290      */
3291     @ViewDebug.ExportedProperty(formatToHexString = true)
3292     int mViewFlags;
3293 
3294     static class TransformationInfo {
3295         /**
3296          * The transform matrix for the View. This transform is calculated internally
3297          * based on the translation, rotation, and scale properties.
3298          *
3299          * Do *not* use this variable directly; instead call getMatrix(), which will
3300          * load the value from the View's RenderNode.
3301          */
3302         private final Matrix mMatrix = new Matrix();
3303 
3304         /**
3305          * The inverse transform matrix for the View. This transform is calculated
3306          * internally based on the translation, rotation, and scale properties.
3307          *
3308          * Do *not* use this variable directly; instead call getInverseMatrix(),
3309          * which will load the value from the View's RenderNode.
3310          */
3311         private Matrix mInverseMatrix;
3312 
3313         /**
3314          * The opacity of the View. This is a value from 0 to 1, where 0 means
3315          * completely transparent and 1 means completely opaque.
3316          */
3317         @ViewDebug.ExportedProperty
3318         float mAlpha = 1f;
3319 
3320         /**
3321          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3322          * property only used by transitions, which is composited with the other alpha
3323          * values to calculate the final visual alpha value.
3324          */
3325         float mTransitionAlpha = 1f;
3326     }
3327 
3328     TransformationInfo mTransformationInfo;
3329 
3330     /**
3331      * Current clip bounds. to which all drawing of this view are constrained.
3332      */
3333     Rect mClipBounds = null;
3334 
3335     private boolean mLastIsOpaque;
3336 
3337     /**
3338      * The distance in pixels from the left edge of this view's parent
3339      * to the left edge of this view.
3340      * {@hide}
3341      */
3342     @ViewDebug.ExportedProperty(category = "layout")
3343     protected int mLeft;
3344     /**
3345      * The distance in pixels from the left edge of this view's parent
3346      * to the right edge of this view.
3347      * {@hide}
3348      */
3349     @ViewDebug.ExportedProperty(category = "layout")
3350     protected int mRight;
3351     /**
3352      * The distance in pixels from the top edge of this view's parent
3353      * to the top edge of this view.
3354      * {@hide}
3355      */
3356     @ViewDebug.ExportedProperty(category = "layout")
3357     protected int mTop;
3358     /**
3359      * The distance in pixels from the top edge of this view's parent
3360      * to the bottom edge of this view.
3361      * {@hide}
3362      */
3363     @ViewDebug.ExportedProperty(category = "layout")
3364     protected int mBottom;
3365 
3366     /**
3367      * The offset, in pixels, by which the content of this view is scrolled
3368      * horizontally.
3369      * {@hide}
3370      */
3371     @ViewDebug.ExportedProperty(category = "scrolling")
3372     protected int mScrollX;
3373     /**
3374      * The offset, in pixels, by which the content of this view is scrolled
3375      * vertically.
3376      * {@hide}
3377      */
3378     @ViewDebug.ExportedProperty(category = "scrolling")
3379     protected int mScrollY;
3380 
3381     /**
3382      * The left padding in pixels, that is the distance in pixels between the
3383      * left edge of this view and the left edge of its content.
3384      * {@hide}
3385      */
3386     @ViewDebug.ExportedProperty(category = "padding")
3387     protected int mPaddingLeft = 0;
3388     /**
3389      * The right padding in pixels, that is the distance in pixels between the
3390      * right edge of this view and the right edge of its content.
3391      * {@hide}
3392      */
3393     @ViewDebug.ExportedProperty(category = "padding")
3394     protected int mPaddingRight = 0;
3395     /**
3396      * The top padding in pixels, that is the distance in pixels between the
3397      * top edge of this view and the top edge of its content.
3398      * {@hide}
3399      */
3400     @ViewDebug.ExportedProperty(category = "padding")
3401     protected int mPaddingTop;
3402     /**
3403      * The bottom padding in pixels, that is the distance in pixels between the
3404      * bottom edge of this view and the bottom edge of its content.
3405      * {@hide}
3406      */
3407     @ViewDebug.ExportedProperty(category = "padding")
3408     protected int mPaddingBottom;
3409 
3410     /**
3411      * The layout insets in pixels, that is the distance in pixels between the
3412      * visible edges of this view its bounds.
3413      */
3414     private Insets mLayoutInsets;
3415 
3416     /**
3417      * Briefly describes the view and is primarily used for accessibility support.
3418      */
3419     private CharSequence mContentDescription;
3420 
3421     /**
3422      * Specifies the id of a view for which this view serves as a label for
3423      * accessibility purposes.
3424      */
3425     private int mLabelForId = View.NO_ID;
3426 
3427     /**
3428      * Predicate for matching labeled view id with its label for
3429      * accessibility purposes.
3430      */
3431     private MatchLabelForPredicate mMatchLabelForPredicate;
3432 
3433     /**
3434      * Specifies a view before which this one is visited in accessibility traversal.
3435      */
3436     private int mAccessibilityTraversalBeforeId = NO_ID;
3437 
3438     /**
3439      * Specifies a view after which this one is visited in accessibility traversal.
3440      */
3441     private int mAccessibilityTraversalAfterId = NO_ID;
3442 
3443     /**
3444      * Predicate for matching a view by its id.
3445      */
3446     private MatchIdPredicate mMatchIdPredicate;
3447 
3448     /**
3449      * Cache the paddingRight set by the user to append to the scrollbar's size.
3450      *
3451      * @hide
3452      */
3453     @ViewDebug.ExportedProperty(category = "padding")
3454     protected int mUserPaddingRight;
3455 
3456     /**
3457      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3458      *
3459      * @hide
3460      */
3461     @ViewDebug.ExportedProperty(category = "padding")
3462     protected int mUserPaddingBottom;
3463 
3464     /**
3465      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3466      *
3467      * @hide
3468      */
3469     @ViewDebug.ExportedProperty(category = "padding")
3470     protected int mUserPaddingLeft;
3471 
3472     /**
3473      * Cache the paddingStart set by the user to append to the scrollbar's size.
3474      *
3475      */
3476     @ViewDebug.ExportedProperty(category = "padding")
3477     int mUserPaddingStart;
3478 
3479     /**
3480      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3481      *
3482      */
3483     @ViewDebug.ExportedProperty(category = "padding")
3484     int mUserPaddingEnd;
3485 
3486     /**
3487      * Cache initial left padding.
3488      *
3489      * @hide
3490      */
3491     int mUserPaddingLeftInitial;
3492 
3493     /**
3494      * Cache initial right padding.
3495      *
3496      * @hide
3497      */
3498     int mUserPaddingRightInitial;
3499 
3500     /**
3501      * Default undefined padding
3502      */
3503     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3504 
3505     /**
3506      * Cache if a left padding has been defined
3507      */
3508     private boolean mLeftPaddingDefined = false;
3509 
3510     /**
3511      * Cache if a right padding has been defined
3512      */
3513     private boolean mRightPaddingDefined = false;
3514 
3515     /**
3516      * @hide
3517      */
3518     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3519     /**
3520      * @hide
3521      */
3522     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3523 
3524     private LongSparseLongArray mMeasureCache;
3525 
3526     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3527     private Drawable mBackground;
3528     private TintInfo mBackgroundTint;
3529 
3530     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3531     private ForegroundInfo mForegroundInfo;
3532 
3533     private Drawable mScrollIndicatorDrawable;
3534 
3535     /**
3536      * RenderNode used for backgrounds.
3537      * <p>
3538      * When non-null and valid, this is expected to contain an up-to-date copy
3539      * of the background drawable. It is cleared on temporary detach, and reset
3540      * on cleanup.
3541      */
3542     private RenderNode mBackgroundRenderNode;
3543 
3544     private int mBackgroundResource;
3545     private boolean mBackgroundSizeChanged;
3546 
3547     private String mTransitionName;
3548 
3549     static class TintInfo {
3550         ColorStateList mTintList;
3551         PorterDuff.Mode mTintMode;
3552         boolean mHasTintMode;
3553         boolean mHasTintList;
3554     }
3555 
3556     private static class ForegroundInfo {
3557         private Drawable mDrawable;
3558         private TintInfo mTintInfo;
3559         private int mGravity = Gravity.FILL;
3560         private boolean mInsidePadding = true;
3561         private boolean mBoundsChanged = true;
3562         private final Rect mSelfBounds = new Rect();
3563         private final Rect mOverlayBounds = new Rect();
3564     }
3565 
3566     static class ListenerInfo {
3567         /**
3568          * Listener used to dispatch focus change events.
3569          * This field should be made private, so it is hidden from the SDK.
3570          * {@hide}
3571          */
3572         protected OnFocusChangeListener mOnFocusChangeListener;
3573 
3574         /**
3575          * Listeners for layout change events.
3576          */
3577         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3578 
3579         protected OnScrollChangeListener mOnScrollChangeListener;
3580 
3581         /**
3582          * Listeners for attach events.
3583          */
3584         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3585 
3586         /**
3587          * Listener used to dispatch click events.
3588          * This field should be made private, so it is hidden from the SDK.
3589          * {@hide}
3590          */
3591         public OnClickListener mOnClickListener;
3592 
3593         /**
3594          * Listener used to dispatch long click events.
3595          * This field should be made private, so it is hidden from the SDK.
3596          * {@hide}
3597          */
3598         protected OnLongClickListener mOnLongClickListener;
3599 
3600         /**
3601          * Listener used to dispatch context click events. This field should be made private, so it
3602          * is hidden from the SDK.
3603          * {@hide}
3604          */
3605         protected OnContextClickListener mOnContextClickListener;
3606 
3607         /**
3608          * Listener used to build the context menu.
3609          * This field should be made private, so it is hidden from the SDK.
3610          * {@hide}
3611          */
3612         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3613 
3614         private OnKeyListener mOnKeyListener;
3615 
3616         private OnTouchListener mOnTouchListener;
3617 
3618         private OnHoverListener mOnHoverListener;
3619 
3620         private OnGenericMotionListener mOnGenericMotionListener;
3621 
3622         private OnDragListener mOnDragListener;
3623 
3624         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3625 
3626         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3627     }
3628 
3629     ListenerInfo mListenerInfo;
3630 
3631     // Temporary values used to hold (x,y) coordinates when delegating from the
3632     // two-arg performLongClick() method to the legacy no-arg version.
3633     private float mLongClickX = Float.NaN;
3634     private float mLongClickY = Float.NaN;
3635 
3636     /**
3637      * The application environment this view lives in.
3638      * This field should be made private, so it is hidden from the SDK.
3639      * {@hide}
3640      */
3641     @ViewDebug.ExportedProperty(deepExport = true)
3642     protected Context mContext;
3643 
3644     private final Resources mResources;
3645 
3646     private ScrollabilityCache mScrollCache;
3647 
3648     private int[] mDrawableState = null;
3649 
3650     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3651 
3652     /**
3653      * Animator that automatically runs based on state changes.
3654      */
3655     private StateListAnimator mStateListAnimator;
3656 
3657     /**
3658      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3659      * the user may specify which view to go to next.
3660      */
3661     private int mNextFocusLeftId = View.NO_ID;
3662 
3663     /**
3664      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3665      * the user may specify which view to go to next.
3666      */
3667     private int mNextFocusRightId = View.NO_ID;
3668 
3669     /**
3670      * When this view has focus and the next focus is {@link #FOCUS_UP},
3671      * the user may specify which view to go to next.
3672      */
3673     private int mNextFocusUpId = View.NO_ID;
3674 
3675     /**
3676      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3677      * the user may specify which view to go to next.
3678      */
3679     private int mNextFocusDownId = View.NO_ID;
3680 
3681     /**
3682      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3683      * the user may specify which view to go to next.
3684      */
3685     int mNextFocusForwardId = View.NO_ID;
3686 
3687     private CheckForLongPress mPendingCheckForLongPress;
3688     private CheckForTap mPendingCheckForTap = null;
3689     private PerformClick mPerformClick;
3690     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3691 
3692     private UnsetPressedState mUnsetPressedState;
3693 
3694     /**
3695      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3696      * up event while a long press is invoked as soon as the long press duration is reached, so
3697      * a long press could be performed before the tap is checked, in which case the tap's action
3698      * should not be invoked.
3699      */
3700     private boolean mHasPerformedLongPress;
3701 
3702     /**
3703      * Whether a context click button is currently pressed down. This is true when the stylus is
3704      * touching the screen and the primary button has been pressed, or if a mouse's right button is
3705      * pressed. This is false once the button is released or if the stylus has been lifted.
3706      */
3707     private boolean mInContextButtonPress;
3708 
3709     /**
3710      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3711      * true after a stylus button press has occured, when the next up event should not be recognized
3712      * as a tap.
3713      */
3714     private boolean mIgnoreNextUpEvent;
3715 
3716     /**
3717      * The minimum height of the view. We'll try our best to have the height
3718      * of this view to at least this amount.
3719      */
3720     @ViewDebug.ExportedProperty(category = "measurement")
3721     private int mMinHeight;
3722 
3723     /**
3724      * The minimum width of the view. We'll try our best to have the width
3725      * of this view to at least this amount.
3726      */
3727     @ViewDebug.ExportedProperty(category = "measurement")
3728     private int mMinWidth;
3729 
3730     /**
3731      * The delegate to handle touch events that are physically in this view
3732      * but should be handled by another view.
3733      */
3734     private TouchDelegate mTouchDelegate = null;
3735 
3736     /**
3737      * Solid color to use as a background when creating the drawing cache. Enables
3738      * the cache to use 16 bit bitmaps instead of 32 bit.
3739      */
3740     private int mDrawingCacheBackgroundColor = 0;
3741 
3742     /**
3743      * Special tree observer used when mAttachInfo is null.
3744      */
3745     private ViewTreeObserver mFloatingTreeObserver;
3746 
3747     /**
3748      * Cache the touch slop from the context that created the view.
3749      */
3750     private int mTouchSlop;
3751 
3752     /**
3753      * Object that handles automatic animation of view properties.
3754      */
3755     private ViewPropertyAnimator mAnimator = null;
3756 
3757     /**
3758      * List of registered FrameMetricsObservers.
3759      */
3760     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3761 
3762     /**
3763      * Flag indicating that a drag can cross window boundaries.  When
3764      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3765      * with this flag set, all visible applications with targetSdkVersion >=
3766      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3767      * in the drag operation and receive the dragged content.
3768      *
3769      * <p>If this is the only flag set, then the drag recipient will only have access to text data
3770      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3771      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3772      */
3773     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3774 
3775     /**
3776      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3777      * request read access to the content URI(s) contained in the {@link ClipData} object.
3778      * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3779      */
3780     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3781 
3782     /**
3783      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3784      * request write access to the content URI(s) contained in the {@link ClipData} object.
3785      * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3786      */
3787     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3788 
3789     /**
3790      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3791      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3792      * reboots until explicitly revoked with
3793      * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3794      * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3795      */
3796     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3797             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3798 
3799     /**
3800      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3801      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3802      * match against the original granted URI.
3803      * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3804      */
3805     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3806             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3807 
3808     /**
3809      * Flag indicating that the drag shadow will be opaque.  When
3810      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3811      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3812      */
3813     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3814 
3815     /**
3816      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3817      */
3818     private float mVerticalScrollFactor;
3819 
3820     /**
3821      * Position of the vertical scroll bar.
3822      */
3823     private int mVerticalScrollbarPosition;
3824 
3825     /**
3826      * Position the scroll bar at the default position as determined by the system.
3827      */
3828     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3829 
3830     /**
3831      * Position the scroll bar along the left edge.
3832      */
3833     public static final int SCROLLBAR_POSITION_LEFT = 1;
3834 
3835     /**
3836      * Position the scroll bar along the right edge.
3837      */
3838     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3839 
3840     /**
3841      * Indicates that the view does not have a layer.
3842      *
3843      * @see #getLayerType()
3844      * @see #setLayerType(int, android.graphics.Paint)
3845      * @see #LAYER_TYPE_SOFTWARE
3846      * @see #LAYER_TYPE_HARDWARE
3847      */
3848     public static final int LAYER_TYPE_NONE = 0;
3849 
3850     /**
3851      * <p>Indicates that the view has a software layer. A software layer is backed
3852      * by a bitmap and causes the view to be rendered using Android's software
3853      * rendering pipeline, even if hardware acceleration is enabled.</p>
3854      *
3855      * <p>Software layers have various usages:</p>
3856      * <p>When the application is not using hardware acceleration, a software layer
3857      * is useful to apply a specific color filter and/or blending mode and/or
3858      * translucency to a view and all its children.</p>
3859      * <p>When the application is using hardware acceleration, a software layer
3860      * is useful to render drawing primitives not supported by the hardware
3861      * accelerated pipeline. It can also be used to cache a complex view tree
3862      * into a texture and reduce the complexity of drawing operations. For instance,
3863      * when animating a complex view tree with a translation, a software layer can
3864      * be used to render the view tree only once.</p>
3865      * <p>Software layers should be avoided when the affected view tree updates
3866      * often. Every update will require to re-render the software layer, which can
3867      * potentially be slow (particularly when hardware acceleration is turned on
3868      * since the layer will have to be uploaded into a hardware texture after every
3869      * update.)</p>
3870      *
3871      * @see #getLayerType()
3872      * @see #setLayerType(int, android.graphics.Paint)
3873      * @see #LAYER_TYPE_NONE
3874      * @see #LAYER_TYPE_HARDWARE
3875      */
3876     public static final int LAYER_TYPE_SOFTWARE = 1;
3877 
3878     /**
3879      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3880      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3881      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3882      * rendering pipeline, but only if hardware acceleration is turned on for the
3883      * view hierarchy. When hardware acceleration is turned off, hardware layers
3884      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3885      *
3886      * <p>A hardware layer is useful to apply a specific color filter and/or
3887      * blending mode and/or translucency to a view and all its children.</p>
3888      * <p>A hardware layer can be used to cache a complex view tree into a
3889      * texture and reduce the complexity of drawing operations. For instance,
3890      * when animating a complex view tree with a translation, a hardware layer can
3891      * be used to render the view tree only once.</p>
3892      * <p>A hardware layer can also be used to increase the rendering quality when
3893      * rotation transformations are applied on a view. It can also be used to
3894      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3895      *
3896      * @see #getLayerType()
3897      * @see #setLayerType(int, android.graphics.Paint)
3898      * @see #LAYER_TYPE_NONE
3899      * @see #LAYER_TYPE_SOFTWARE
3900      */
3901     public static final int LAYER_TYPE_HARDWARE = 2;
3902 
3903     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3904             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3905             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3906             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3907     })
3908     int mLayerType = LAYER_TYPE_NONE;
3909     Paint mLayerPaint;
3910 
3911     /**
3912      * Set to true when drawing cache is enabled and cannot be created.
3913      *
3914      * @hide
3915      */
3916     public boolean mCachingFailed;
3917     private Bitmap mDrawingCache;
3918     private Bitmap mUnscaledDrawingCache;
3919 
3920     /**
3921      * RenderNode holding View properties, potentially holding a DisplayList of View content.
3922      * <p>
3923      * When non-null and valid, this is expected to contain an up-to-date copy
3924      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3925      * cleanup.
3926      */
3927     final RenderNode mRenderNode;
3928 
3929     /**
3930      * Set to true when the view is sending hover accessibility events because it
3931      * is the innermost hovered view.
3932      */
3933     private boolean mSendingHoverAccessibilityEvents;
3934 
3935     /**
3936      * Delegate for injecting accessibility functionality.
3937      */
3938     AccessibilityDelegate mAccessibilityDelegate;
3939 
3940     /**
3941      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3942      * and add/remove objects to/from the overlay directly through the Overlay methods.
3943      */
3944     ViewOverlay mOverlay;
3945 
3946     /**
3947      * The currently active parent view for receiving delegated nested scrolling events.
3948      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3949      * by {@link #stopNestedScroll()} at the same point where we clear
3950      * requestDisallowInterceptTouchEvent.
3951      */
3952     private ViewParent mNestedScrollingParent;
3953 
3954     /**
3955      * Consistency verifier for debugging purposes.
3956      * @hide
3957      */
3958     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3959             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3960                     new InputEventConsistencyVerifier(this, 0) : null;
3961 
3962     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3963 
3964     private int[] mTempNestedScrollConsumed;
3965 
3966     /**
3967      * An overlay is going to draw this View instead of being drawn as part of this
3968      * View's parent. mGhostView is the View in the Overlay that must be invalidated
3969      * when this view is invalidated.
3970      */
3971     GhostView mGhostView;
3972 
3973     /**
3974      * Holds pairs of adjacent attribute data: attribute name followed by its value.
3975      * @hide
3976      */
3977     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3978     public String[] mAttributes;
3979 
3980     /**
3981      * Maps a Resource id to its name.
3982      */
3983     private static SparseArray<String> mAttributeMap;
3984 
3985     /**
3986      * Queue of pending runnables. Used to postpone calls to post() until this
3987      * view is attached and has a handler.
3988      */
3989     private HandlerActionQueue mRunQueue;
3990 
3991     /**
3992      * The pointer icon when the mouse hovers on this view. The default is null.
3993      */
3994     private PointerIcon mPointerIcon;
3995 
3996     /**
3997      * @hide
3998      */
3999     String mStartActivityRequestWho;
4000 
4001     @Nullable
4002     private RoundScrollbarRenderer mRoundScrollbarRenderer;
4003 
4004     /**
4005      * Simple constructor to use when creating a view from code.
4006      *
4007      * @param context The Context the view is running in, through which it can
4008      *        access the current theme, resources, etc.
4009      */
View(Context context)4010     public View(Context context) {
4011         mContext = context;
4012         mResources = context != null ? context.getResources() : null;
4013         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4014         // Set some flags defaults
4015         mPrivateFlags2 =
4016                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4017                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4018                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4019                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4020                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4021                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4022         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4023         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4024         mUserPaddingStart = UNDEFINED_PADDING;
4025         mUserPaddingEnd = UNDEFINED_PADDING;
4026         mRenderNode = RenderNode.create(getClass().getName(), this);
4027 
4028         if (!sCompatibilityDone && context != null) {
4029             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4030 
4031             // Older apps may need this compatibility hack for measurement.
4032             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4033 
4034             // Older apps expect onMeasure() to always be called on a layout pass, regardless
4035             // of whether a layout was requested on that View.
4036             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4037 
4038             Canvas.sCompatibilityRestore = targetSdkVersion < M;
4039 
4040             // In M and newer, our widgets can pass a "hint" value in the size
4041             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4042             // know what the expected parent size is going to be, so e.g. list items can size
4043             // themselves at 1/3 the size of their container. It breaks older apps though,
4044             // specifically apps that use some popular open source libraries.
4045             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4046 
4047             // Old versions of the platform would give different results from
4048             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4049             // modes, so we always need to run an additional EXACTLY pass.
4050             sAlwaysRemeasureExactly = targetSdkVersion <= M;
4051 
4052             // Prior to N, layout params could change without requiring a
4053             // subsequent call to setLayoutParams() and they would usually
4054             // work. Partial layout breaks this assumption.
4055             sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4056 
4057             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4058             // On N+, we throw, but that breaks compatibility with apps that use these methods.
4059             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4060 
4061             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4062             // in apps so we target check it to avoid breaking existing apps.
4063             sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4064 
4065             sCascadedDragDrop = targetSdkVersion < N;
4066 
4067             sCompatibilityDone = true;
4068         }
4069     }
4070 
4071     /**
4072      * Constructor that is called when inflating a view from XML. This is called
4073      * when a view is being constructed from an XML file, supplying attributes
4074      * that were specified in the XML file. This version uses a default style of
4075      * 0, so the only attribute values applied are those in the Context's Theme
4076      * and the given AttributeSet.
4077      *
4078      * <p>
4079      * The method onFinishInflate() will be called after all children have been
4080      * added.
4081      *
4082      * @param context The Context the view is running in, through which it can
4083      *        access the current theme, resources, etc.
4084      * @param attrs The attributes of the XML tag that is inflating the view.
4085      * @see #View(Context, AttributeSet, int)
4086      */
4087     public View(Context context, @Nullable AttributeSet attrs) {
4088         this(context, attrs, 0);
4089     }
4090 
4091     /**
4092      * Perform inflation from XML and apply a class-specific base style from a
4093      * theme attribute. This constructor of View allows subclasses to use their
4094      * own base style when they are inflating. For example, a Button class's
4095      * constructor would call this version of the super class constructor and
4096      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4097      * allows the theme's button style to modify all of the base view attributes
4098      * (in particular its background) as well as the Button class's attributes.
4099      *
4100      * @param context The Context the view is running in, through which it can
4101      *        access the current theme, resources, etc.
4102      * @param attrs The attributes of the XML tag that is inflating the view.
4103      * @param defStyleAttr An attribute in the current theme that contains a
4104      *        reference to a style resource that supplies default values for
4105      *        the view. Can be 0 to not look for defaults.
4106      * @see #View(Context, AttributeSet)
4107      */
4108     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4109         this(context, attrs, defStyleAttr, 0);
4110     }
4111 
4112     /**
4113      * Perform inflation from XML and apply a class-specific base style from a
4114      * theme attribute or style resource. This constructor of View allows
4115      * subclasses to use their own base style when they are inflating.
4116      * <p>
4117      * When determining the final value of a particular attribute, there are
4118      * four inputs that come into play:
4119      * <ol>
4120      * <li>Any attribute values in the given AttributeSet.
4121      * <li>The style resource specified in the AttributeSet (named "style").
4122      * <li>The default style specified by <var>defStyleAttr</var>.
4123      * <li>The default style specified by <var>defStyleRes</var>.
4124      * <li>The base values in this theme.
4125      * </ol>
4126      * <p>
4127      * Each of these inputs is considered in-order, with the first listed taking
4128      * precedence over the following ones. In other words, if in the
4129      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4130      * , then the button's text will <em>always</em> be black, regardless of
4131      * what is specified in any of the styles.
4132      *
4133      * @param context The Context the view is running in, through which it can
4134      *        access the current theme, resources, etc.
4135      * @param attrs The attributes of the XML tag that is inflating the view.
4136      * @param defStyleAttr An attribute in the current theme that contains a
4137      *        reference to a style resource that supplies default values for
4138      *        the view. Can be 0 to not look for defaults.
4139      * @param defStyleRes A resource identifier of a style resource that
4140      *        supplies default values for the view, used only if
4141      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4142      *        to not look for defaults.
4143      * @see #View(Context, AttributeSet, int)
4144      */
4145     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4146         this(context);
4147 
4148         final TypedArray a = context.obtainStyledAttributes(
4149                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4150 
4151         if (mDebugViewAttributes) {
4152             saveAttributeData(attrs, a);
4153         }
4154 
4155         Drawable background = null;
4156 
4157         int leftPadding = -1;
4158         int topPadding = -1;
4159         int rightPadding = -1;
4160         int bottomPadding = -1;
4161         int startPadding = UNDEFINED_PADDING;
4162         int endPadding = UNDEFINED_PADDING;
4163 
4164         int padding = -1;
4165 
4166         int viewFlagValues = 0;
4167         int viewFlagMasks = 0;
4168 
4169         boolean setScrollContainer = false;
4170 
4171         int x = 0;
4172         int y = 0;
4173 
4174         float tx = 0;
4175         float ty = 0;
4176         float tz = 0;
4177         float elevation = 0;
4178         float rotation = 0;
4179         float rotationX = 0;
4180         float rotationY = 0;
4181         float sx = 1f;
4182         float sy = 1f;
4183         boolean transformSet = false;
4184 
4185         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4186         int overScrollMode = mOverScrollMode;
4187         boolean initializeScrollbars = false;
4188         boolean initializeScrollIndicators = false;
4189 
4190         boolean startPaddingDefined = false;
4191         boolean endPaddingDefined = false;
4192         boolean leftPaddingDefined = false;
4193         boolean rightPaddingDefined = false;
4194 
4195         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4196 
4197         final int N = a.getIndexCount();
4198         for (int i = 0; i < N; i++) {
4199             int attr = a.getIndex(i);
4200             switch (attr) {
4201                 case com.android.internal.R.styleable.View_background:
4202                     background = a.getDrawable(attr);
4203                     break;
4204                 case com.android.internal.R.styleable.View_padding:
4205                     padding = a.getDimensionPixelSize(attr, -1);
4206                     mUserPaddingLeftInitial = padding;
4207                     mUserPaddingRightInitial = padding;
4208                     leftPaddingDefined = true;
4209                     rightPaddingDefined = true;
4210                     break;
4211                  case com.android.internal.R.styleable.View_paddingLeft:
4212                     leftPadding = a.getDimensionPixelSize(attr, -1);
4213                     mUserPaddingLeftInitial = leftPadding;
4214                     leftPaddingDefined = true;
4215                     break;
4216                 case com.android.internal.R.styleable.View_paddingTop:
4217                     topPadding = a.getDimensionPixelSize(attr, -1);
4218                     break;
4219                 case com.android.internal.R.styleable.View_paddingRight:
4220                     rightPadding = a.getDimensionPixelSize(attr, -1);
4221                     mUserPaddingRightInitial = rightPadding;
4222                     rightPaddingDefined = true;
4223                     break;
4224                 case com.android.internal.R.styleable.View_paddingBottom:
4225                     bottomPadding = a.getDimensionPixelSize(attr, -1);
4226                     break;
4227                 case com.android.internal.R.styleable.View_paddingStart:
4228                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4229                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4230                     break;
4231                 case com.android.internal.R.styleable.View_paddingEnd:
4232                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4233                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4234                     break;
4235                 case com.android.internal.R.styleable.View_scrollX:
4236                     x = a.getDimensionPixelOffset(attr, 0);
4237                     break;
4238                 case com.android.internal.R.styleable.View_scrollY:
4239                     y = a.getDimensionPixelOffset(attr, 0);
4240                     break;
4241                 case com.android.internal.R.styleable.View_alpha:
4242                     setAlpha(a.getFloat(attr, 1f));
4243                     break;
4244                 case com.android.internal.R.styleable.View_transformPivotX:
4245                     setPivotX(a.getDimension(attr, 0));
4246                     break;
4247                 case com.android.internal.R.styleable.View_transformPivotY:
4248                     setPivotY(a.getDimension(attr, 0));
4249                     break;
4250                 case com.android.internal.R.styleable.View_translationX:
4251                     tx = a.getDimension(attr, 0);
4252                     transformSet = true;
4253                     break;
4254                 case com.android.internal.R.styleable.View_translationY:
4255                     ty = a.getDimension(attr, 0);
4256                     transformSet = true;
4257                     break;
4258                 case com.android.internal.R.styleable.View_translationZ:
4259                     tz = a.getDimension(attr, 0);
4260                     transformSet = true;
4261                     break;
4262                 case com.android.internal.R.styleable.View_elevation:
4263                     elevation = a.getDimension(attr, 0);
4264                     transformSet = true;
4265                     break;
4266                 case com.android.internal.R.styleable.View_rotation:
4267                     rotation = a.getFloat(attr, 0);
4268                     transformSet = true;
4269                     break;
4270                 case com.android.internal.R.styleable.View_rotationX:
4271                     rotationX = a.getFloat(attr, 0);
4272                     transformSet = true;
4273                     break;
4274                 case com.android.internal.R.styleable.View_rotationY:
4275                     rotationY = a.getFloat(attr, 0);
4276                     transformSet = true;
4277                     break;
4278                 case com.android.internal.R.styleable.View_scaleX:
4279                     sx = a.getFloat(attr, 1f);
4280                     transformSet = true;
4281                     break;
4282                 case com.android.internal.R.styleable.View_scaleY:
4283                     sy = a.getFloat(attr, 1f);
4284                     transformSet = true;
4285                     break;
4286                 case com.android.internal.R.styleable.View_id:
4287                     mID = a.getResourceId(attr, NO_ID);
4288                     break;
4289                 case com.android.internal.R.styleable.View_tag:
4290                     mTag = a.getText(attr);
4291                     break;
4292                 case com.android.internal.R.styleable.View_fitsSystemWindows:
4293                     if (a.getBoolean(attr, false)) {
4294                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
4295                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4296                     }
4297                     break;
4298                 case com.android.internal.R.styleable.View_focusable:
4299                     if (a.getBoolean(attr, false)) {
4300                         viewFlagValues |= FOCUSABLE;
4301                         viewFlagMasks |= FOCUSABLE_MASK;
4302                     }
4303                     break;
4304                 case com.android.internal.R.styleable.View_focusableInTouchMode:
4305                     if (a.getBoolean(attr, false)) {
4306                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4307                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4308                     }
4309                     break;
4310                 case com.android.internal.R.styleable.View_clickable:
4311                     if (a.getBoolean(attr, false)) {
4312                         viewFlagValues |= CLICKABLE;
4313                         viewFlagMasks |= CLICKABLE;
4314                     }
4315                     break;
4316                 case com.android.internal.R.styleable.View_longClickable:
4317                     if (a.getBoolean(attr, false)) {
4318                         viewFlagValues |= LONG_CLICKABLE;
4319                         viewFlagMasks |= LONG_CLICKABLE;
4320                     }
4321                     break;
4322                 case com.android.internal.R.styleable.View_contextClickable:
4323                     if (a.getBoolean(attr, false)) {
4324                         viewFlagValues |= CONTEXT_CLICKABLE;
4325                         viewFlagMasks |= CONTEXT_CLICKABLE;
4326                     }
4327                     break;
4328                 case com.android.internal.R.styleable.View_saveEnabled:
4329                     if (!a.getBoolean(attr, true)) {
4330                         viewFlagValues |= SAVE_DISABLED;
4331                         viewFlagMasks |= SAVE_DISABLED_MASK;
4332                     }
4333                     break;
4334                 case com.android.internal.R.styleable.View_duplicateParentState:
4335                     if (a.getBoolean(attr, false)) {
4336                         viewFlagValues |= DUPLICATE_PARENT_STATE;
4337                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
4338                     }
4339                     break;
4340                 case com.android.internal.R.styleable.View_visibility:
4341                     final int visibility = a.getInt(attr, 0);
4342                     if (visibility != 0) {
4343                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
4344                         viewFlagMasks |= VISIBILITY_MASK;
4345                     }
4346                     break;
4347                 case com.android.internal.R.styleable.View_layoutDirection:
4348                     // Clear any layout direction flags (included resolved bits) already set
4349                     mPrivateFlags2 &=
4350                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4351                     // Set the layout direction flags depending on the value of the attribute
4352                     final int layoutDirection = a.getInt(attr, -1);
4353                     final int value = (layoutDirection != -1) ?
4354                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4355                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4356                     break;
4357                 case com.android.internal.R.styleable.View_drawingCacheQuality:
4358                     final int cacheQuality = a.getInt(attr, 0);
4359                     if (cacheQuality != 0) {
4360                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4361                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4362                     }
4363                     break;
4364                 case com.android.internal.R.styleable.View_contentDescription:
4365                     setContentDescription(a.getString(attr));
4366                     break;
4367                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4368                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4369                     break;
4370                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4371                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4372                     break;
4373                 case com.android.internal.R.styleable.View_labelFor:
4374                     setLabelFor(a.getResourceId(attr, NO_ID));
4375                     break;
4376                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4377                     if (!a.getBoolean(attr, true)) {
4378                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4379                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4380                     }
4381                     break;
4382                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4383                     if (!a.getBoolean(attr, true)) {
4384                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4385                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4386                     }
4387                     break;
4388                 case R.styleable.View_scrollbars:
4389                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4390                     if (scrollbars != SCROLLBARS_NONE) {
4391                         viewFlagValues |= scrollbars;
4392                         viewFlagMasks |= SCROLLBARS_MASK;
4393                         initializeScrollbars = true;
4394                     }
4395                     break;
4396                 //noinspection deprecation
4397                 case R.styleable.View_fadingEdge:
4398                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4399                         // Ignore the attribute starting with ICS
4400                         break;
4401                     }
4402                     // With builds < ICS, fall through and apply fading edges
4403                 case R.styleable.View_requiresFadingEdge:
4404                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4405                     if (fadingEdge != FADING_EDGE_NONE) {
4406                         viewFlagValues |= fadingEdge;
4407                         viewFlagMasks |= FADING_EDGE_MASK;
4408                         initializeFadingEdgeInternal(a);
4409                     }
4410                     break;
4411                 case R.styleable.View_scrollbarStyle:
4412                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4413                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4414                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4415                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4416                     }
4417                     break;
4418                 case R.styleable.View_isScrollContainer:
4419                     setScrollContainer = true;
4420                     if (a.getBoolean(attr, false)) {
4421                         setScrollContainer(true);
4422                     }
4423                     break;
4424                 case com.android.internal.R.styleable.View_keepScreenOn:
4425                     if (a.getBoolean(attr, false)) {
4426                         viewFlagValues |= KEEP_SCREEN_ON;
4427                         viewFlagMasks |= KEEP_SCREEN_ON;
4428                     }
4429                     break;
4430                 case R.styleable.View_filterTouchesWhenObscured:
4431                     if (a.getBoolean(attr, false)) {
4432                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4433                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4434                     }
4435                     break;
4436                 case R.styleable.View_nextFocusLeft:
4437                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4438                     break;
4439                 case R.styleable.View_nextFocusRight:
4440                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4441                     break;
4442                 case R.styleable.View_nextFocusUp:
4443                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4444                     break;
4445                 case R.styleable.View_nextFocusDown:
4446                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4447                     break;
4448                 case R.styleable.View_nextFocusForward:
4449                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4450                     break;
4451                 case R.styleable.View_minWidth:
4452                     mMinWidth = a.getDimensionPixelSize(attr, 0);
4453                     break;
4454                 case R.styleable.View_minHeight:
4455                     mMinHeight = a.getDimensionPixelSize(attr, 0);
4456                     break;
4457                 case R.styleable.View_onClick:
4458                     if (context.isRestricted()) {
4459                         throw new IllegalStateException("The android:onClick attribute cannot "
4460                                 + "be used within a restricted context");
4461                     }
4462 
4463                     final String handlerName = a.getString(attr);
4464                     if (handlerName != null) {
4465                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4466                     }
4467                     break;
4468                 case R.styleable.View_overScrollMode:
4469                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4470                     break;
4471                 case R.styleable.View_verticalScrollbarPosition:
4472                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4473                     break;
4474                 case R.styleable.View_layerType:
4475                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4476                     break;
4477                 case R.styleable.View_textDirection:
4478                     // Clear any text direction flag already set
4479                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4480                     // Set the text direction flags depending on the value of the attribute
4481                     final int textDirection = a.getInt(attr, -1);
4482                     if (textDirection != -1) {
4483                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4484                     }
4485                     break;
4486                 case R.styleable.View_textAlignment:
4487                     // Clear any text alignment flag already set
4488                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4489                     // Set the text alignment flag depending on the value of the attribute
4490                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4491                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4492                     break;
4493                 case R.styleable.View_importantForAccessibility:
4494                     setImportantForAccessibility(a.getInt(attr,
4495                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4496                     break;
4497                 case R.styleable.View_accessibilityLiveRegion:
4498                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4499                     break;
4500                 case R.styleable.View_transitionName:
4501                     setTransitionName(a.getString(attr));
4502                     break;
4503                 case R.styleable.View_nestedScrollingEnabled:
4504                     setNestedScrollingEnabled(a.getBoolean(attr, false));
4505                     break;
4506                 case R.styleable.View_stateListAnimator:
4507                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4508                             a.getResourceId(attr, 0)));
4509                     break;
4510                 case R.styleable.View_backgroundTint:
4511                     // This will get applied later during setBackground().
4512                     if (mBackgroundTint == null) {
4513                         mBackgroundTint = new TintInfo();
4514                     }
4515                     mBackgroundTint.mTintList = a.getColorStateList(
4516                             R.styleable.View_backgroundTint);
4517                     mBackgroundTint.mHasTintList = true;
4518                     break;
4519                 case R.styleable.View_backgroundTintMode:
4520                     // This will get applied later during setBackground().
4521                     if (mBackgroundTint == null) {
4522                         mBackgroundTint = new TintInfo();
4523                     }
4524                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4525                             R.styleable.View_backgroundTintMode, -1), null);
4526                     mBackgroundTint.mHasTintMode = true;
4527                     break;
4528                 case R.styleable.View_outlineProvider:
4529                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4530                             PROVIDER_BACKGROUND));
4531                     break;
4532                 case R.styleable.View_foreground:
4533                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4534                         setForeground(a.getDrawable(attr));
4535                     }
4536                     break;
4537                 case R.styleable.View_foregroundGravity:
4538                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4539                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4540                     }
4541                     break;
4542                 case R.styleable.View_foregroundTintMode:
4543                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4544                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4545                     }
4546                     break;
4547                 case R.styleable.View_foregroundTint:
4548                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4549                         setForegroundTintList(a.getColorStateList(attr));
4550                     }
4551                     break;
4552                 case R.styleable.View_foregroundInsidePadding:
4553                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4554                         if (mForegroundInfo == null) {
4555                             mForegroundInfo = new ForegroundInfo();
4556                         }
4557                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4558                                 mForegroundInfo.mInsidePadding);
4559                     }
4560                     break;
4561                 case R.styleable.View_scrollIndicators:
4562                     final int scrollIndicators =
4563                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4564                                     & SCROLL_INDICATORS_PFLAG3_MASK;
4565                     if (scrollIndicators != 0) {
4566                         mPrivateFlags3 |= scrollIndicators;
4567                         initializeScrollIndicators = true;
4568                     }
4569                     break;
4570                 case R.styleable.View_pointerIcon:
4571                     final int resourceId = a.getResourceId(attr, 0);
4572                     if (resourceId != 0) {
4573                         setPointerIcon(PointerIcon.load(
4574                                 context.getResources(), resourceId));
4575                     } else {
4576                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4577                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4578                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4579                         }
4580                     }
4581                     break;
4582                 case R.styleable.View_forceHasOverlappingRendering:
4583                     if (a.peekValue(attr) != null) {
4584                         forceHasOverlappingRendering(a.getBoolean(attr, true));
4585                     }
4586                     break;
4587 
4588             }
4589         }
4590 
4591         setOverScrollMode(overScrollMode);
4592 
4593         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4594         // the resolved layout direction). Those cached values will be used later during padding
4595         // resolution.
4596         mUserPaddingStart = startPadding;
4597         mUserPaddingEnd = endPadding;
4598 
4599         if (background != null) {
4600             setBackground(background);
4601         }
4602 
4603         // setBackground above will record that padding is currently provided by the background.
4604         // If we have padding specified via xml, record that here instead and use it.
4605         mLeftPaddingDefined = leftPaddingDefined;
4606         mRightPaddingDefined = rightPaddingDefined;
4607 
4608         if (padding >= 0) {
4609             leftPadding = padding;
4610             topPadding = padding;
4611             rightPadding = padding;
4612             bottomPadding = padding;
4613             mUserPaddingLeftInitial = padding;
4614             mUserPaddingRightInitial = padding;
4615         }
4616 
4617         if (isRtlCompatibilityMode()) {
4618             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4619             // left / right padding are used if defined (meaning here nothing to do). If they are not
4620             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4621             // start / end and resolve them as left / right (layout direction is not taken into account).
4622             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4623             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4624             // defined.
4625             if (!mLeftPaddingDefined && startPaddingDefined) {
4626                 leftPadding = startPadding;
4627             }
4628             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4629             if (!mRightPaddingDefined && endPaddingDefined) {
4630                 rightPadding = endPadding;
4631             }
4632             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4633         } else {
4634             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4635             // values defined. Otherwise, left /right values are used.
4636             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4637             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4638             // defined.
4639             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4640 
4641             if (mLeftPaddingDefined && !hasRelativePadding) {
4642                 mUserPaddingLeftInitial = leftPadding;
4643             }
4644             if (mRightPaddingDefined && !hasRelativePadding) {
4645                 mUserPaddingRightInitial = rightPadding;
4646             }
4647         }
4648 
4649         internalSetPadding(
4650                 mUserPaddingLeftInitial,
4651                 topPadding >= 0 ? topPadding : mPaddingTop,
4652                 mUserPaddingRightInitial,
4653                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4654 
4655         if (viewFlagMasks != 0) {
4656             setFlags(viewFlagValues, viewFlagMasks);
4657         }
4658 
4659         if (initializeScrollbars) {
4660             initializeScrollbarsInternal(a);
4661         }
4662 
4663         if (initializeScrollIndicators) {
4664             initializeScrollIndicatorsInternal();
4665         }
4666 
4667         a.recycle();
4668 
4669         // Needs to be called after mViewFlags is set
4670         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4671             recomputePadding();
4672         }
4673 
4674         if (x != 0 || y != 0) {
4675             scrollTo(x, y);
4676         }
4677 
4678         if (transformSet) {
4679             setTranslationX(tx);
4680             setTranslationY(ty);
4681             setTranslationZ(tz);
4682             setElevation(elevation);
4683             setRotation(rotation);
4684             setRotationX(rotationX);
4685             setRotationY(rotationY);
4686             setScaleX(sx);
4687             setScaleY(sy);
4688         }
4689 
4690         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4691             setScrollContainer(true);
4692         }
4693 
4694         computeOpaqueFlags();
4695     }
4696 
4697     /**
4698      * An implementation of OnClickListener that attempts to lazily load a
4699      * named click handling method from a parent or ancestor context.
4700      */
4701     private static class DeclaredOnClickListener implements OnClickListener {
4702         private final View mHostView;
4703         private final String mMethodName;
4704 
4705         private Method mResolvedMethod;
4706         private Context mResolvedContext;
4707 
DeclaredOnClickListener(@onNull View hostView, @NonNull String methodName)4708         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4709             mHostView = hostView;
4710             mMethodName = methodName;
4711         }
4712 
4713         @Override
onClick(@onNull View v)4714         public void onClick(@NonNull View v) {
4715             if (mResolvedMethod == null) {
4716                 resolveMethod(mHostView.getContext(), mMethodName);
4717             }
4718 
4719             try {
4720                 mResolvedMethod.invoke(mResolvedContext, v);
4721             } catch (IllegalAccessException e) {
4722                 throw new IllegalStateException(
4723                         "Could not execute non-public method for android:onClick", e);
4724             } catch (InvocationTargetException e) {
4725                 throw new IllegalStateException(
4726                         "Could not execute method for android:onClick", e);
4727             }
4728         }
4729 
4730         @NonNull
resolveMethod(@ullable Context context, @NonNull String name)4731         private void resolveMethod(@Nullable Context context, @NonNull String name) {
4732             while (context != null) {
4733                 try {
4734                     if (!context.isRestricted()) {
4735                         final Method method = context.getClass().getMethod(mMethodName, View.class);
4736                         if (method != null) {
4737                             mResolvedMethod = method;
4738                             mResolvedContext = context;
4739                             return;
4740                         }
4741                     }
4742                 } catch (NoSuchMethodException e) {
4743                     // Failed to find method, keep searching up the hierarchy.
4744                 }
4745 
4746                 if (context instanceof ContextWrapper) {
4747                     context = ((ContextWrapper) context).getBaseContext();
4748                 } else {
4749                     // Can't search up the hierarchy, null out and fail.
4750                     context = null;
4751                 }
4752             }
4753 
4754             final int id = mHostView.getId();
4755             final String idText = id == NO_ID ? "" : " with id '"
4756                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4757             throw new IllegalStateException("Could not find method " + mMethodName
4758                     + "(View) in a parent or ancestor Context for android:onClick "
4759                     + "attribute defined on view " + mHostView.getClass() + idText);
4760         }
4761     }
4762 
4763     /**
4764      * Non-public constructor for use in testing
4765      */
View()4766     View() {
4767         mResources = null;
4768         mRenderNode = RenderNode.create(getClass().getName(), this);
4769     }
4770 
getAttributeMap()4771     private static SparseArray<String> getAttributeMap() {
4772         if (mAttributeMap == null) {
4773             mAttributeMap = new SparseArray<>();
4774         }
4775         return mAttributeMap;
4776     }
4777 
saveAttributeData(@ullable AttributeSet attrs, @NonNull TypedArray t)4778     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4779         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4780         final int indexCount = t.getIndexCount();
4781         final String[] attributes = new String[(attrsCount + indexCount) * 2];
4782 
4783         int i = 0;
4784 
4785         // Store raw XML attributes.
4786         for (int j = 0; j < attrsCount; ++j) {
4787             attributes[i] = attrs.getAttributeName(j);
4788             attributes[i + 1] = attrs.getAttributeValue(j);
4789             i += 2;
4790         }
4791 
4792         // Store resolved styleable attributes.
4793         final Resources res = t.getResources();
4794         final SparseArray<String> attributeMap = getAttributeMap();
4795         for (int j = 0; j < indexCount; ++j) {
4796             final int index = t.getIndex(j);
4797             if (!t.hasValueOrEmpty(index)) {
4798                 // Value is undefined. Skip it.
4799                 continue;
4800             }
4801 
4802             final int resourceId = t.getResourceId(index, 0);
4803             if (resourceId == 0) {
4804                 // Value is not a reference. Skip it.
4805                 continue;
4806             }
4807 
4808             String resourceName = attributeMap.get(resourceId);
4809             if (resourceName == null) {
4810                 try {
4811                     resourceName = res.getResourceName(resourceId);
4812                 } catch (Resources.NotFoundException e) {
4813                     resourceName = "0x" + Integer.toHexString(resourceId);
4814                 }
4815                 attributeMap.put(resourceId, resourceName);
4816             }
4817 
4818             attributes[i] = resourceName;
4819             attributes[i + 1] = t.getString(index);
4820             i += 2;
4821         }
4822 
4823         // Trim to fit contents.
4824         final String[] trimmed = new String[i];
4825         System.arraycopy(attributes, 0, trimmed, 0, i);
4826         mAttributes = trimmed;
4827     }
4828 
toString()4829     public String toString() {
4830         StringBuilder out = new StringBuilder(128);
4831         out.append(getClass().getName());
4832         out.append('{');
4833         out.append(Integer.toHexString(System.identityHashCode(this)));
4834         out.append(' ');
4835         switch (mViewFlags&VISIBILITY_MASK) {
4836             case VISIBLE: out.append('V'); break;
4837             case INVISIBLE: out.append('I'); break;
4838             case GONE: out.append('G'); break;
4839             default: out.append('.'); break;
4840         }
4841         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4842         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4843         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4844         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4845         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4846         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4847         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4848         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4849         out.append(' ');
4850         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4851         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4852         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4853         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4854             out.append('p');
4855         } else {
4856             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4857         }
4858         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4859         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4860         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4861         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4862         out.append(' ');
4863         out.append(mLeft);
4864         out.append(',');
4865         out.append(mTop);
4866         out.append('-');
4867         out.append(mRight);
4868         out.append(',');
4869         out.append(mBottom);
4870         final int id = getId();
4871         if (id != NO_ID) {
4872             out.append(" #");
4873             out.append(Integer.toHexString(id));
4874             final Resources r = mResources;
4875             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4876                 try {
4877                     String pkgname;
4878                     switch (id&0xff000000) {
4879                         case 0x7f000000:
4880                             pkgname="app";
4881                             break;
4882                         case 0x01000000:
4883                             pkgname="android";
4884                             break;
4885                         default:
4886                             pkgname = r.getResourcePackageName(id);
4887                             break;
4888                     }
4889                     String typename = r.getResourceTypeName(id);
4890                     String entryname = r.getResourceEntryName(id);
4891                     out.append(" ");
4892                     out.append(pkgname);
4893                     out.append(":");
4894                     out.append(typename);
4895                     out.append("/");
4896                     out.append(entryname);
4897                 } catch (Resources.NotFoundException e) {
4898                 }
4899             }
4900         }
4901         out.append("}");
4902         return out.toString();
4903     }
4904 
4905     /**
4906      * <p>
4907      * Initializes the fading edges from a given set of styled attributes. This
4908      * method should be called by subclasses that need fading edges and when an
4909      * instance of these subclasses is created programmatically rather than
4910      * being inflated from XML. This method is automatically called when the XML
4911      * is inflated.
4912      * </p>
4913      *
4914      * @param a the styled attributes set to initialize the fading edges from
4915      *
4916      * @removed
4917      */
initializeFadingEdge(TypedArray a)4918     protected void initializeFadingEdge(TypedArray a) {
4919         // This method probably shouldn't have been included in the SDK to begin with.
4920         // It relies on 'a' having been initialized using an attribute filter array that is
4921         // not publicly available to the SDK. The old method has been renamed
4922         // to initializeFadingEdgeInternal and hidden for framework use only;
4923         // this one initializes using defaults to make it safe to call for apps.
4924 
4925         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4926 
4927         initializeFadingEdgeInternal(arr);
4928 
4929         arr.recycle();
4930     }
4931 
4932     /**
4933      * <p>
4934      * Initializes the fading edges from a given set of styled attributes. This
4935      * method should be called by subclasses that need fading edges and when an
4936      * instance of these subclasses is created programmatically rather than
4937      * being inflated from XML. This method is automatically called when the XML
4938      * is inflated.
4939      * </p>
4940      *
4941      * @param a the styled attributes set to initialize the fading edges from
4942      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4943      */
initializeFadingEdgeInternal(TypedArray a)4944     protected void initializeFadingEdgeInternal(TypedArray a) {
4945         initScrollCache();
4946 
4947         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4948                 R.styleable.View_fadingEdgeLength,
4949                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4950     }
4951 
4952     /**
4953      * Returns the size of the vertical faded edges used to indicate that more
4954      * content in this view is visible.
4955      *
4956      * @return The size in pixels of the vertical faded edge or 0 if vertical
4957      *         faded edges are not enabled for this view.
4958      * @attr ref android.R.styleable#View_fadingEdgeLength
4959      */
getVerticalFadingEdgeLength()4960     public int getVerticalFadingEdgeLength() {
4961         if (isVerticalFadingEdgeEnabled()) {
4962             ScrollabilityCache cache = mScrollCache;
4963             if (cache != null) {
4964                 return cache.fadingEdgeLength;
4965             }
4966         }
4967         return 0;
4968     }
4969 
4970     /**
4971      * Set the size of the faded edge used to indicate that more content in this
4972      * view is available.  Will not change whether the fading edge is enabled; use
4973      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4974      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4975      * for the vertical or horizontal fading edges.
4976      *
4977      * @param length The size in pixels of the faded edge used to indicate that more
4978      *        content in this view is visible.
4979      */
setFadingEdgeLength(int length)4980     public void setFadingEdgeLength(int length) {
4981         initScrollCache();
4982         mScrollCache.fadingEdgeLength = length;
4983     }
4984 
4985     /**
4986      * Returns the size of the horizontal faded edges used to indicate that more
4987      * content in this view is visible.
4988      *
4989      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4990      *         faded edges are not enabled for this view.
4991      * @attr ref android.R.styleable#View_fadingEdgeLength
4992      */
getHorizontalFadingEdgeLength()4993     public int getHorizontalFadingEdgeLength() {
4994         if (isHorizontalFadingEdgeEnabled()) {
4995             ScrollabilityCache cache = mScrollCache;
4996             if (cache != null) {
4997                 return cache.fadingEdgeLength;
4998             }
4999         }
5000         return 0;
5001     }
5002 
5003     /**
5004      * Returns the width of the vertical scrollbar.
5005      *
5006      * @return The width in pixels of the vertical scrollbar or 0 if there
5007      *         is no vertical scrollbar.
5008      */
getVerticalScrollbarWidth()5009     public int getVerticalScrollbarWidth() {
5010         ScrollabilityCache cache = mScrollCache;
5011         if (cache != null) {
5012             ScrollBarDrawable scrollBar = cache.scrollBar;
5013             if (scrollBar != null) {
5014                 int size = scrollBar.getSize(true);
5015                 if (size <= 0) {
5016                     size = cache.scrollBarSize;
5017                 }
5018                 return size;
5019             }
5020             return 0;
5021         }
5022         return 0;
5023     }
5024 
5025     /**
5026      * Returns the height of the horizontal scrollbar.
5027      *
5028      * @return The height in pixels of the horizontal scrollbar or 0 if
5029      *         there is no horizontal scrollbar.
5030      */
getHorizontalScrollbarHeight()5031     protected int getHorizontalScrollbarHeight() {
5032         ScrollabilityCache cache = mScrollCache;
5033         if (cache != null) {
5034             ScrollBarDrawable scrollBar = cache.scrollBar;
5035             if (scrollBar != null) {
5036                 int size = scrollBar.getSize(false);
5037                 if (size <= 0) {
5038                     size = cache.scrollBarSize;
5039                 }
5040                 return size;
5041             }
5042             return 0;
5043         }
5044         return 0;
5045     }
5046 
5047     /**
5048      * <p>
5049      * Initializes the scrollbars from a given set of styled attributes. This
5050      * method should be called by subclasses that need scrollbars and when an
5051      * instance of these subclasses is created programmatically rather than
5052      * being inflated from XML. This method is automatically called when the XML
5053      * is inflated.
5054      * </p>
5055      *
5056      * @param a the styled attributes set to initialize the scrollbars from
5057      *
5058      * @removed
5059      */
initializeScrollbars(TypedArray a)5060     protected void initializeScrollbars(TypedArray a) {
5061         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5062         // using the View filter array which is not available to the SDK. As such, internal
5063         // framework usage now uses initializeScrollbarsInternal and we grab a default
5064         // TypedArray with the right filter instead here.
5065         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5066 
5067         initializeScrollbarsInternal(arr);
5068 
5069         // We ignored the method parameter. Recycle the one we actually did use.
5070         arr.recycle();
5071     }
5072 
5073     /**
5074      * <p>
5075      * Initializes the scrollbars from a given set of styled attributes. This
5076      * method should be called by subclasses that need scrollbars and when an
5077      * instance of these subclasses is created programmatically rather than
5078      * being inflated from XML. This method is automatically called when the XML
5079      * is inflated.
5080      * </p>
5081      *
5082      * @param a the styled attributes set to initialize the scrollbars from
5083      * @hide
5084      */
initializeScrollbarsInternal(TypedArray a)5085     protected void initializeScrollbarsInternal(TypedArray a) {
5086         initScrollCache();
5087 
5088         final ScrollabilityCache scrollabilityCache = mScrollCache;
5089 
5090         if (scrollabilityCache.scrollBar == null) {
5091             scrollabilityCache.scrollBar = new ScrollBarDrawable();
5092             scrollabilityCache.scrollBar.setState(getDrawableState());
5093             scrollabilityCache.scrollBar.setCallback(this);
5094         }
5095 
5096         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5097 
5098         if (!fadeScrollbars) {
5099             scrollabilityCache.state = ScrollabilityCache.ON;
5100         }
5101         scrollabilityCache.fadeScrollBars = fadeScrollbars;
5102 
5103 
5104         scrollabilityCache.scrollBarFadeDuration = a.getInt(
5105                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5106                         .getScrollBarFadeDuration());
5107         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5108                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
5109                 ViewConfiguration.getScrollDefaultDelay());
5110 
5111 
5112         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5113                 com.android.internal.R.styleable.View_scrollbarSize,
5114                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
5115 
5116         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5117         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5118 
5119         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5120         if (thumb != null) {
5121             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5122         }
5123 
5124         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5125                 false);
5126         if (alwaysDraw) {
5127             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5128         }
5129 
5130         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5131         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5132 
5133         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5134         if (thumb != null) {
5135             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5136         }
5137 
5138         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5139                 false);
5140         if (alwaysDraw) {
5141             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5142         }
5143 
5144         // Apply layout direction to the new Drawables if needed
5145         final int layoutDirection = getLayoutDirection();
5146         if (track != null) {
5147             track.setLayoutDirection(layoutDirection);
5148         }
5149         if (thumb != null) {
5150             thumb.setLayoutDirection(layoutDirection);
5151         }
5152 
5153         // Re-apply user/background padding so that scrollbar(s) get added
5154         resolvePadding();
5155     }
5156 
initializeScrollIndicatorsInternal()5157     private void initializeScrollIndicatorsInternal() {
5158         // Some day maybe we'll break this into top/left/start/etc. and let the
5159         // client control it. Until then, you can have any scroll indicator you
5160         // want as long as it's a 1dp foreground-colored rectangle.
5161         if (mScrollIndicatorDrawable == null) {
5162             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5163         }
5164     }
5165 
5166     /**
5167      * <p>
5168      * Initalizes the scrollability cache if necessary.
5169      * </p>
5170      */
initScrollCache()5171     private void initScrollCache() {
5172         if (mScrollCache == null) {
5173             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5174         }
5175     }
5176 
getScrollCache()5177     private ScrollabilityCache getScrollCache() {
5178         initScrollCache();
5179         return mScrollCache;
5180     }
5181 
5182     /**
5183      * Set the position of the vertical scroll bar. Should be one of
5184      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5185      * {@link #SCROLLBAR_POSITION_RIGHT}.
5186      *
5187      * @param position Where the vertical scroll bar should be positioned.
5188      */
setVerticalScrollbarPosition(int position)5189     public void setVerticalScrollbarPosition(int position) {
5190         if (mVerticalScrollbarPosition != position) {
5191             mVerticalScrollbarPosition = position;
5192             computeOpaqueFlags();
5193             resolvePadding();
5194         }
5195     }
5196 
5197     /**
5198      * @return The position where the vertical scroll bar will show, if applicable.
5199      * @see #setVerticalScrollbarPosition(int)
5200      */
getVerticalScrollbarPosition()5201     public int getVerticalScrollbarPosition() {
5202         return mVerticalScrollbarPosition;
5203     }
5204 
isOnScrollbar(float x, float y)5205     boolean isOnScrollbar(float x, float y) {
5206         if (mScrollCache == null) {
5207             return false;
5208         }
5209         x += getScrollX();
5210         y += getScrollY();
5211         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5212             final Rect bounds = mScrollCache.mScrollBarBounds;
5213             getVerticalScrollBarBounds(bounds);
5214             if (bounds.contains((int)x, (int)y)) {
5215                 return true;
5216             }
5217         }
5218         if (isHorizontalScrollBarEnabled()) {
5219             final Rect bounds = mScrollCache.mScrollBarBounds;
5220             getHorizontalScrollBarBounds(bounds);
5221             if (bounds.contains((int)x, (int)y)) {
5222                 return true;
5223             }
5224         }
5225         return false;
5226     }
5227 
isOnScrollbarThumb(float x, float y)5228     boolean isOnScrollbarThumb(float x, float y) {
5229         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5230     }
5231 
isOnVerticalScrollbarThumb(float x, float y)5232     private boolean isOnVerticalScrollbarThumb(float x, float y) {
5233         if (mScrollCache == null) {
5234             return false;
5235         }
5236         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5237             x += getScrollX();
5238             y += getScrollY();
5239             final Rect bounds = mScrollCache.mScrollBarBounds;
5240             getVerticalScrollBarBounds(bounds);
5241             final int range = computeVerticalScrollRange();
5242             final int offset = computeVerticalScrollOffset();
5243             final int extent = computeVerticalScrollExtent();
5244             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5245                     extent, range);
5246             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5247                     extent, range, offset);
5248             final int thumbTop = bounds.top + thumbOffset;
5249             if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5250                     && y <= thumbTop + thumbLength) {
5251                 return true;
5252             }
5253         }
5254         return false;
5255     }
5256 
isOnHorizontalScrollbarThumb(float x, float y)5257     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5258         if (mScrollCache == null) {
5259             return false;
5260         }
5261         if (isHorizontalScrollBarEnabled()) {
5262             x += getScrollX();
5263             y += getScrollY();
5264             final Rect bounds = mScrollCache.mScrollBarBounds;
5265             getHorizontalScrollBarBounds(bounds);
5266             final int range = computeHorizontalScrollRange();
5267             final int offset = computeHorizontalScrollOffset();
5268             final int extent = computeHorizontalScrollExtent();
5269             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5270                     extent, range);
5271             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5272                     extent, range, offset);
5273             final int thumbLeft = bounds.left + thumbOffset;
5274             if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5275                     && y <= bounds.bottom) {
5276                 return true;
5277             }
5278         }
5279         return false;
5280     }
5281 
isDraggingScrollBar()5282     boolean isDraggingScrollBar() {
5283         return mScrollCache != null
5284                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5285     }
5286 
5287     /**
5288      * Sets the state of all scroll indicators.
5289      * <p>
5290      * See {@link #setScrollIndicators(int, int)} for usage information.
5291      *
5292      * @param indicators a bitmask of indicators that should be enabled, or
5293      *                   {@code 0} to disable all indicators
5294      * @see #setScrollIndicators(int, int)
5295      * @see #getScrollIndicators()
5296      * @attr ref android.R.styleable#View_scrollIndicators
5297      */
setScrollIndicators(@crollIndicators int indicators)5298     public void setScrollIndicators(@ScrollIndicators int indicators) {
5299         setScrollIndicators(indicators,
5300                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5301     }
5302 
5303     /**
5304      * Sets the state of the scroll indicators specified by the mask. To change
5305      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5306      * <p>
5307      * When a scroll indicator is enabled, it will be displayed if the view
5308      * can scroll in the direction of the indicator.
5309      * <p>
5310      * Multiple indicator types may be enabled or disabled by passing the
5311      * logical OR of the desired types. If multiple types are specified, they
5312      * will all be set to the same enabled state.
5313      * <p>
5314      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5315      *
5316      * @param indicators the indicator direction, or the logical OR of multiple
5317      *             indicator directions. One or more of:
5318      *             <ul>
5319      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5320      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5321      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5322      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5323      *               <li>{@link #SCROLL_INDICATOR_START}</li>
5324      *               <li>{@link #SCROLL_INDICATOR_END}</li>
5325      *             </ul>
5326      * @see #setScrollIndicators(int)
5327      * @see #getScrollIndicators()
5328      * @attr ref android.R.styleable#View_scrollIndicators
5329      */
setScrollIndicators(@crollIndicators int indicators, @ScrollIndicators int mask)5330     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5331         // Shift and sanitize mask.
5332         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5333         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5334 
5335         // Shift and mask indicators.
5336         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5337         indicators &= mask;
5338 
5339         // Merge with non-masked flags.
5340         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5341 
5342         if (mPrivateFlags3 != updatedFlags) {
5343             mPrivateFlags3 = updatedFlags;
5344 
5345             if (indicators != 0) {
5346                 initializeScrollIndicatorsInternal();
5347             }
5348             invalidate();
5349         }
5350     }
5351 
5352     /**
5353      * Returns a bitmask representing the enabled scroll indicators.
5354      * <p>
5355      * For example, if the top and left scroll indicators are enabled and all
5356      * other indicators are disabled, the return value will be
5357      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5358      * <p>
5359      * To check whether the bottom scroll indicator is enabled, use the value
5360      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5361      *
5362      * @return a bitmask representing the enabled scroll indicators
5363      */
5364     @ScrollIndicators
getScrollIndicators()5365     public int getScrollIndicators() {
5366         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5367                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5368     }
5369 
getListenerInfo()5370     ListenerInfo getListenerInfo() {
5371         if (mListenerInfo != null) {
5372             return mListenerInfo;
5373         }
5374         mListenerInfo = new ListenerInfo();
5375         return mListenerInfo;
5376     }
5377 
5378     /**
5379      * Register a callback to be invoked when the scroll X or Y positions of
5380      * this view change.
5381      * <p>
5382      * <b>Note:</b> Some views handle scrolling independently from View and may
5383      * have their own separate listeners for scroll-type events. For example,
5384      * {@link android.widget.ListView ListView} allows clients to register an
5385      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5386      * to listen for changes in list scroll position.
5387      *
5388      * @param l The listener to notify when the scroll X or Y position changes.
5389      * @see android.view.View#getScrollX()
5390      * @see android.view.View#getScrollY()
5391      */
setOnScrollChangeListener(OnScrollChangeListener l)5392     public void setOnScrollChangeListener(OnScrollChangeListener l) {
5393         getListenerInfo().mOnScrollChangeListener = l;
5394     }
5395 
5396     /**
5397      * Register a callback to be invoked when focus of this view changed.
5398      *
5399      * @param l The callback that will run.
5400      */
setOnFocusChangeListener(OnFocusChangeListener l)5401     public void setOnFocusChangeListener(OnFocusChangeListener l) {
5402         getListenerInfo().mOnFocusChangeListener = l;
5403     }
5404 
5405     /**
5406      * Add a listener that will be called when the bounds of the view change due to
5407      * layout processing.
5408      *
5409      * @param listener The listener that will be called when layout bounds change.
5410      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)5411     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5412         ListenerInfo li = getListenerInfo();
5413         if (li.mOnLayoutChangeListeners == null) {
5414             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5415         }
5416         if (!li.mOnLayoutChangeListeners.contains(listener)) {
5417             li.mOnLayoutChangeListeners.add(listener);
5418         }
5419     }
5420 
5421     /**
5422      * Remove a listener for layout changes.
5423      *
5424      * @param listener The listener for layout bounds change.
5425      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)5426     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5427         ListenerInfo li = mListenerInfo;
5428         if (li == null || li.mOnLayoutChangeListeners == null) {
5429             return;
5430         }
5431         li.mOnLayoutChangeListeners.remove(listener);
5432     }
5433 
5434     /**
5435      * Add a listener for attach state changes.
5436      *
5437      * This listener will be called whenever this view is attached or detached
5438      * from a window. Remove the listener using
5439      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5440      *
5441      * @param listener Listener to attach
5442      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5443      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)5444     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5445         ListenerInfo li = getListenerInfo();
5446         if (li.mOnAttachStateChangeListeners == null) {
5447             li.mOnAttachStateChangeListeners
5448                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5449         }
5450         li.mOnAttachStateChangeListeners.add(listener);
5451     }
5452 
5453     /**
5454      * Remove a listener for attach state changes. The listener will receive no further
5455      * notification of window attach/detach events.
5456      *
5457      * @param listener Listener to remove
5458      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5459      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)5460     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5461         ListenerInfo li = mListenerInfo;
5462         if (li == null || li.mOnAttachStateChangeListeners == null) {
5463             return;
5464         }
5465         li.mOnAttachStateChangeListeners.remove(listener);
5466     }
5467 
5468     /**
5469      * Returns the focus-change callback registered for this view.
5470      *
5471      * @return The callback, or null if one is not registered.
5472      */
getOnFocusChangeListener()5473     public OnFocusChangeListener getOnFocusChangeListener() {
5474         ListenerInfo li = mListenerInfo;
5475         return li != null ? li.mOnFocusChangeListener : null;
5476     }
5477 
5478     /**
5479      * Register a callback to be invoked when this view is clicked. If this view is not
5480      * clickable, it becomes clickable.
5481      *
5482      * @param l The callback that will run
5483      *
5484      * @see #setClickable(boolean)
5485      */
setOnClickListener(@ullable OnClickListener l)5486     public void setOnClickListener(@Nullable OnClickListener l) {
5487         if (!isClickable()) {
5488             setClickable(true);
5489         }
5490         getListenerInfo().mOnClickListener = l;
5491     }
5492 
5493     /**
5494      * Return whether this view has an attached OnClickListener.  Returns
5495      * true if there is a listener, false if there is none.
5496      */
hasOnClickListeners()5497     public boolean hasOnClickListeners() {
5498         ListenerInfo li = mListenerInfo;
5499         return (li != null && li.mOnClickListener != null);
5500     }
5501 
5502     /**
5503      * Register a callback to be invoked when this view is clicked and held. If this view is not
5504      * long clickable, it becomes long clickable.
5505      *
5506      * @param l The callback that will run
5507      *
5508      * @see #setLongClickable(boolean)
5509      */
setOnLongClickListener(@ullable OnLongClickListener l)5510     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5511         if (!isLongClickable()) {
5512             setLongClickable(true);
5513         }
5514         getListenerInfo().mOnLongClickListener = l;
5515     }
5516 
5517     /**
5518      * Register a callback to be invoked when this view is context clicked. If the view is not
5519      * context clickable, it becomes context clickable.
5520      *
5521      * @param l The callback that will run
5522      * @see #setContextClickable(boolean)
5523      */
setOnContextClickListener(@ullable OnContextClickListener l)5524     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5525         if (!isContextClickable()) {
5526             setContextClickable(true);
5527         }
5528         getListenerInfo().mOnContextClickListener = l;
5529     }
5530 
5531     /**
5532      * Register a callback to be invoked when the context menu for this view is
5533      * being built. If this view is not long clickable, it becomes long clickable.
5534      *
5535      * @param l The callback that will run
5536      *
5537      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)5538     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5539         if (!isLongClickable()) {
5540             setLongClickable(true);
5541         }
5542         getListenerInfo().mOnCreateContextMenuListener = l;
5543     }
5544 
5545     /**
5546      * Set an observer to collect stats for each frame rendered for this view.
5547      *
5548      * @hide
5549      */
addFrameMetricsListener(Window window, Window.OnFrameMetricsAvailableListener listener, Handler handler)5550     public void addFrameMetricsListener(Window window,
5551             Window.OnFrameMetricsAvailableListener listener,
5552             Handler handler) {
5553         if (mAttachInfo != null) {
5554             if (mAttachInfo.mHardwareRenderer != null) {
5555                 if (mFrameMetricsObservers == null) {
5556                     mFrameMetricsObservers = new ArrayList<>();
5557                 }
5558 
5559                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5560                         handler.getLooper(), listener);
5561                 mFrameMetricsObservers.add(fmo);
5562                 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
5563             } else {
5564                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5565             }
5566         } else {
5567             if (mFrameMetricsObservers == null) {
5568                 mFrameMetricsObservers = new ArrayList<>();
5569             }
5570 
5571             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5572                     handler.getLooper(), listener);
5573             mFrameMetricsObservers.add(fmo);
5574         }
5575     }
5576 
5577     /**
5578      * Remove observer configured to collect frame stats for this view.
5579      *
5580      * @hide
5581      */
removeFrameMetricsListener( Window.OnFrameMetricsAvailableListener listener)5582     public void removeFrameMetricsListener(
5583             Window.OnFrameMetricsAvailableListener listener) {
5584         ThreadedRenderer renderer = getHardwareRenderer();
5585         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5586         if (fmo == null) {
5587             throw new IllegalArgumentException(
5588                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
5589         }
5590 
5591         if (mFrameMetricsObservers != null) {
5592             mFrameMetricsObservers.remove(fmo);
5593             if (renderer != null) {
5594                 renderer.removeFrameMetricsObserver(fmo);
5595             }
5596         }
5597     }
5598 
registerPendingFrameMetricsObservers()5599     private void registerPendingFrameMetricsObservers() {
5600         if (mFrameMetricsObservers != null) {
5601             ThreadedRenderer renderer = getHardwareRenderer();
5602             if (renderer != null) {
5603                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5604                     renderer.addFrameMetricsObserver(fmo);
5605                 }
5606             } else {
5607                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5608             }
5609         }
5610     }
5611 
findFrameMetricsObserver( Window.OnFrameMetricsAvailableListener listener)5612     private FrameMetricsObserver findFrameMetricsObserver(
5613             Window.OnFrameMetricsAvailableListener listener) {
5614         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5615             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5616             if (observer.mListener == listener) {
5617                 return observer;
5618             }
5619         }
5620 
5621         return null;
5622     }
5623 
5624     /**
5625      * Call this view's OnClickListener, if it is defined.  Performs all normal
5626      * actions associated with clicking: reporting accessibility event, playing
5627      * a sound, etc.
5628      *
5629      * @return True there was an assigned OnClickListener that was called, false
5630      *         otherwise is returned.
5631      */
performClick()5632     public boolean performClick() {
5633         final boolean result;
5634         final ListenerInfo li = mListenerInfo;
5635         if (li != null && li.mOnClickListener != null) {
5636             playSoundEffect(SoundEffectConstants.CLICK);
5637             li.mOnClickListener.onClick(this);
5638             result = true;
5639         } else {
5640             result = false;
5641         }
5642 
5643         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5644         return result;
5645     }
5646 
5647     /**
5648      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5649      * this only calls the listener, and does not do any associated clicking
5650      * actions like reporting an accessibility event.
5651      *
5652      * @return True there was an assigned OnClickListener that was called, false
5653      *         otherwise is returned.
5654      */
callOnClick()5655     public boolean callOnClick() {
5656         ListenerInfo li = mListenerInfo;
5657         if (li != null && li.mOnClickListener != null) {
5658             li.mOnClickListener.onClick(this);
5659             return true;
5660         }
5661         return false;
5662     }
5663 
5664     /**
5665      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5666      * context menu if the OnLongClickListener did not consume the event.
5667      *
5668      * @return {@code true} if one of the above receivers consumed the event,
5669      *         {@code false} otherwise
5670      */
performLongClick()5671     public boolean performLongClick() {
5672         return performLongClickInternal(mLongClickX, mLongClickY);
5673     }
5674 
5675     /**
5676      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5677      * context menu if the OnLongClickListener did not consume the event,
5678      * anchoring it to an (x,y) coordinate.
5679      *
5680      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5681      *          to disable anchoring
5682      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5683      *          to disable anchoring
5684      * @return {@code true} if one of the above receivers consumed the event,
5685      *         {@code false} otherwise
5686      */
performLongClick(float x, float y)5687     public boolean performLongClick(float x, float y) {
5688         mLongClickX = x;
5689         mLongClickY = y;
5690         final boolean handled = performLongClick();
5691         mLongClickX = Float.NaN;
5692         mLongClickY = Float.NaN;
5693         return handled;
5694     }
5695 
5696     /**
5697      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5698      * context menu if the OnLongClickListener did not consume the event,
5699      * optionally anchoring it to an (x,y) coordinate.
5700      *
5701      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5702      *          to disable anchoring
5703      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5704      *          to disable anchoring
5705      * @return {@code true} if one of the above receivers consumed the event,
5706      *         {@code false} otherwise
5707      */
performLongClickInternal(float x, float y)5708     private boolean performLongClickInternal(float x, float y) {
5709         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5710 
5711         boolean handled = false;
5712         final ListenerInfo li = mListenerInfo;
5713         if (li != null && li.mOnLongClickListener != null) {
5714             handled = li.mOnLongClickListener.onLongClick(View.this);
5715         }
5716         if (!handled) {
5717             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5718             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5719         }
5720         if (handled) {
5721             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5722         }
5723         return handled;
5724     }
5725 
5726     /**
5727      * Call this view's OnContextClickListener, if it is defined.
5728      *
5729      * @param x the x coordinate of the context click
5730      * @param y the y coordinate of the context click
5731      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5732      *         otherwise.
5733      */
performContextClick(float x, float y)5734     public boolean performContextClick(float x, float y) {
5735         return performContextClick();
5736     }
5737 
5738     /**
5739      * Call this view's OnContextClickListener, if it is defined.
5740      *
5741      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5742      *         otherwise.
5743      */
performContextClick()5744     public boolean performContextClick() {
5745         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5746 
5747         boolean handled = false;
5748         ListenerInfo li = mListenerInfo;
5749         if (li != null && li.mOnContextClickListener != null) {
5750             handled = li.mOnContextClickListener.onContextClick(View.this);
5751         }
5752         if (handled) {
5753             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5754         }
5755         return handled;
5756     }
5757 
5758     /**
5759      * Performs button-related actions during a touch down event.
5760      *
5761      * @param event The event.
5762      * @return True if the down was consumed.
5763      *
5764      * @hide
5765      */
performButtonActionOnTouchDown(MotionEvent event)5766     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5767         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5768             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5769             showContextMenu(event.getX(), event.getY());
5770             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5771             return true;
5772         }
5773         return false;
5774     }
5775 
5776     /**
5777      * Shows the context menu for this view.
5778      *
5779      * @return {@code true} if the context menu was shown, {@code false}
5780      *         otherwise
5781      * @see #showContextMenu(float, float)
5782      */
showContextMenu()5783     public boolean showContextMenu() {
5784         return getParent().showContextMenuForChild(this);
5785     }
5786 
5787     /**
5788      * Shows the context menu for this view anchored to the specified
5789      * view-relative coordinate.
5790      *
5791      * @param x the X coordinate in pixels relative to the view to which the
5792      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5793      * @param y the Y coordinate in pixels relative to the view to which the
5794      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5795      * @return {@code true} if the context menu was shown, {@code false}
5796      *         otherwise
5797      */
showContextMenu(float x, float y)5798     public boolean showContextMenu(float x, float y) {
5799         return getParent().showContextMenuForChild(this, x, y);
5800     }
5801 
5802     /**
5803      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5804      *
5805      * @param callback Callback that will control the lifecycle of the action mode
5806      * @return The new action mode if it is started, null otherwise
5807      *
5808      * @see ActionMode
5809      * @see #startActionMode(android.view.ActionMode.Callback, int)
5810      */
startActionMode(ActionMode.Callback callback)5811     public ActionMode startActionMode(ActionMode.Callback callback) {
5812         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5813     }
5814 
5815     /**
5816      * Start an action mode with the given type.
5817      *
5818      * @param callback Callback that will control the lifecycle of the action mode
5819      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5820      * @return The new action mode if it is started, null otherwise
5821      *
5822      * @see ActionMode
5823      */
startActionMode(ActionMode.Callback callback, int type)5824     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5825         ViewParent parent = getParent();
5826         if (parent == null) return null;
5827         try {
5828             return parent.startActionModeForChild(this, callback, type);
5829         } catch (AbstractMethodError ame) {
5830             // Older implementations of custom views might not implement this.
5831             return parent.startActionModeForChild(this, callback);
5832         }
5833     }
5834 
5835     /**
5836      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5837      * Context, creating a unique View identifier to retrieve the result.
5838      *
5839      * @param intent The Intent to be started.
5840      * @param requestCode The request code to use.
5841      * @hide
5842      */
startActivityForResult(Intent intent, int requestCode)5843     public void startActivityForResult(Intent intent, int requestCode) {
5844         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5845         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5846     }
5847 
5848     /**
5849      * If this View corresponds to the calling who, dispatches the activity result.
5850      * @param who The identifier for the targeted View to receive the result.
5851      * @param requestCode The integer request code originally supplied to
5852      *                    startActivityForResult(), allowing you to identify who this
5853      *                    result came from.
5854      * @param resultCode The integer result code returned by the child activity
5855      *                   through its setResult().
5856      * @param data An Intent, which can return result data to the caller
5857      *               (various data can be attached to Intent "extras").
5858      * @return {@code true} if the activity result was dispatched.
5859      * @hide
5860      */
dispatchActivityResult( String who, int requestCode, int resultCode, Intent data)5861     public boolean dispatchActivityResult(
5862             String who, int requestCode, int resultCode, Intent data) {
5863         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5864             onActivityResult(requestCode, resultCode, data);
5865             mStartActivityRequestWho = null;
5866             return true;
5867         }
5868         return false;
5869     }
5870 
5871     /**
5872      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5873      *
5874      * @param requestCode The integer request code originally supplied to
5875      *                    startActivityForResult(), allowing you to identify who this
5876      *                    result came from.
5877      * @param resultCode The integer result code returned by the child activity
5878      *                   through its setResult().
5879      * @param data An Intent, which can return result data to the caller
5880      *               (various data can be attached to Intent "extras").
5881      * @hide
5882      */
onActivityResult(int requestCode, int resultCode, Intent data)5883     public void onActivityResult(int requestCode, int resultCode, Intent data) {
5884         // Do nothing.
5885     }
5886 
5887     /**
5888      * Register a callback to be invoked when a hardware key is pressed in this view.
5889      * Key presses in software input methods will generally not trigger the methods of
5890      * this listener.
5891      * @param l the key listener to attach to this view
5892      */
setOnKeyListener(OnKeyListener l)5893     public void setOnKeyListener(OnKeyListener l) {
5894         getListenerInfo().mOnKeyListener = l;
5895     }
5896 
5897     /**
5898      * Register a callback to be invoked when a touch event is sent to this view.
5899      * @param l the touch listener to attach to this view
5900      */
setOnTouchListener(OnTouchListener l)5901     public void setOnTouchListener(OnTouchListener l) {
5902         getListenerInfo().mOnTouchListener = l;
5903     }
5904 
5905     /**
5906      * Register a callback to be invoked when a generic motion event is sent to this view.
5907      * @param l the generic motion listener to attach to this view
5908      */
setOnGenericMotionListener(OnGenericMotionListener l)5909     public void setOnGenericMotionListener(OnGenericMotionListener l) {
5910         getListenerInfo().mOnGenericMotionListener = l;
5911     }
5912 
5913     /**
5914      * Register a callback to be invoked when a hover event is sent to this view.
5915      * @param l the hover listener to attach to this view
5916      */
setOnHoverListener(OnHoverListener l)5917     public void setOnHoverListener(OnHoverListener l) {
5918         getListenerInfo().mOnHoverListener = l;
5919     }
5920 
5921     /**
5922      * Register a drag event listener callback object for this View. The parameter is
5923      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5924      * View, the system calls the
5925      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5926      * @param l An implementation of {@link android.view.View.OnDragListener}.
5927      */
setOnDragListener(OnDragListener l)5928     public void setOnDragListener(OnDragListener l) {
5929         getListenerInfo().mOnDragListener = l;
5930     }
5931 
5932     /**
5933      * Give this view focus. This will cause
5934      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5935      *
5936      * Note: this does not check whether this {@link View} should get focus, it just
5937      * gives it focus no matter what.  It should only be called internally by framework
5938      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5939      *
5940      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5941      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5942      *        focus moved when requestFocus() is called. It may not always
5943      *        apply, in which case use the default View.FOCUS_DOWN.
5944      * @param previouslyFocusedRect The rectangle of the view that had focus
5945      *        prior in this View's coordinate system.
5946      */
handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)5947     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5948         if (DBG) {
5949             System.out.println(this + " requestFocus()");
5950         }
5951 
5952         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5953             mPrivateFlags |= PFLAG_FOCUSED;
5954 
5955             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5956 
5957             if (mParent != null) {
5958                 mParent.requestChildFocus(this, this);
5959             }
5960 
5961             if (mAttachInfo != null) {
5962                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5963             }
5964 
5965             onFocusChanged(true, direction, previouslyFocusedRect);
5966             refreshDrawableState();
5967         }
5968     }
5969 
5970     /**
5971      * Sets this view's preference for reveal behavior when it gains focus.
5972      *
5973      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
5974      * this view would prefer to be brought fully into view when it gains focus.
5975      * For example, a text field that a user is meant to type into. Other views such
5976      * as scrolling containers may prefer to opt-out of this behavior.</p>
5977      *
5978      * <p>The default value for views is true, though subclasses may change this
5979      * based on their preferred behavior.</p>
5980      *
5981      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
5982      *
5983      * @see #getRevealOnFocusHint()
5984      */
setRevealOnFocusHint(boolean revealOnFocus)5985     public final void setRevealOnFocusHint(boolean revealOnFocus) {
5986         if (revealOnFocus) {
5987             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
5988         } else {
5989             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
5990         }
5991     }
5992 
5993     /**
5994      * Returns this view's preference for reveal behavior when it gains focus.
5995      *
5996      * <p>When this method returns true for a child view requesting focus, ancestor
5997      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
5998      * should make a best effort to make the newly focused child fully visible to the user.
5999      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6000      * other properties affecting visibility to the user as part of the focus change.</p>
6001      *
6002      * @return true if this view would prefer to become fully visible when it gains focus,
6003      *         false if it would prefer not to disrupt scroll positioning
6004      *
6005      * @see #setRevealOnFocusHint(boolean)
6006      */
getRevealOnFocusHint()6007     public final boolean getRevealOnFocusHint() {
6008         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6009     }
6010 
6011     /**
6012      * Populates <code>outRect</code> with the hotspot bounds. By default,
6013      * the hotspot bounds are identical to the screen bounds.
6014      *
6015      * @param outRect rect to populate with hotspot bounds
6016      * @hide Only for internal use by views and widgets.
6017      */
getHotspotBounds(Rect outRect)6018     public void getHotspotBounds(Rect outRect) {
6019         final Drawable background = getBackground();
6020         if (background != null) {
6021             background.getHotspotBounds(outRect);
6022         } else {
6023             getBoundsOnScreen(outRect);
6024         }
6025     }
6026 
6027     /**
6028      * Request that a rectangle of this view be visible on the screen,
6029      * scrolling if necessary just enough.
6030      *
6031      * <p>A View should call this if it maintains some notion of which part
6032      * of its content is interesting.  For example, a text editing view
6033      * should call this when its cursor moves.
6034      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6035      * It should not be affected by which part of the View is currently visible or its scroll
6036      * position.
6037      *
6038      * @param rectangle The rectangle in the View's content coordinate space
6039      * @return Whether any parent scrolled.
6040      */
requestRectangleOnScreen(Rect rectangle)6041     public boolean requestRectangleOnScreen(Rect rectangle) {
6042         return requestRectangleOnScreen(rectangle, false);
6043     }
6044 
6045     /**
6046      * Request that a rectangle of this view be visible on the screen,
6047      * scrolling if necessary just enough.
6048      *
6049      * <p>A View should call this if it maintains some notion of which part
6050      * of its content is interesting.  For example, a text editing view
6051      * should call this when its cursor moves.
6052      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6053      * It should not be affected by which part of the View is currently visible or its scroll
6054      * position.
6055      * <p>When <code>immediate</code> is set to true, scrolling will not be
6056      * animated.
6057      *
6058      * @param rectangle The rectangle in the View's content coordinate space
6059      * @param immediate True to forbid animated scrolling, false otherwise
6060      * @return Whether any parent scrolled.
6061      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)6062     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6063         if (mParent == null) {
6064             return false;
6065         }
6066 
6067         View child = this;
6068 
6069         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6070         position.set(rectangle);
6071 
6072         ViewParent parent = mParent;
6073         boolean scrolled = false;
6074         while (parent != null) {
6075             rectangle.set((int) position.left, (int) position.top,
6076                     (int) position.right, (int) position.bottom);
6077 
6078             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6079 
6080             if (!(parent instanceof View)) {
6081                 break;
6082             }
6083 
6084             // move it from child's content coordinate space to parent's content coordinate space
6085             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6086 
6087             child = (View) parent;
6088             parent = child.getParent();
6089         }
6090 
6091         return scrolled;
6092     }
6093 
6094     /**
6095      * Called when this view wants to give up focus. If focus is cleared
6096      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6097      * <p>
6098      * <strong>Note:</strong> When a View clears focus the framework is trying
6099      * to give focus to the first focusable View from the top. Hence, if this
6100      * View is the first from the top that can take focus, then all callbacks
6101      * related to clearing focus will be invoked after which the framework will
6102      * give focus to this view.
6103      * </p>
6104      */
clearFocus()6105     public void clearFocus() {
6106         if (DBG) {
6107             System.out.println(this + " clearFocus()");
6108         }
6109 
6110         clearFocusInternal(null, true, true);
6111     }
6112 
6113     /**
6114      * Clears focus from the view, optionally propagating the change up through
6115      * the parent hierarchy and requesting that the root view place new focus.
6116      *
6117      * @param propagate whether to propagate the change up through the parent
6118      *            hierarchy
6119      * @param refocus when propagate is true, specifies whether to request the
6120      *            root view place new focus
6121      */
clearFocusInternal(View focused, boolean propagate, boolean refocus)6122     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6123         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6124             mPrivateFlags &= ~PFLAG_FOCUSED;
6125 
6126             if (propagate && mParent != null) {
6127                 mParent.clearChildFocus(this);
6128             }
6129 
6130             onFocusChanged(false, 0, null);
6131             refreshDrawableState();
6132 
6133             if (propagate && (!refocus || !rootViewRequestFocus())) {
6134                 notifyGlobalFocusCleared(this);
6135             }
6136         }
6137     }
6138 
notifyGlobalFocusCleared(View oldFocus)6139     void notifyGlobalFocusCleared(View oldFocus) {
6140         if (oldFocus != null && mAttachInfo != null) {
6141             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6142         }
6143     }
6144 
rootViewRequestFocus()6145     boolean rootViewRequestFocus() {
6146         final View root = getRootView();
6147         return root != null && root.requestFocus();
6148     }
6149 
6150     /**
6151      * Called internally by the view system when a new view is getting focus.
6152      * This is what clears the old focus.
6153      * <p>
6154      * <b>NOTE:</b> The parent view's focused child must be updated manually
6155      * after calling this method. Otherwise, the view hierarchy may be left in
6156      * an inconstent state.
6157      */
unFocus(View focused)6158     void unFocus(View focused) {
6159         if (DBG) {
6160             System.out.println(this + " unFocus()");
6161         }
6162 
6163         clearFocusInternal(focused, false, false);
6164     }
6165 
6166     /**
6167      * Returns true if this view has focus itself, or is the ancestor of the
6168      * view that has focus.
6169      *
6170      * @return True if this view has or contains focus, false otherwise.
6171      */
6172     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()6173     public boolean hasFocus() {
6174         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6175     }
6176 
6177     /**
6178      * Returns true if this view is focusable or if it contains a reachable View
6179      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6180      * is a View whose parents do not block descendants focus.
6181      *
6182      * Only {@link #VISIBLE} views are considered focusable.
6183      *
6184      * @return True if the view is focusable or if the view contains a focusable
6185      *         View, false otherwise.
6186      *
6187      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6188      * @see ViewGroup#getTouchscreenBlocksFocus()
6189      */
hasFocusable()6190     public boolean hasFocusable() {
6191         if (!isFocusableInTouchMode()) {
6192             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6193                 final ViewGroup g = (ViewGroup) p;
6194                 if (g.shouldBlockFocusForTouchscreen()) {
6195                     return false;
6196                 }
6197             }
6198         }
6199         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6200     }
6201 
6202     /**
6203      * Called by the view system when the focus state of this view changes.
6204      * When the focus change event is caused by directional navigation, direction
6205      * and previouslyFocusedRect provide insight into where the focus is coming from.
6206      * When overriding, be sure to call up through to the super class so that
6207      * the standard focus handling will occur.
6208      *
6209      * @param gainFocus True if the View has focus; false otherwise.
6210      * @param direction The direction focus has moved when requestFocus()
6211      *                  is called to give this view focus. Values are
6212      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6213      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6214      *                  It may not always apply, in which case use the default.
6215      * @param previouslyFocusedRect The rectangle, in this view's coordinate
6216      *        system, of the previously focused view.  If applicable, this will be
6217      *        passed in as finer grained information about where the focus is coming
6218      *        from (in addition to direction).  Will be <code>null</code> otherwise.
6219      */
6220     @CallSuper
onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)6221     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6222             @Nullable Rect previouslyFocusedRect) {
6223         if (gainFocus) {
6224             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6225         } else {
6226             notifyViewAccessibilityStateChangedIfNeeded(
6227                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6228         }
6229 
6230         InputMethodManager imm = InputMethodManager.peekInstance();
6231         if (!gainFocus) {
6232             if (isPressed()) {
6233                 setPressed(false);
6234             }
6235             if (imm != null && mAttachInfo != null
6236                     && mAttachInfo.mHasWindowFocus) {
6237                 imm.focusOut(this);
6238             }
6239             onFocusLost();
6240         } else if (imm != null && mAttachInfo != null
6241                 && mAttachInfo.mHasWindowFocus) {
6242             imm.focusIn(this);
6243         }
6244 
6245         invalidate(true);
6246         ListenerInfo li = mListenerInfo;
6247         if (li != null && li.mOnFocusChangeListener != null) {
6248             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6249         }
6250 
6251         if (mAttachInfo != null) {
6252             mAttachInfo.mKeyDispatchState.reset(this);
6253         }
6254     }
6255 
6256     /**
6257      * Sends an accessibility event of the given type. If accessibility is
6258      * not enabled this method has no effect. The default implementation calls
6259      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6260      * to populate information about the event source (this View), then calls
6261      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6262      * populate the text content of the event source including its descendants,
6263      * and last calls
6264      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6265      * on its parent to request sending of the event to interested parties.
6266      * <p>
6267      * If an {@link AccessibilityDelegate} has been specified via calling
6268      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6269      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6270      * responsible for handling this call.
6271      * </p>
6272      *
6273      * @param eventType The type of the event to send, as defined by several types from
6274      * {@link android.view.accessibility.AccessibilityEvent}, such as
6275      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6276      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6277      *
6278      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6279      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6280      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6281      * @see AccessibilityDelegate
6282      */
sendAccessibilityEvent(int eventType)6283     public void sendAccessibilityEvent(int eventType) {
6284         if (mAccessibilityDelegate != null) {
6285             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6286         } else {
6287             sendAccessibilityEventInternal(eventType);
6288         }
6289     }
6290 
6291     /**
6292      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6293      * {@link AccessibilityEvent} to make an announcement which is related to some
6294      * sort of a context change for which none of the events representing UI transitions
6295      * is a good fit. For example, announcing a new page in a book. If accessibility
6296      * is not enabled this method does nothing.
6297      *
6298      * @param text The announcement text.
6299      */
announceForAccessibility(CharSequence text)6300     public void announceForAccessibility(CharSequence text) {
6301         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6302             AccessibilityEvent event = AccessibilityEvent.obtain(
6303                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
6304             onInitializeAccessibilityEvent(event);
6305             event.getText().add(text);
6306             event.setContentDescription(null);
6307             mParent.requestSendAccessibilityEvent(this, event);
6308         }
6309     }
6310 
6311     /**
6312      * @see #sendAccessibilityEvent(int)
6313      *
6314      * Note: Called from the default {@link AccessibilityDelegate}.
6315      *
6316      * @hide
6317      */
sendAccessibilityEventInternal(int eventType)6318     public void sendAccessibilityEventInternal(int eventType) {
6319         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6320             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6321         }
6322     }
6323 
6324     /**
6325      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6326      * takes as an argument an empty {@link AccessibilityEvent} and does not
6327      * perform a check whether accessibility is enabled.
6328      * <p>
6329      * If an {@link AccessibilityDelegate} has been specified via calling
6330      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6331      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6332      * is responsible for handling this call.
6333      * </p>
6334      *
6335      * @param event The event to send.
6336      *
6337      * @see #sendAccessibilityEvent(int)
6338      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)6339     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6340         if (mAccessibilityDelegate != null) {
6341             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6342         } else {
6343             sendAccessibilityEventUncheckedInternal(event);
6344         }
6345     }
6346 
6347     /**
6348      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6349      *
6350      * Note: Called from the default {@link AccessibilityDelegate}.
6351      *
6352      * @hide
6353      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)6354     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6355         if (!isShown()) {
6356             return;
6357         }
6358         onInitializeAccessibilityEvent(event);
6359         // Only a subset of accessibility events populates text content.
6360         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6361             dispatchPopulateAccessibilityEvent(event);
6362         }
6363         // In the beginning we called #isShown(), so we know that getParent() is not null.
6364         getParent().requestSendAccessibilityEvent(this, event);
6365     }
6366 
6367     /**
6368      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6369      * to its children for adding their text content to the event. Note that the
6370      * event text is populated in a separate dispatch path since we add to the
6371      * event not only the text of the source but also the text of all its descendants.
6372      * A typical implementation will call
6373      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6374      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6375      * on each child. Override this method if custom population of the event text
6376      * content is required.
6377      * <p>
6378      * If an {@link AccessibilityDelegate} has been specified via calling
6379      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6380      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6381      * is responsible for handling this call.
6382      * </p>
6383      * <p>
6384      * <em>Note:</em> Accessibility events of certain types are not dispatched for
6385      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6386      * </p>
6387      *
6388      * @param event The event.
6389      *
6390      * @return True if the event population was completed.
6391      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)6392     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6393         if (mAccessibilityDelegate != null) {
6394             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6395         } else {
6396             return dispatchPopulateAccessibilityEventInternal(event);
6397         }
6398     }
6399 
6400     /**
6401      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6402      *
6403      * Note: Called from the default {@link AccessibilityDelegate}.
6404      *
6405      * @hide
6406      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)6407     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6408         onPopulateAccessibilityEvent(event);
6409         return false;
6410     }
6411 
6412     /**
6413      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6414      * giving a chance to this View to populate the accessibility event with its
6415      * text content. While this method is free to modify event
6416      * attributes other than text content, doing so should normally be performed in
6417      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6418      * <p>
6419      * Example: Adding formatted date string to an accessibility event in addition
6420      *          to the text added by the super implementation:
6421      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6422      *     super.onPopulateAccessibilityEvent(event);
6423      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6424      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6425      *         mCurrentDate.getTimeInMillis(), flags);
6426      *     event.getText().add(selectedDateUtterance);
6427      * }</pre>
6428      * <p>
6429      * If an {@link AccessibilityDelegate} has been specified via calling
6430      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6431      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6432      * is responsible for handling this call.
6433      * </p>
6434      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6435      * information to the event, in case the default implementation has basic information to add.
6436      * </p>
6437      *
6438      * @param event The accessibility event which to populate.
6439      *
6440      * @see #sendAccessibilityEvent(int)
6441      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6442      */
6443     @CallSuper
onPopulateAccessibilityEvent(AccessibilityEvent event)6444     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6445         if (mAccessibilityDelegate != null) {
6446             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6447         } else {
6448             onPopulateAccessibilityEventInternal(event);
6449         }
6450     }
6451 
6452     /**
6453      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6454      *
6455      * Note: Called from the default {@link AccessibilityDelegate}.
6456      *
6457      * @hide
6458      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)6459     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6460     }
6461 
6462     /**
6463      * Initializes an {@link AccessibilityEvent} with information about
6464      * this View which is the event source. In other words, the source of
6465      * an accessibility event is the view whose state change triggered firing
6466      * the event.
6467      * <p>
6468      * Example: Setting the password property of an event in addition
6469      *          to properties set by the super implementation:
6470      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6471      *     super.onInitializeAccessibilityEvent(event);
6472      *     event.setPassword(true);
6473      * }</pre>
6474      * <p>
6475      * If an {@link AccessibilityDelegate} has been specified via calling
6476      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6477      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6478      * is responsible for handling this call.
6479      * </p>
6480      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6481      * information to the event, in case the default implementation has basic information to add.
6482      * </p>
6483      * @param event The event to initialize.
6484      *
6485      * @see #sendAccessibilityEvent(int)
6486      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6487      */
6488     @CallSuper
onInitializeAccessibilityEvent(AccessibilityEvent event)6489     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6490         if (mAccessibilityDelegate != null) {
6491             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6492         } else {
6493             onInitializeAccessibilityEventInternal(event);
6494         }
6495     }
6496 
6497     /**
6498      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6499      *
6500      * Note: Called from the default {@link AccessibilityDelegate}.
6501      *
6502      * @hide
6503      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)6504     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6505         event.setSource(this);
6506         event.setClassName(getAccessibilityClassName());
6507         event.setPackageName(getContext().getPackageName());
6508         event.setEnabled(isEnabled());
6509         event.setContentDescription(mContentDescription);
6510 
6511         switch (event.getEventType()) {
6512             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6513                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
6514                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6515                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6516                 event.setItemCount(focusablesTempList.size());
6517                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6518                 if (mAttachInfo != null) {
6519                     focusablesTempList.clear();
6520                 }
6521             } break;
6522             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6523                 CharSequence text = getIterableTextForAccessibility();
6524                 if (text != null && text.length() > 0) {
6525                     event.setFromIndex(getAccessibilitySelectionStart());
6526                     event.setToIndex(getAccessibilitySelectionEnd());
6527                     event.setItemCount(text.length());
6528                 }
6529             } break;
6530         }
6531     }
6532 
6533     /**
6534      * Returns an {@link AccessibilityNodeInfo} representing this view from the
6535      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6536      * This method is responsible for obtaining an accessibility node info from a
6537      * pool of reusable instances and calling
6538      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6539      * initialize the former.
6540      * <p>
6541      * Note: The client is responsible for recycling the obtained instance by calling
6542      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6543      * </p>
6544      *
6545      * @return A populated {@link AccessibilityNodeInfo}.
6546      *
6547      * @see AccessibilityNodeInfo
6548      */
createAccessibilityNodeInfo()6549     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6550         if (mAccessibilityDelegate != null) {
6551             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6552         } else {
6553             return createAccessibilityNodeInfoInternal();
6554         }
6555     }
6556 
6557     /**
6558      * @see #createAccessibilityNodeInfo()
6559      *
6560      * @hide
6561      */
createAccessibilityNodeInfoInternal()6562     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6563         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6564         if (provider != null) {
6565             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6566         } else {
6567             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6568             onInitializeAccessibilityNodeInfo(info);
6569             return info;
6570         }
6571     }
6572 
6573     /**
6574      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6575      * The base implementation sets:
6576      * <ul>
6577      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6578      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6579      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6580      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6581      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6582      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6583      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6584      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6585      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6586      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6587      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6588      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6589      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6590      * </ul>
6591      * <p>
6592      * Subclasses should override this method, call the super implementation,
6593      * and set additional attributes.
6594      * </p>
6595      * <p>
6596      * If an {@link AccessibilityDelegate} has been specified via calling
6597      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6598      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6599      * is responsible for handling this call.
6600      * </p>
6601      *
6602      * @param info The instance to initialize.
6603      */
6604     @CallSuper
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)6605     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6606         if (mAccessibilityDelegate != null) {
6607             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6608         } else {
6609             onInitializeAccessibilityNodeInfoInternal(info);
6610         }
6611     }
6612 
6613     /**
6614      * Gets the location of this view in screen coordinates.
6615      *
6616      * @param outRect The output location
6617      * @hide
6618      */
getBoundsOnScreen(Rect outRect)6619     public void getBoundsOnScreen(Rect outRect) {
6620         getBoundsOnScreen(outRect, false);
6621     }
6622 
6623     /**
6624      * Gets the location of this view in screen coordinates.
6625      *
6626      * @param outRect The output location
6627      * @param clipToParent Whether to clip child bounds to the parent ones.
6628      * @hide
6629      */
getBoundsOnScreen(Rect outRect, boolean clipToParent)6630     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6631         if (mAttachInfo == null) {
6632             return;
6633         }
6634 
6635         RectF position = mAttachInfo.mTmpTransformRect;
6636         position.set(0, 0, mRight - mLeft, mBottom - mTop);
6637 
6638         if (!hasIdentityMatrix()) {
6639             getMatrix().mapRect(position);
6640         }
6641 
6642         position.offset(mLeft, mTop);
6643 
6644         ViewParent parent = mParent;
6645         while (parent instanceof View) {
6646             View parentView = (View) parent;
6647 
6648             position.offset(-parentView.mScrollX, -parentView.mScrollY);
6649 
6650             if (clipToParent) {
6651                 position.left = Math.max(position.left, 0);
6652                 position.top = Math.max(position.top, 0);
6653                 position.right = Math.min(position.right, parentView.getWidth());
6654                 position.bottom = Math.min(position.bottom, parentView.getHeight());
6655             }
6656 
6657             if (!parentView.hasIdentityMatrix()) {
6658                 parentView.getMatrix().mapRect(position);
6659             }
6660 
6661             position.offset(parentView.mLeft, parentView.mTop);
6662 
6663             parent = parentView.mParent;
6664         }
6665 
6666         if (parent instanceof ViewRootImpl) {
6667             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6668             position.offset(0, -viewRootImpl.mCurScrollY);
6669         }
6670 
6671         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6672 
6673         outRect.set(Math.round(position.left), Math.round(position.top),
6674                 Math.round(position.right), Math.round(position.bottom));
6675     }
6676 
6677     /**
6678      * Return the class name of this object to be used for accessibility purposes.
6679      * Subclasses should only override this if they are implementing something that
6680      * should be seen as a completely new class of view when used by accessibility,
6681      * unrelated to the class it is deriving from.  This is used to fill in
6682      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6683      */
getAccessibilityClassName()6684     public CharSequence getAccessibilityClassName() {
6685         return View.class.getName();
6686     }
6687 
6688     /**
6689      * Called when assist structure is being retrieved from a view as part of
6690      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6691      * @param structure Fill in with structured view data.  The default implementation
6692      * fills in all data that can be inferred from the view itself.
6693      */
onProvideStructure(ViewStructure structure)6694     public void onProvideStructure(ViewStructure structure) {
6695         final int id = mID;
6696         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6697                 && (id&0x0000ffff) != 0) {
6698             String pkg, type, entry;
6699             try {
6700                 final Resources res = getResources();
6701                 entry = res.getResourceEntryName(id);
6702                 type = res.getResourceTypeName(id);
6703                 pkg = res.getResourcePackageName(id);
6704             } catch (Resources.NotFoundException e) {
6705                 entry = type = pkg = null;
6706             }
6707             structure.setId(id, pkg, type, entry);
6708         } else {
6709             structure.setId(id, null, null, null);
6710         }
6711         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6712         if (!hasIdentityMatrix()) {
6713             structure.setTransformation(getMatrix());
6714         }
6715         structure.setElevation(getZ());
6716         structure.setVisibility(getVisibility());
6717         structure.setEnabled(isEnabled());
6718         if (isClickable()) {
6719             structure.setClickable(true);
6720         }
6721         if (isFocusable()) {
6722             structure.setFocusable(true);
6723         }
6724         if (isFocused()) {
6725             structure.setFocused(true);
6726         }
6727         if (isAccessibilityFocused()) {
6728             structure.setAccessibilityFocused(true);
6729         }
6730         if (isSelected()) {
6731             structure.setSelected(true);
6732         }
6733         if (isActivated()) {
6734             structure.setActivated(true);
6735         }
6736         if (isLongClickable()) {
6737             structure.setLongClickable(true);
6738         }
6739         if (this instanceof Checkable) {
6740             structure.setCheckable(true);
6741             if (((Checkable)this).isChecked()) {
6742                 structure.setChecked(true);
6743             }
6744         }
6745         if (isContextClickable()) {
6746             structure.setContextClickable(true);
6747         }
6748         structure.setClassName(getAccessibilityClassName().toString());
6749         structure.setContentDescription(getContentDescription());
6750     }
6751 
6752     /**
6753      * Called when assist structure is being retrieved from a view as part of
6754      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6755      * generate additional virtual structure under this view.  The defaullt implementation
6756      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6757      * view's virtual accessibility nodes, if any.  You can override this for a more
6758      * optimal implementation providing this data.
6759      */
onProvideVirtualStructure(ViewStructure structure)6760     public void onProvideVirtualStructure(ViewStructure structure) {
6761         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6762         if (provider != null) {
6763             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6764             structure.setChildCount(1);
6765             ViewStructure root = structure.newChild(0);
6766             populateVirtualStructure(root, provider, info);
6767             info.recycle();
6768         }
6769     }
6770 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info)6771     private void populateVirtualStructure(ViewStructure structure,
6772             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6773         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6774                 null, null, null);
6775         Rect rect = structure.getTempRect();
6776         info.getBoundsInParent(rect);
6777         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6778         structure.setVisibility(VISIBLE);
6779         structure.setEnabled(info.isEnabled());
6780         if (info.isClickable()) {
6781             structure.setClickable(true);
6782         }
6783         if (info.isFocusable()) {
6784             structure.setFocusable(true);
6785         }
6786         if (info.isFocused()) {
6787             structure.setFocused(true);
6788         }
6789         if (info.isAccessibilityFocused()) {
6790             structure.setAccessibilityFocused(true);
6791         }
6792         if (info.isSelected()) {
6793             structure.setSelected(true);
6794         }
6795         if (info.isLongClickable()) {
6796             structure.setLongClickable(true);
6797         }
6798         if (info.isCheckable()) {
6799             structure.setCheckable(true);
6800             if (info.isChecked()) {
6801                 structure.setChecked(true);
6802             }
6803         }
6804         if (info.isContextClickable()) {
6805             structure.setContextClickable(true);
6806         }
6807         CharSequence cname = info.getClassName();
6808         structure.setClassName(cname != null ? cname.toString() : null);
6809         structure.setContentDescription(info.getContentDescription());
6810         if (info.getText() != null || info.getError() != null) {
6811             structure.setText(info.getText(), info.getTextSelectionStart(),
6812                     info.getTextSelectionEnd());
6813         }
6814         final int NCHILDREN = info.getChildCount();
6815         if (NCHILDREN > 0) {
6816             structure.setChildCount(NCHILDREN);
6817             for (int i=0; i<NCHILDREN; i++) {
6818                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6819                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6820                 ViewStructure child = structure.newChild(i);
6821                 populateVirtualStructure(child, provider, cinfo);
6822                 cinfo.recycle();
6823             }
6824         }
6825     }
6826 
6827     /**
6828      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6829      * implementation calls {@link #onProvideStructure} and
6830      * {@link #onProvideVirtualStructure}.
6831      */
dispatchProvideStructure(ViewStructure structure)6832     public void dispatchProvideStructure(ViewStructure structure) {
6833         if (!isAssistBlocked()) {
6834             onProvideStructure(structure);
6835             onProvideVirtualStructure(structure);
6836         } else {
6837             structure.setClassName(getAccessibilityClassName().toString());
6838             structure.setAssistBlocked(true);
6839         }
6840     }
6841 
6842     /**
6843      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6844      *
6845      * Note: Called from the default {@link AccessibilityDelegate}.
6846      *
6847      * @hide
6848      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)6849     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6850         if (mAttachInfo == null) {
6851             return;
6852         }
6853 
6854         Rect bounds = mAttachInfo.mTmpInvalRect;
6855 
6856         getDrawingRect(bounds);
6857         info.setBoundsInParent(bounds);
6858 
6859         getBoundsOnScreen(bounds, true);
6860         info.setBoundsInScreen(bounds);
6861 
6862         ViewParent parent = getParentForAccessibility();
6863         if (parent instanceof View) {
6864             info.setParent((View) parent);
6865         }
6866 
6867         if (mID != View.NO_ID) {
6868             View rootView = getRootView();
6869             if (rootView == null) {
6870                 rootView = this;
6871             }
6872 
6873             View label = rootView.findLabelForView(this, mID);
6874             if (label != null) {
6875                 info.setLabeledBy(label);
6876             }
6877 
6878             if ((mAttachInfo.mAccessibilityFetchFlags
6879                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6880                     && Resources.resourceHasPackage(mID)) {
6881                 try {
6882                     String viewId = getResources().getResourceName(mID);
6883                     info.setViewIdResourceName(viewId);
6884                 } catch (Resources.NotFoundException nfe) {
6885                     /* ignore */
6886                 }
6887             }
6888         }
6889 
6890         if (mLabelForId != View.NO_ID) {
6891             View rootView = getRootView();
6892             if (rootView == null) {
6893                 rootView = this;
6894             }
6895             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6896             if (labeled != null) {
6897                 info.setLabelFor(labeled);
6898             }
6899         }
6900 
6901         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6902             View rootView = getRootView();
6903             if (rootView == null) {
6904                 rootView = this;
6905             }
6906             View next = rootView.findViewInsideOutShouldExist(this,
6907                     mAccessibilityTraversalBeforeId);
6908             if (next != null && next.includeForAccessibility()) {
6909                 info.setTraversalBefore(next);
6910             }
6911         }
6912 
6913         if (mAccessibilityTraversalAfterId != View.NO_ID) {
6914             View rootView = getRootView();
6915             if (rootView == null) {
6916                 rootView = this;
6917             }
6918             View next = rootView.findViewInsideOutShouldExist(this,
6919                     mAccessibilityTraversalAfterId);
6920             if (next != null && next.includeForAccessibility()) {
6921                 info.setTraversalAfter(next);
6922             }
6923         }
6924 
6925         info.setVisibleToUser(isVisibleToUser());
6926 
6927         if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6928                 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6929             info.setImportantForAccessibility(isImportantForAccessibility());
6930         } else {
6931             info.setImportantForAccessibility(true);
6932         }
6933 
6934         info.setPackageName(mContext.getPackageName());
6935         info.setClassName(getAccessibilityClassName());
6936         info.setContentDescription(getContentDescription());
6937 
6938         info.setEnabled(isEnabled());
6939         info.setClickable(isClickable());
6940         info.setFocusable(isFocusable());
6941         info.setFocused(isFocused());
6942         info.setAccessibilityFocused(isAccessibilityFocused());
6943         info.setSelected(isSelected());
6944         info.setLongClickable(isLongClickable());
6945         info.setContextClickable(isContextClickable());
6946         info.setLiveRegion(getAccessibilityLiveRegion());
6947 
6948         // TODO: These make sense only if we are in an AdapterView but all
6949         // views can be selected. Maybe from accessibility perspective
6950         // we should report as selectable view in an AdapterView.
6951         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6952         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6953 
6954         if (isFocusable()) {
6955             if (isFocused()) {
6956                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6957             } else {
6958                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6959             }
6960         }
6961 
6962         if (!isAccessibilityFocused()) {
6963             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6964         } else {
6965             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6966         }
6967 
6968         if (isClickable() && isEnabled()) {
6969             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6970         }
6971 
6972         if (isLongClickable() && isEnabled()) {
6973             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6974         }
6975 
6976         if (isContextClickable() && isEnabled()) {
6977             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6978         }
6979 
6980         CharSequence text = getIterableTextForAccessibility();
6981         if (text != null && text.length() > 0) {
6982             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6983 
6984             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6985             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6986             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6987             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6988                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6989                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6990         }
6991 
6992         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6993         populateAccessibilityNodeInfoDrawingOrderInParent(info);
6994     }
6995 
6996     /**
6997      * Determine the order in which this view will be drawn relative to its siblings for a11y
6998      *
6999      * @param info The info whose drawing order should be populated
7000      */
populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)7001     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7002         /*
7003          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7004          * drawing order may not be well-defined, and some Views with custom drawing order may
7005          * not be initialized sufficiently to respond properly getChildDrawingOrder.
7006          */
7007         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7008             info.setDrawingOrder(0);
7009             return;
7010         }
7011         int drawingOrderInParent = 1;
7012         // Iterate up the hierarchy if parents are not important for a11y
7013         View viewAtDrawingLevel = this;
7014         final ViewParent parent = getParentForAccessibility();
7015         while (viewAtDrawingLevel != parent) {
7016             final ViewParent currentParent = viewAtDrawingLevel.getParent();
7017             if (!(currentParent instanceof ViewGroup)) {
7018                 // Should only happen for the Decor
7019                 drawingOrderInParent = 0;
7020                 break;
7021             } else {
7022                 final ViewGroup parentGroup = (ViewGroup) currentParent;
7023                 final int childCount = parentGroup.getChildCount();
7024                 if (childCount > 1) {
7025                     List<View> preorderedList = parentGroup.buildOrderedChildList();
7026                     if (preorderedList != null) {
7027                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7028                         for (int i = 0; i < childDrawIndex; i++) {
7029                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7030                         }
7031                     } else {
7032                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7033                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7034                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7035                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
7036                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7037                         if (childDrawIndex != 0) {
7038                             for (int i = 0; i < numChildrenToIterate; i++) {
7039                                 final int otherDrawIndex = (customOrder ?
7040                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
7041                                 if (otherDrawIndex < childDrawIndex) {
7042                                     drawingOrderInParent +=
7043                                             numViewsForAccessibility(parentGroup.getChildAt(i));
7044                                 }
7045                             }
7046                         }
7047                     }
7048                 }
7049             }
7050             viewAtDrawingLevel = (View) currentParent;
7051         }
7052         info.setDrawingOrder(drawingOrderInParent);
7053     }
7054 
numViewsForAccessibility(View view)7055     private static int numViewsForAccessibility(View view) {
7056         if (view != null) {
7057             if (view.includeForAccessibility()) {
7058                 return 1;
7059             } else if (view instanceof ViewGroup) {
7060                 return ((ViewGroup) view).getNumChildrenForAccessibility();
7061             }
7062         }
7063         return 0;
7064     }
7065 
findLabelForView(View view, int labeledId)7066     private View findLabelForView(View view, int labeledId) {
7067         if (mMatchLabelForPredicate == null) {
7068             mMatchLabelForPredicate = new MatchLabelForPredicate();
7069         }
7070         mMatchLabelForPredicate.mLabeledId = labeledId;
7071         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7072     }
7073 
7074     /**
7075      * Computes whether this view is visible to the user. Such a view is
7076      * attached, visible, all its predecessors are visible, it is not clipped
7077      * entirely by its predecessors, and has an alpha greater than zero.
7078      *
7079      * @return Whether the view is visible on the screen.
7080      *
7081      * @hide
7082      */
isVisibleToUser()7083     protected boolean isVisibleToUser() {
7084         return isVisibleToUser(null);
7085     }
7086 
7087     /**
7088      * Computes whether the given portion of this view is visible to the user.
7089      * Such a view is attached, visible, all its predecessors are visible,
7090      * has an alpha greater than zero, and the specified portion is not
7091      * clipped entirely by its predecessors.
7092      *
7093      * @param boundInView the portion of the view to test; coordinates should be relative; may be
7094      *                    <code>null</code>, and the entire view will be tested in this case.
7095      *                    When <code>true</code> is returned by the function, the actual visible
7096      *                    region will be stored in this parameter; that is, if boundInView is fully
7097      *                    contained within the view, no modification will be made, otherwise regions
7098      *                    outside of the visible area of the view will be clipped.
7099      *
7100      * @return Whether the specified portion of the view is visible on the screen.
7101      *
7102      * @hide
7103      */
isVisibleToUser(Rect boundInView)7104     protected boolean isVisibleToUser(Rect boundInView) {
7105         if (mAttachInfo != null) {
7106             // Attached to invisible window means this view is not visible.
7107             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7108                 return false;
7109             }
7110             // An invisible predecessor or one with alpha zero means
7111             // that this view is not visible to the user.
7112             Object current = this;
7113             while (current instanceof View) {
7114                 View view = (View) current;
7115                 // We have attach info so this view is attached and there is no
7116                 // need to check whether we reach to ViewRootImpl on the way up.
7117                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7118                         view.getVisibility() != VISIBLE) {
7119                     return false;
7120                 }
7121                 current = view.mParent;
7122             }
7123             // Check if the view is entirely covered by its predecessors.
7124             Rect visibleRect = mAttachInfo.mTmpInvalRect;
7125             Point offset = mAttachInfo.mPoint;
7126             if (!getGlobalVisibleRect(visibleRect, offset)) {
7127                 return false;
7128             }
7129             // Check if the visible portion intersects the rectangle of interest.
7130             if (boundInView != null) {
7131                 visibleRect.offset(-offset.x, -offset.y);
7132                 return boundInView.intersect(visibleRect);
7133             }
7134             return true;
7135         }
7136         return false;
7137     }
7138 
7139     /**
7140      * Returns the delegate for implementing accessibility support via
7141      * composition. For more details see {@link AccessibilityDelegate}.
7142      *
7143      * @return The delegate, or null if none set.
7144      *
7145      * @hide
7146      */
getAccessibilityDelegate()7147     public AccessibilityDelegate getAccessibilityDelegate() {
7148         return mAccessibilityDelegate;
7149     }
7150 
7151     /**
7152      * Sets a delegate for implementing accessibility support via composition
7153      * (as opposed to inheritance). For more details, see
7154      * {@link AccessibilityDelegate}.
7155      * <p>
7156      * <strong>Note:</strong> On platform versions prior to
7157      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7158      * views in the {@code android.widget.*} package are called <i>before</i>
7159      * host methods. This prevents certain properties such as class name from
7160      * being modified by overriding
7161      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7162      * as any changes will be overwritten by the host class.
7163      * <p>
7164      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7165      * methods are called <i>after</i> host methods, which all properties to be
7166      * modified without being overwritten by the host class.
7167      *
7168      * @param delegate the object to which accessibility method calls should be
7169      *                 delegated
7170      * @see AccessibilityDelegate
7171      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)7172     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7173         mAccessibilityDelegate = delegate;
7174     }
7175 
7176     /**
7177      * Gets the provider for managing a virtual view hierarchy rooted at this View
7178      * and reported to {@link android.accessibilityservice.AccessibilityService}s
7179      * that explore the window content.
7180      * <p>
7181      * If this method returns an instance, this instance is responsible for managing
7182      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7183      * View including the one representing the View itself. Similarly the returned
7184      * instance is responsible for performing accessibility actions on any virtual
7185      * view or the root view itself.
7186      * </p>
7187      * <p>
7188      * If an {@link AccessibilityDelegate} has been specified via calling
7189      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7190      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7191      * is responsible for handling this call.
7192      * </p>
7193      *
7194      * @return The provider.
7195      *
7196      * @see AccessibilityNodeProvider
7197      */
getAccessibilityNodeProvider()7198     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7199         if (mAccessibilityDelegate != null) {
7200             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7201         } else {
7202             return null;
7203         }
7204     }
7205 
7206     /**
7207      * Gets the unique identifier of this view on the screen for accessibility purposes.
7208      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7209      *
7210      * @return The view accessibility id.
7211      *
7212      * @hide
7213      */
getAccessibilityViewId()7214     public int getAccessibilityViewId() {
7215         if (mAccessibilityViewId == NO_ID) {
7216             mAccessibilityViewId = sNextAccessibilityViewId++;
7217         }
7218         return mAccessibilityViewId;
7219     }
7220 
7221     /**
7222      * Gets the unique identifier of the window in which this View reseides.
7223      *
7224      * @return The window accessibility id.
7225      *
7226      * @hide
7227      */
getAccessibilityWindowId()7228     public int getAccessibilityWindowId() {
7229         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7230                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7231     }
7232 
7233     /**
7234      * Returns the {@link View}'s content description.
7235      * <p>
7236      * <strong>Note:</strong> Do not override this method, as it will have no
7237      * effect on the content description presented to accessibility services.
7238      * You must call {@link #setContentDescription(CharSequence)} to modify the
7239      * content description.
7240      *
7241      * @return the content description
7242      * @see #setContentDescription(CharSequence)
7243      * @attr ref android.R.styleable#View_contentDescription
7244      */
7245     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()7246     public CharSequence getContentDescription() {
7247         return mContentDescription;
7248     }
7249 
7250     /**
7251      * Sets the {@link View}'s content description.
7252      * <p>
7253      * A content description briefly describes the view and is primarily used
7254      * for accessibility support to determine how a view should be presented to
7255      * the user. In the case of a view with no textual representation, such as
7256      * {@link android.widget.ImageButton}, a useful content description
7257      * explains what the view does. For example, an image button with a phone
7258      * icon that is used to place a call may use "Call" as its content
7259      * description. An image of a floppy disk that is used to save a file may
7260      * use "Save".
7261      *
7262      * @param contentDescription The content description.
7263      * @see #getContentDescription()
7264      * @attr ref android.R.styleable#View_contentDescription
7265      */
7266     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)7267     public void setContentDescription(CharSequence contentDescription) {
7268         if (mContentDescription == null) {
7269             if (contentDescription == null) {
7270                 return;
7271             }
7272         } else if (mContentDescription.equals(contentDescription)) {
7273             return;
7274         }
7275         mContentDescription = contentDescription;
7276         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7277         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7278             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7279             notifySubtreeAccessibilityStateChangedIfNeeded();
7280         } else {
7281             notifyViewAccessibilityStateChangedIfNeeded(
7282                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7283         }
7284     }
7285 
7286     /**
7287      * Sets the id of a view before which this one is visited in accessibility traversal.
7288      * A screen-reader must visit the content of this view before the content of the one
7289      * it precedes. For example, if view B is set to be before view A, then a screen-reader
7290      * will traverse the entire content of B before traversing the entire content of A,
7291      * regardles of what traversal strategy it is using.
7292      * <p>
7293      * Views that do not have specified before/after relationships are traversed in order
7294      * determined by the screen-reader.
7295      * </p>
7296      * <p>
7297      * Setting that this view is before a view that is not important for accessibility
7298      * or if this view is not important for accessibility will have no effect as the
7299      * screen-reader is not aware of unimportant views.
7300      * </p>
7301      *
7302      * @param beforeId The id of a view this one precedes in accessibility traversal.
7303      *
7304      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7305      *
7306      * @see #setImportantForAccessibility(int)
7307      */
7308     @RemotableViewMethod
setAccessibilityTraversalBefore(int beforeId)7309     public void setAccessibilityTraversalBefore(int beforeId) {
7310         if (mAccessibilityTraversalBeforeId == beforeId) {
7311             return;
7312         }
7313         mAccessibilityTraversalBeforeId = beforeId;
7314         notifyViewAccessibilityStateChangedIfNeeded(
7315                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7316     }
7317 
7318     /**
7319      * Gets the id of a view before which this one is visited in accessibility traversal.
7320      *
7321      * @return The id of a view this one precedes in accessibility traversal if
7322      *         specified, otherwise {@link #NO_ID}.
7323      *
7324      * @see #setAccessibilityTraversalBefore(int)
7325      */
getAccessibilityTraversalBefore()7326     public int getAccessibilityTraversalBefore() {
7327         return mAccessibilityTraversalBeforeId;
7328     }
7329 
7330     /**
7331      * Sets the id of a view after which this one is visited in accessibility traversal.
7332      * A screen-reader must visit the content of the other view before the content of this
7333      * one. For example, if view B is set to be after view A, then a screen-reader
7334      * will traverse the entire content of A before traversing the entire content of B,
7335      * regardles of what traversal strategy it is using.
7336      * <p>
7337      * Views that do not have specified before/after relationships are traversed in order
7338      * determined by the screen-reader.
7339      * </p>
7340      * <p>
7341      * Setting that this view is after a view that is not important for accessibility
7342      * or if this view is not important for accessibility will have no effect as the
7343      * screen-reader is not aware of unimportant views.
7344      * </p>
7345      *
7346      * @param afterId The id of a view this one succedees in accessibility traversal.
7347      *
7348      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7349      *
7350      * @see #setImportantForAccessibility(int)
7351      */
7352     @RemotableViewMethod
setAccessibilityTraversalAfter(int afterId)7353     public void setAccessibilityTraversalAfter(int afterId) {
7354         if (mAccessibilityTraversalAfterId == afterId) {
7355             return;
7356         }
7357         mAccessibilityTraversalAfterId = afterId;
7358         notifyViewAccessibilityStateChangedIfNeeded(
7359                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7360     }
7361 
7362     /**
7363      * Gets the id of a view after which this one is visited in accessibility traversal.
7364      *
7365      * @return The id of a view this one succeedes in accessibility traversal if
7366      *         specified, otherwise {@link #NO_ID}.
7367      *
7368      * @see #setAccessibilityTraversalAfter(int)
7369      */
getAccessibilityTraversalAfter()7370     public int getAccessibilityTraversalAfter() {
7371         return mAccessibilityTraversalAfterId;
7372     }
7373 
7374     /**
7375      * Gets the id of a view for which this view serves as a label for
7376      * accessibility purposes.
7377      *
7378      * @return The labeled view id.
7379      */
7380     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()7381     public int getLabelFor() {
7382         return mLabelForId;
7383     }
7384 
7385     /**
7386      * Sets the id of a view for which this view serves as a label for
7387      * accessibility purposes.
7388      *
7389      * @param id The labeled view id.
7390      */
7391     @RemotableViewMethod
setLabelFor(@dRes int id)7392     public void setLabelFor(@IdRes int id) {
7393         if (mLabelForId == id) {
7394             return;
7395         }
7396         mLabelForId = id;
7397         if (mLabelForId != View.NO_ID
7398                 && mID == View.NO_ID) {
7399             mID = generateViewId();
7400         }
7401         notifyViewAccessibilityStateChangedIfNeeded(
7402                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7403     }
7404 
7405     /**
7406      * Invoked whenever this view loses focus, either by losing window focus or by losing
7407      * focus within its window. This method can be used to clear any state tied to the
7408      * focus. For instance, if a button is held pressed with the trackball and the window
7409      * loses focus, this method can be used to cancel the press.
7410      *
7411      * Subclasses of View overriding this method should always call super.onFocusLost().
7412      *
7413      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7414      * @see #onWindowFocusChanged(boolean)
7415      *
7416      * @hide pending API council approval
7417      */
7418     @CallSuper
onFocusLost()7419     protected void onFocusLost() {
7420         resetPressedState();
7421     }
7422 
resetPressedState()7423     private void resetPressedState() {
7424         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7425             return;
7426         }
7427 
7428         if (isPressed()) {
7429             setPressed(false);
7430 
7431             if (!mHasPerformedLongPress) {
7432                 removeLongPressCallback();
7433             }
7434         }
7435     }
7436 
7437     /**
7438      * Returns true if this view has focus
7439      *
7440      * @return True if this view has focus, false otherwise.
7441      */
7442     @ViewDebug.ExportedProperty(category = "focus")
isFocused()7443     public boolean isFocused() {
7444         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7445     }
7446 
7447     /**
7448      * Find the view in the hierarchy rooted at this view that currently has
7449      * focus.
7450      *
7451      * @return The view that currently has focus, or null if no focused view can
7452      *         be found.
7453      */
findFocus()7454     public View findFocus() {
7455         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7456     }
7457 
7458     /**
7459      * Indicates whether this view is one of the set of scrollable containers in
7460      * its window.
7461      *
7462      * @return whether this view is one of the set of scrollable containers in
7463      * its window
7464      *
7465      * @attr ref android.R.styleable#View_isScrollContainer
7466      */
isScrollContainer()7467     public boolean isScrollContainer() {
7468         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7469     }
7470 
7471     /**
7472      * Change whether this view is one of the set of scrollable containers in
7473      * its window.  This will be used to determine whether the window can
7474      * resize or must pan when a soft input area is open -- scrollable
7475      * containers allow the window to use resize mode since the container
7476      * will appropriately shrink.
7477      *
7478      * @attr ref android.R.styleable#View_isScrollContainer
7479      */
setScrollContainer(boolean isScrollContainer)7480     public void setScrollContainer(boolean isScrollContainer) {
7481         if (isScrollContainer) {
7482             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7483                 mAttachInfo.mScrollContainers.add(this);
7484                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7485             }
7486             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7487         } else {
7488             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7489                 mAttachInfo.mScrollContainers.remove(this);
7490             }
7491             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7492         }
7493     }
7494 
7495     /**
7496      * Returns the quality of the drawing cache.
7497      *
7498      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7499      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7500      *
7501      * @see #setDrawingCacheQuality(int)
7502      * @see #setDrawingCacheEnabled(boolean)
7503      * @see #isDrawingCacheEnabled()
7504      *
7505      * @attr ref android.R.styleable#View_drawingCacheQuality
7506      */
7507     @DrawingCacheQuality
getDrawingCacheQuality()7508     public int getDrawingCacheQuality() {
7509         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7510     }
7511 
7512     /**
7513      * Set the drawing cache quality of this view. This value is used only when the
7514      * drawing cache is enabled
7515      *
7516      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7517      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7518      *
7519      * @see #getDrawingCacheQuality()
7520      * @see #setDrawingCacheEnabled(boolean)
7521      * @see #isDrawingCacheEnabled()
7522      *
7523      * @attr ref android.R.styleable#View_drawingCacheQuality
7524      */
setDrawingCacheQuality(@rawingCacheQuality int quality)7525     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7526         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7527     }
7528 
7529     /**
7530      * Returns whether the screen should remain on, corresponding to the current
7531      * value of {@link #KEEP_SCREEN_ON}.
7532      *
7533      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7534      *
7535      * @see #setKeepScreenOn(boolean)
7536      *
7537      * @attr ref android.R.styleable#View_keepScreenOn
7538      */
getKeepScreenOn()7539     public boolean getKeepScreenOn() {
7540         return (mViewFlags & KEEP_SCREEN_ON) != 0;
7541     }
7542 
7543     /**
7544      * Controls whether the screen should remain on, modifying the
7545      * value of {@link #KEEP_SCREEN_ON}.
7546      *
7547      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7548      *
7549      * @see #getKeepScreenOn()
7550      *
7551      * @attr ref android.R.styleable#View_keepScreenOn
7552      */
setKeepScreenOn(boolean keepScreenOn)7553     public void setKeepScreenOn(boolean keepScreenOn) {
7554         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7555     }
7556 
7557     /**
7558      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7559      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7560      *
7561      * @attr ref android.R.styleable#View_nextFocusLeft
7562      */
getNextFocusLeftId()7563     public int getNextFocusLeftId() {
7564         return mNextFocusLeftId;
7565     }
7566 
7567     /**
7568      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7569      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7570      * decide automatically.
7571      *
7572      * @attr ref android.R.styleable#View_nextFocusLeft
7573      */
setNextFocusLeftId(int nextFocusLeftId)7574     public void setNextFocusLeftId(int nextFocusLeftId) {
7575         mNextFocusLeftId = nextFocusLeftId;
7576     }
7577 
7578     /**
7579      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7580      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7581      *
7582      * @attr ref android.R.styleable#View_nextFocusRight
7583      */
getNextFocusRightId()7584     public int getNextFocusRightId() {
7585         return mNextFocusRightId;
7586     }
7587 
7588     /**
7589      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7590      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7591      * decide automatically.
7592      *
7593      * @attr ref android.R.styleable#View_nextFocusRight
7594      */
setNextFocusRightId(int nextFocusRightId)7595     public void setNextFocusRightId(int nextFocusRightId) {
7596         mNextFocusRightId = nextFocusRightId;
7597     }
7598 
7599     /**
7600      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7601      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7602      *
7603      * @attr ref android.R.styleable#View_nextFocusUp
7604      */
getNextFocusUpId()7605     public int getNextFocusUpId() {
7606         return mNextFocusUpId;
7607     }
7608 
7609     /**
7610      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7611      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7612      * decide automatically.
7613      *
7614      * @attr ref android.R.styleable#View_nextFocusUp
7615      */
setNextFocusUpId(int nextFocusUpId)7616     public void setNextFocusUpId(int nextFocusUpId) {
7617         mNextFocusUpId = nextFocusUpId;
7618     }
7619 
7620     /**
7621      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7622      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7623      *
7624      * @attr ref android.R.styleable#View_nextFocusDown
7625      */
getNextFocusDownId()7626     public int getNextFocusDownId() {
7627         return mNextFocusDownId;
7628     }
7629 
7630     /**
7631      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7632      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7633      * decide automatically.
7634      *
7635      * @attr ref android.R.styleable#View_nextFocusDown
7636      */
setNextFocusDownId(int nextFocusDownId)7637     public void setNextFocusDownId(int nextFocusDownId) {
7638         mNextFocusDownId = nextFocusDownId;
7639     }
7640 
7641     /**
7642      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7643      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7644      *
7645      * @attr ref android.R.styleable#View_nextFocusForward
7646      */
getNextFocusForwardId()7647     public int getNextFocusForwardId() {
7648         return mNextFocusForwardId;
7649     }
7650 
7651     /**
7652      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7653      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7654      * decide automatically.
7655      *
7656      * @attr ref android.R.styleable#View_nextFocusForward
7657      */
setNextFocusForwardId(int nextFocusForwardId)7658     public void setNextFocusForwardId(int nextFocusForwardId) {
7659         mNextFocusForwardId = nextFocusForwardId;
7660     }
7661 
7662     /**
7663      * Returns the visibility of this view and all of its ancestors
7664      *
7665      * @return True if this view and all of its ancestors are {@link #VISIBLE}
7666      */
isShown()7667     public boolean isShown() {
7668         View current = this;
7669         //noinspection ConstantConditions
7670         do {
7671             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7672                 return false;
7673             }
7674             ViewParent parent = current.mParent;
7675             if (parent == null) {
7676                 return false; // We are not attached to the view root
7677             }
7678             if (!(parent instanceof View)) {
7679                 return true;
7680             }
7681             current = (View) parent;
7682         } while (current != null);
7683 
7684         return false;
7685     }
7686 
7687     /**
7688      * Called by the view hierarchy when the content insets for a window have
7689      * changed, to allow it to adjust its content to fit within those windows.
7690      * The content insets tell you the space that the status bar, input method,
7691      * and other system windows infringe on the application's window.
7692      *
7693      * <p>You do not normally need to deal with this function, since the default
7694      * window decoration given to applications takes care of applying it to the
7695      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7696      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7697      * and your content can be placed under those system elements.  You can then
7698      * use this method within your view hierarchy if you have parts of your UI
7699      * which you would like to ensure are not being covered.
7700      *
7701      * <p>The default implementation of this method simply applies the content
7702      * insets to the view's padding, consuming that content (modifying the
7703      * insets to be 0), and returning true.  This behavior is off by default, but can
7704      * be enabled through {@link #setFitsSystemWindows(boolean)}.
7705      *
7706      * <p>This function's traversal down the hierarchy is depth-first.  The same content
7707      * insets object is propagated down the hierarchy, so any changes made to it will
7708      * be seen by all following views (including potentially ones above in
7709      * the hierarchy since this is a depth-first traversal).  The first view
7710      * that returns true will abort the entire traversal.
7711      *
7712      * <p>The default implementation works well for a situation where it is
7713      * used with a container that covers the entire window, allowing it to
7714      * apply the appropriate insets to its content on all edges.  If you need
7715      * a more complicated layout (such as two different views fitting system
7716      * windows, one on the top of the window, and one on the bottom),
7717      * you can override the method and handle the insets however you would like.
7718      * Note that the insets provided by the framework are always relative to the
7719      * far edges of the window, not accounting for the location of the called view
7720      * within that window.  (In fact when this method is called you do not yet know
7721      * where the layout will place the view, as it is done before layout happens.)
7722      *
7723      * <p>Note: unlike many View methods, there is no dispatch phase to this
7724      * call.  If you are overriding it in a ViewGroup and want to allow the
7725      * call to continue to your children, you must be sure to call the super
7726      * implementation.
7727      *
7728      * <p>Here is a sample layout that makes use of fitting system windows
7729      * to have controls for a video view placed inside of the window decorations
7730      * that it hides and shows.  This can be used with code like the second
7731      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7732      *
7733      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7734      *
7735      * @param insets Current content insets of the window.  Prior to
7736      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7737      * the insets or else you and Android will be unhappy.
7738      *
7739      * @return {@code true} if this view applied the insets and it should not
7740      * continue propagating further down the hierarchy, {@code false} otherwise.
7741      * @see #getFitsSystemWindows()
7742      * @see #setFitsSystemWindows(boolean)
7743      * @see #setSystemUiVisibility(int)
7744      *
7745      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7746      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7747      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7748      * to implement handling their own insets.
7749      */
fitSystemWindows(Rect insets)7750     protected boolean fitSystemWindows(Rect insets) {
7751         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7752             if (insets == null) {
7753                 // Null insets by definition have already been consumed.
7754                 // This call cannot apply insets since there are none to apply,
7755                 // so return false.
7756                 return false;
7757             }
7758             // If we're not in the process of dispatching the newer apply insets call,
7759             // that means we're not in the compatibility path. Dispatch into the newer
7760             // apply insets path and take things from there.
7761             try {
7762                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7763                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7764             } finally {
7765                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7766             }
7767         } else {
7768             // We're being called from the newer apply insets path.
7769             // Perform the standard fallback behavior.
7770             return fitSystemWindowsInt(insets);
7771         }
7772     }
7773 
fitSystemWindowsInt(Rect insets)7774     private boolean fitSystemWindowsInt(Rect insets) {
7775         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7776             mUserPaddingStart = UNDEFINED_PADDING;
7777             mUserPaddingEnd = UNDEFINED_PADDING;
7778             Rect localInsets = sThreadLocal.get();
7779             if (localInsets == null) {
7780                 localInsets = new Rect();
7781                 sThreadLocal.set(localInsets);
7782             }
7783             boolean res = computeFitSystemWindows(insets, localInsets);
7784             mUserPaddingLeftInitial = localInsets.left;
7785             mUserPaddingRightInitial = localInsets.right;
7786             internalSetPadding(localInsets.left, localInsets.top,
7787                     localInsets.right, localInsets.bottom);
7788             return res;
7789         }
7790         return false;
7791     }
7792 
7793     /**
7794      * Called when the view should apply {@link WindowInsets} according to its internal policy.
7795      *
7796      * <p>This method should be overridden by views that wish to apply a policy different from or
7797      * in addition to the default behavior. Clients that wish to force a view subtree
7798      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7799      *
7800      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7801      * it will be called during dispatch instead of this method. The listener may optionally
7802      * call this method from its own implementation if it wishes to apply the view's default
7803      * insets policy in addition to its own.</p>
7804      *
7805      * <p>Implementations of this method should either return the insets parameter unchanged
7806      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7807      * that this view applied itself. This allows new inset types added in future platform
7808      * versions to pass through existing implementations unchanged without being erroneously
7809      * consumed.</p>
7810      *
7811      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7812      * property is set then the view will consume the system window insets and apply them
7813      * as padding for the view.</p>
7814      *
7815      * @param insets Insets to apply
7816      * @return The supplied insets with any applied insets consumed
7817      */
onApplyWindowInsets(WindowInsets insets)7818     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7819         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7820             // We weren't called from within a direct call to fitSystemWindows,
7821             // call into it as a fallback in case we're in a class that overrides it
7822             // and has logic to perform.
7823             if (fitSystemWindows(insets.getSystemWindowInsets())) {
7824                 return insets.consumeSystemWindowInsets();
7825             }
7826         } else {
7827             // We were called from within a direct call to fitSystemWindows.
7828             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7829                 return insets.consumeSystemWindowInsets();
7830             }
7831         }
7832         return insets;
7833     }
7834 
7835     /**
7836      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7837      * window insets to this view. The listener's
7838      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7839      * method will be called instead of the view's
7840      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7841      *
7842      * @param listener Listener to set
7843      *
7844      * @see #onApplyWindowInsets(WindowInsets)
7845      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)7846     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7847         getListenerInfo().mOnApplyWindowInsetsListener = listener;
7848     }
7849 
7850     /**
7851      * Request to apply the given window insets to this view or another view in its subtree.
7852      *
7853      * <p>This method should be called by clients wishing to apply insets corresponding to areas
7854      * obscured by window decorations or overlays. This can include the status and navigation bars,
7855      * action bars, input methods and more. New inset categories may be added in the future.
7856      * The method returns the insets provided minus any that were applied by this view or its
7857      * children.</p>
7858      *
7859      * <p>Clients wishing to provide custom behavior should override the
7860      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7861      * {@link OnApplyWindowInsetsListener} via the
7862      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7863      * method.</p>
7864      *
7865      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7866      * </p>
7867      *
7868      * @param insets Insets to apply
7869      * @return The provided insets minus the insets that were consumed
7870      */
dispatchApplyWindowInsets(WindowInsets insets)7871     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7872         try {
7873             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7874             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7875                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7876             } else {
7877                 return onApplyWindowInsets(insets);
7878             }
7879         } finally {
7880             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7881         }
7882     }
7883 
7884     /**
7885      * Compute the view's coordinate within the surface.
7886      *
7887      * <p>Computes the coordinates of this view in its surface. The argument
7888      * must be an array of two integers. After the method returns, the array
7889      * contains the x and y location in that order.</p>
7890      * @hide
7891      * @param location an array of two integers in which to hold the coordinates
7892      */
getLocationInSurface(@ize2) int[] location)7893     public void getLocationInSurface(@Size(2) int[] location) {
7894         getLocationInWindow(location);
7895         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7896             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7897             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7898         }
7899     }
7900 
7901     /**
7902      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7903      * only available if the view is attached.
7904      *
7905      * @return WindowInsets from the top of the view hierarchy or null if View is detached
7906      */
getRootWindowInsets()7907     public WindowInsets getRootWindowInsets() {
7908         if (mAttachInfo != null) {
7909             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7910         }
7911         return null;
7912     }
7913 
7914     /**
7915      * @hide Compute the insets that should be consumed by this view and the ones
7916      * that should propagate to those under it.
7917      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)7918     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7919         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7920                 || mAttachInfo == null
7921                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7922                         && !mAttachInfo.mOverscanRequested)) {
7923             outLocalInsets.set(inoutInsets);
7924             inoutInsets.set(0, 0, 0, 0);
7925             return true;
7926         } else {
7927             // The application wants to take care of fitting system window for
7928             // the content...  however we still need to take care of any overscan here.
7929             final Rect overscan = mAttachInfo.mOverscanInsets;
7930             outLocalInsets.set(overscan);
7931             inoutInsets.left -= overscan.left;
7932             inoutInsets.top -= overscan.top;
7933             inoutInsets.right -= overscan.right;
7934             inoutInsets.bottom -= overscan.bottom;
7935             return false;
7936         }
7937     }
7938 
7939     /**
7940      * Compute insets that should be consumed by this view and the ones that should propagate
7941      * to those under it.
7942      *
7943      * @param in Insets currently being processed by this View, likely received as a parameter
7944      *           to {@link #onApplyWindowInsets(WindowInsets)}.
7945      * @param outLocalInsets A Rect that will receive the insets that should be consumed
7946      *                       by this view
7947      * @return Insets that should be passed along to views under this one
7948      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)7949     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7950         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7951                 || mAttachInfo == null
7952                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7953             outLocalInsets.set(in.getSystemWindowInsets());
7954             return in.consumeSystemWindowInsets();
7955         } else {
7956             outLocalInsets.set(0, 0, 0, 0);
7957             return in;
7958         }
7959     }
7960 
7961     /**
7962      * Sets whether or not this view should account for system screen decorations
7963      * such as the status bar and inset its content; that is, controlling whether
7964      * the default implementation of {@link #fitSystemWindows(Rect)} will be
7965      * executed.  See that method for more details.
7966      *
7967      * <p>Note that if you are providing your own implementation of
7968      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7969      * flag to true -- your implementation will be overriding the default
7970      * implementation that checks this flag.
7971      *
7972      * @param fitSystemWindows If true, then the default implementation of
7973      * {@link #fitSystemWindows(Rect)} will be executed.
7974      *
7975      * @attr ref android.R.styleable#View_fitsSystemWindows
7976      * @see #getFitsSystemWindows()
7977      * @see #fitSystemWindows(Rect)
7978      * @see #setSystemUiVisibility(int)
7979      */
setFitsSystemWindows(boolean fitSystemWindows)7980     public void setFitsSystemWindows(boolean fitSystemWindows) {
7981         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7982     }
7983 
7984     /**
7985      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7986      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7987      * will be executed.
7988      *
7989      * @return {@code true} if the default implementation of
7990      * {@link #fitSystemWindows(Rect)} will be executed.
7991      *
7992      * @attr ref android.R.styleable#View_fitsSystemWindows
7993      * @see #setFitsSystemWindows(boolean)
7994      * @see #fitSystemWindows(Rect)
7995      * @see #setSystemUiVisibility(int)
7996      */
7997     @ViewDebug.ExportedProperty
getFitsSystemWindows()7998     public boolean getFitsSystemWindows() {
7999         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8000     }
8001 
8002     /** @hide */
fitsSystemWindows()8003     public boolean fitsSystemWindows() {
8004         return getFitsSystemWindows();
8005     }
8006 
8007     /**
8008      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8009      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8010      */
requestFitSystemWindows()8011     public void requestFitSystemWindows() {
8012         if (mParent != null) {
8013             mParent.requestFitSystemWindows();
8014         }
8015     }
8016 
8017     /**
8018      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8019      */
requestApplyInsets()8020     public void requestApplyInsets() {
8021         requestFitSystemWindows();
8022     }
8023 
8024     /**
8025      * For use by PhoneWindow to make its own system window fitting optional.
8026      * @hide
8027      */
makeOptionalFitsSystemWindows()8028     public void makeOptionalFitsSystemWindows() {
8029         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8030     }
8031 
8032     /**
8033      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8034      * treat them as such.
8035      * @hide
8036      */
getOutsets(Rect outOutsetRect)8037     public void getOutsets(Rect outOutsetRect) {
8038         if (mAttachInfo != null) {
8039             outOutsetRect.set(mAttachInfo.mOutsets);
8040         } else {
8041             outOutsetRect.setEmpty();
8042         }
8043     }
8044 
8045     /**
8046      * Returns the visibility status for this view.
8047      *
8048      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8049      * @attr ref android.R.styleable#View_visibility
8050      */
8051     @ViewDebug.ExportedProperty(mapping = {
8052         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8053         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8054         @ViewDebug.IntToString(from = GONE,      to = "GONE")
8055     })
8056     @Visibility
getVisibility()8057     public int getVisibility() {
8058         return mViewFlags & VISIBILITY_MASK;
8059     }
8060 
8061     /**
8062      * Set the visibility state of this view.
8063      *
8064      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8065      * @attr ref android.R.styleable#View_visibility
8066      */
8067     @RemotableViewMethod
setVisibility(@isibility int visibility)8068     public void setVisibility(@Visibility int visibility) {
8069         setFlags(visibility, VISIBILITY_MASK);
8070     }
8071 
8072     /**
8073      * Returns the enabled status for this view. The interpretation of the
8074      * enabled state varies by subclass.
8075      *
8076      * @return True if this view is enabled, false otherwise.
8077      */
8078     @ViewDebug.ExportedProperty
isEnabled()8079     public boolean isEnabled() {
8080         return (mViewFlags & ENABLED_MASK) == ENABLED;
8081     }
8082 
8083     /**
8084      * Set the enabled state of this view. The interpretation of the enabled
8085      * state varies by subclass.
8086      *
8087      * @param enabled True if this view is enabled, false otherwise.
8088      */
8089     @RemotableViewMethod
setEnabled(boolean enabled)8090     public void setEnabled(boolean enabled) {
8091         if (enabled == isEnabled()) return;
8092 
8093         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8094 
8095         /*
8096          * The View most likely has to change its appearance, so refresh
8097          * the drawable state.
8098          */
8099         refreshDrawableState();
8100 
8101         // Invalidate too, since the default behavior for views is to be
8102         // be drawn at 50% alpha rather than to change the drawable.
8103         invalidate(true);
8104 
8105         if (!enabled) {
8106             cancelPendingInputEvents();
8107         }
8108     }
8109 
8110     /**
8111      * Set whether this view can receive the focus.
8112      *
8113      * Setting this to false will also ensure that this view is not focusable
8114      * in touch mode.
8115      *
8116      * @param focusable If true, this view can receive the focus.
8117      *
8118      * @see #setFocusableInTouchMode(boolean)
8119      * @attr ref android.R.styleable#View_focusable
8120      */
setFocusable(boolean focusable)8121     public void setFocusable(boolean focusable) {
8122         if (!focusable) {
8123             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8124         }
8125         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8126     }
8127 
8128     /**
8129      * Set whether this view can receive focus while in touch mode.
8130      *
8131      * Setting this to true will also ensure that this view is focusable.
8132      *
8133      * @param focusableInTouchMode If true, this view can receive the focus while
8134      *   in touch mode.
8135      *
8136      * @see #setFocusable(boolean)
8137      * @attr ref android.R.styleable#View_focusableInTouchMode
8138      */
setFocusableInTouchMode(boolean focusableInTouchMode)8139     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8140         // Focusable in touch mode should always be set before the focusable flag
8141         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8142         // which, in touch mode, will not successfully request focus on this view
8143         // because the focusable in touch mode flag is not set
8144         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8145         if (focusableInTouchMode) {
8146             setFlags(FOCUSABLE, FOCUSABLE_MASK);
8147         }
8148     }
8149 
8150     /**
8151      * Set whether this view should have sound effects enabled for events such as
8152      * clicking and touching.
8153      *
8154      * <p>You may wish to disable sound effects for a view if you already play sounds,
8155      * for instance, a dial key that plays dtmf tones.
8156      *
8157      * @param soundEffectsEnabled whether sound effects are enabled for this view.
8158      * @see #isSoundEffectsEnabled()
8159      * @see #playSoundEffect(int)
8160      * @attr ref android.R.styleable#View_soundEffectsEnabled
8161      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)8162     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8163         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8164     }
8165 
8166     /**
8167      * @return whether this view should have sound effects enabled for events such as
8168      *     clicking and touching.
8169      *
8170      * @see #setSoundEffectsEnabled(boolean)
8171      * @see #playSoundEffect(int)
8172      * @attr ref android.R.styleable#View_soundEffectsEnabled
8173      */
8174     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()8175     public boolean isSoundEffectsEnabled() {
8176         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8177     }
8178 
8179     /**
8180      * Set whether this view should have haptic feedback for events such as
8181      * long presses.
8182      *
8183      * <p>You may wish to disable haptic feedback if your view already controls
8184      * its own haptic feedback.
8185      *
8186      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8187      * @see #isHapticFeedbackEnabled()
8188      * @see #performHapticFeedback(int)
8189      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8190      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)8191     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8192         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8193     }
8194 
8195     /**
8196      * @return whether this view should have haptic feedback enabled for events
8197      * long presses.
8198      *
8199      * @see #setHapticFeedbackEnabled(boolean)
8200      * @see #performHapticFeedback(int)
8201      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8202      */
8203     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()8204     public boolean isHapticFeedbackEnabled() {
8205         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8206     }
8207 
8208     /**
8209      * Returns the layout direction for this view.
8210      *
8211      * @return One of {@link #LAYOUT_DIRECTION_LTR},
8212      *   {@link #LAYOUT_DIRECTION_RTL},
8213      *   {@link #LAYOUT_DIRECTION_INHERIT} or
8214      *   {@link #LAYOUT_DIRECTION_LOCALE}.
8215      *
8216      * @attr ref android.R.styleable#View_layoutDirection
8217      *
8218      * @hide
8219      */
8220     @ViewDebug.ExportedProperty(category = "layout", mapping = {
8221         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8222         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8223         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8224         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8225     })
8226     @LayoutDir
getRawLayoutDirection()8227     public int getRawLayoutDirection() {
8228         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8229     }
8230 
8231     /**
8232      * Set the layout direction for this view. This will propagate a reset of layout direction
8233      * resolution to the view's children and resolve layout direction for this view.
8234      *
8235      * @param layoutDirection the layout direction to set. Should be one of:
8236      *
8237      * {@link #LAYOUT_DIRECTION_LTR},
8238      * {@link #LAYOUT_DIRECTION_RTL},
8239      * {@link #LAYOUT_DIRECTION_INHERIT},
8240      * {@link #LAYOUT_DIRECTION_LOCALE}.
8241      *
8242      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8243      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8244      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8245      *
8246      * @attr ref android.R.styleable#View_layoutDirection
8247      */
8248     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)8249     public void setLayoutDirection(@LayoutDir int layoutDirection) {
8250         if (getRawLayoutDirection() != layoutDirection) {
8251             // Reset the current layout direction and the resolved one
8252             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8253             resetRtlProperties();
8254             // Set the new layout direction (filtered)
8255             mPrivateFlags2 |=
8256                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8257             // We need to resolve all RTL properties as they all depend on layout direction
8258             resolveRtlPropertiesIfNeeded();
8259             requestLayout();
8260             invalidate(true);
8261         }
8262     }
8263 
8264     /**
8265      * Returns the resolved layout direction for this view.
8266      *
8267      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8268      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8269      *
8270      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8271      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8272      *
8273      * @attr ref android.R.styleable#View_layoutDirection
8274      */
8275     @ViewDebug.ExportedProperty(category = "layout", mapping = {
8276         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8277         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8278     })
8279     @ResolvedLayoutDir
getLayoutDirection()8280     public int getLayoutDirection() {
8281         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8282         if (targetSdkVersion < JELLY_BEAN_MR1) {
8283             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8284             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8285         }
8286         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8287                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8288     }
8289 
8290     /**
8291      * Indicates whether or not this view's layout is right-to-left. This is resolved from
8292      * layout attribute and/or the inherited value from the parent
8293      *
8294      * @return true if the layout is right-to-left.
8295      *
8296      * @hide
8297      */
8298     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()8299     public boolean isLayoutRtl() {
8300         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8301     }
8302 
8303     /**
8304      * Indicates whether the view is currently tracking transient state that the
8305      * app should not need to concern itself with saving and restoring, but that
8306      * the framework should take special note to preserve when possible.
8307      *
8308      * <p>A view with transient state cannot be trivially rebound from an external
8309      * data source, such as an adapter binding item views in a list. This may be
8310      * because the view is performing an animation, tracking user selection
8311      * of content, or similar.</p>
8312      *
8313      * @return true if the view has transient state
8314      */
8315     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()8316     public boolean hasTransientState() {
8317         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8318     }
8319 
8320     /**
8321      * Set whether this view is currently tracking transient state that the
8322      * framework should attempt to preserve when possible. This flag is reference counted,
8323      * so every call to setHasTransientState(true) should be paired with a later call
8324      * to setHasTransientState(false).
8325      *
8326      * <p>A view with transient state cannot be trivially rebound from an external
8327      * data source, such as an adapter binding item views in a list. This may be
8328      * because the view is performing an animation, tracking user selection
8329      * of content, or similar.</p>
8330      *
8331      * @param hasTransientState true if this view has transient state
8332      */
setHasTransientState(boolean hasTransientState)8333     public void setHasTransientState(boolean hasTransientState) {
8334         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8335                 mTransientStateCount - 1;
8336         if (mTransientStateCount < 0) {
8337             mTransientStateCount = 0;
8338             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8339                     "unmatched pair of setHasTransientState calls");
8340         } else if ((hasTransientState && mTransientStateCount == 1) ||
8341                 (!hasTransientState && mTransientStateCount == 0)) {
8342             // update flag if we've just incremented up from 0 or decremented down to 0
8343             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8344                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8345             if (mParent != null) {
8346                 try {
8347                     mParent.childHasTransientStateChanged(this, hasTransientState);
8348                 } catch (AbstractMethodError e) {
8349                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8350                             " does not fully implement ViewParent", e);
8351                 }
8352             }
8353         }
8354     }
8355 
8356     /**
8357      * Returns true if this view is currently attached to a window.
8358      */
isAttachedToWindow()8359     public boolean isAttachedToWindow() {
8360         return mAttachInfo != null;
8361     }
8362 
8363     /**
8364      * Returns true if this view has been through at least one layout since it
8365      * was last attached to or detached from a window.
8366      */
isLaidOut()8367     public boolean isLaidOut() {
8368         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8369     }
8370 
8371     /**
8372      * If this view doesn't do any drawing on its own, set this flag to
8373      * allow further optimizations. By default, this flag is not set on
8374      * View, but could be set on some View subclasses such as ViewGroup.
8375      *
8376      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8377      * you should clear this flag.
8378      *
8379      * @param willNotDraw whether or not this View draw on its own
8380      */
setWillNotDraw(boolean willNotDraw)8381     public void setWillNotDraw(boolean willNotDraw) {
8382         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8383     }
8384 
8385     /**
8386      * Returns whether or not this View draws on its own.
8387      *
8388      * @return true if this view has nothing to draw, false otherwise
8389      */
8390     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()8391     public boolean willNotDraw() {
8392         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8393     }
8394 
8395     /**
8396      * When a View's drawing cache is enabled, drawing is redirected to an
8397      * offscreen bitmap. Some views, like an ImageView, must be able to
8398      * bypass this mechanism if they already draw a single bitmap, to avoid
8399      * unnecessary usage of the memory.
8400      *
8401      * @param willNotCacheDrawing true if this view does not cache its
8402      *        drawing, false otherwise
8403      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)8404     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8405         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8406     }
8407 
8408     /**
8409      * Returns whether or not this View can cache its drawing or not.
8410      *
8411      * @return true if this view does not cache its drawing, false otherwise
8412      */
8413     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()8414     public boolean willNotCacheDrawing() {
8415         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8416     }
8417 
8418     /**
8419      * Indicates whether this view reacts to click events or not.
8420      *
8421      * @return true if the view is clickable, false otherwise
8422      *
8423      * @see #setClickable(boolean)
8424      * @attr ref android.R.styleable#View_clickable
8425      */
8426     @ViewDebug.ExportedProperty
isClickable()8427     public boolean isClickable() {
8428         return (mViewFlags & CLICKABLE) == CLICKABLE;
8429     }
8430 
8431     /**
8432      * Enables or disables click events for this view. When a view
8433      * is clickable it will change its state to "pressed" on every click.
8434      * Subclasses should set the view clickable to visually react to
8435      * user's clicks.
8436      *
8437      * @param clickable true to make the view clickable, false otherwise
8438      *
8439      * @see #isClickable()
8440      * @attr ref android.R.styleable#View_clickable
8441      */
setClickable(boolean clickable)8442     public void setClickable(boolean clickable) {
8443         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8444     }
8445 
8446     /**
8447      * Indicates whether this view reacts to long click events or not.
8448      *
8449      * @return true if the view is long clickable, false otherwise
8450      *
8451      * @see #setLongClickable(boolean)
8452      * @attr ref android.R.styleable#View_longClickable
8453      */
isLongClickable()8454     public boolean isLongClickable() {
8455         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8456     }
8457 
8458     /**
8459      * Enables or disables long click events for this view. When a view is long
8460      * clickable it reacts to the user holding down the button for a longer
8461      * duration than a tap. This event can either launch the listener or a
8462      * context menu.
8463      *
8464      * @param longClickable true to make the view long clickable, false otherwise
8465      * @see #isLongClickable()
8466      * @attr ref android.R.styleable#View_longClickable
8467      */
setLongClickable(boolean longClickable)8468     public void setLongClickable(boolean longClickable) {
8469         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8470     }
8471 
8472     /**
8473      * Indicates whether this view reacts to context clicks or not.
8474      *
8475      * @return true if the view is context clickable, false otherwise
8476      * @see #setContextClickable(boolean)
8477      * @attr ref android.R.styleable#View_contextClickable
8478      */
isContextClickable()8479     public boolean isContextClickable() {
8480         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8481     }
8482 
8483     /**
8484      * Enables or disables context clicking for this view. This event can launch the listener.
8485      *
8486      * @param contextClickable true to make the view react to a context click, false otherwise
8487      * @see #isContextClickable()
8488      * @attr ref android.R.styleable#View_contextClickable
8489      */
setContextClickable(boolean contextClickable)8490     public void setContextClickable(boolean contextClickable) {
8491         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8492     }
8493 
8494     /**
8495      * Sets the pressed state for this view and provides a touch coordinate for
8496      * animation hinting.
8497      *
8498      * @param pressed Pass true to set the View's internal state to "pressed",
8499      *            or false to reverts the View's internal state from a
8500      *            previously set "pressed" state.
8501      * @param x The x coordinate of the touch that caused the press
8502      * @param y The y coordinate of the touch that caused the press
8503      */
setPressed(boolean pressed, float x, float y)8504     private void setPressed(boolean pressed, float x, float y) {
8505         if (pressed) {
8506             drawableHotspotChanged(x, y);
8507         }
8508 
8509         setPressed(pressed);
8510     }
8511 
8512     /**
8513      * Sets the pressed state for this view.
8514      *
8515      * @see #isClickable()
8516      * @see #setClickable(boolean)
8517      *
8518      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8519      *        the View's internal state from a previously set "pressed" state.
8520      */
setPressed(boolean pressed)8521     public void setPressed(boolean pressed) {
8522         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8523 
8524         if (pressed) {
8525             mPrivateFlags |= PFLAG_PRESSED;
8526         } else {
8527             mPrivateFlags &= ~PFLAG_PRESSED;
8528         }
8529 
8530         if (needsRefresh) {
8531             refreshDrawableState();
8532         }
8533         dispatchSetPressed(pressed);
8534     }
8535 
8536     /**
8537      * Dispatch setPressed to all of this View's children.
8538      *
8539      * @see #setPressed(boolean)
8540      *
8541      * @param pressed The new pressed state
8542      */
dispatchSetPressed(boolean pressed)8543     protected void dispatchSetPressed(boolean pressed) {
8544     }
8545 
8546     /**
8547      * Indicates whether the view is currently in pressed state. Unless
8548      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8549      * the pressed state.
8550      *
8551      * @see #setPressed(boolean)
8552      * @see #isClickable()
8553      * @see #setClickable(boolean)
8554      *
8555      * @return true if the view is currently pressed, false otherwise
8556      */
8557     @ViewDebug.ExportedProperty
isPressed()8558     public boolean isPressed() {
8559         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8560     }
8561 
8562     /**
8563      * @hide
8564      * Indicates whether this view will participate in data collection through
8565      * {@link ViewStructure}.  If true, it will not provide any data
8566      * for itself or its children.  If false, the normal data collection will be allowed.
8567      *
8568      * @return Returns false if assist data collection is not blocked, else true.
8569      *
8570      * @see #setAssistBlocked(boolean)
8571      * @attr ref android.R.styleable#View_assistBlocked
8572      */
isAssistBlocked()8573     public boolean isAssistBlocked() {
8574         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8575     }
8576 
8577     /**
8578      * @hide
8579      * Controls whether assist data collection from this view and its children is enabled
8580      * (that is, whether {@link #onProvideStructure} and
8581      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8582      * allowing normal assist collection.  Setting this to false will disable assist collection.
8583      *
8584      * @param enabled Set to true to <em>disable</em> assist data collection, or false
8585      * (the default) to allow it.
8586      *
8587      * @see #isAssistBlocked()
8588      * @see #onProvideStructure
8589      * @see #onProvideVirtualStructure
8590      * @attr ref android.R.styleable#View_assistBlocked
8591      */
setAssistBlocked(boolean enabled)8592     public void setAssistBlocked(boolean enabled) {
8593         if (enabled) {
8594             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8595         } else {
8596             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8597         }
8598     }
8599 
8600     /**
8601      * Indicates whether this view will save its state (that is,
8602      * whether its {@link #onSaveInstanceState} method will be called).
8603      *
8604      * @return Returns true if the view state saving is enabled, else false.
8605      *
8606      * @see #setSaveEnabled(boolean)
8607      * @attr ref android.R.styleable#View_saveEnabled
8608      */
isSaveEnabled()8609     public boolean isSaveEnabled() {
8610         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8611     }
8612 
8613     /**
8614      * Controls whether the saving of this view's state is
8615      * enabled (that is, whether its {@link #onSaveInstanceState} method
8616      * will be called).  Note that even if freezing is enabled, the
8617      * view still must have an id assigned to it (via {@link #setId(int)})
8618      * for its state to be saved.  This flag can only disable the
8619      * saving of this view; any child views may still have their state saved.
8620      *
8621      * @param enabled Set to false to <em>disable</em> state saving, or true
8622      * (the default) to allow it.
8623      *
8624      * @see #isSaveEnabled()
8625      * @see #setId(int)
8626      * @see #onSaveInstanceState()
8627      * @attr ref android.R.styleable#View_saveEnabled
8628      */
setSaveEnabled(boolean enabled)8629     public void setSaveEnabled(boolean enabled) {
8630         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8631     }
8632 
8633     /**
8634      * Gets whether the framework should discard touches when the view's
8635      * window is obscured by another visible window.
8636      * Refer to the {@link View} security documentation for more details.
8637      *
8638      * @return True if touch filtering is enabled.
8639      *
8640      * @see #setFilterTouchesWhenObscured(boolean)
8641      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8642      */
8643     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()8644     public boolean getFilterTouchesWhenObscured() {
8645         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8646     }
8647 
8648     /**
8649      * Sets whether the framework should discard touches when the view's
8650      * window is obscured by another visible window.
8651      * Refer to the {@link View} security documentation for more details.
8652      *
8653      * @param enabled True if touch filtering should be enabled.
8654      *
8655      * @see #getFilterTouchesWhenObscured
8656      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8657      */
setFilterTouchesWhenObscured(boolean enabled)8658     public void setFilterTouchesWhenObscured(boolean enabled) {
8659         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8660                 FILTER_TOUCHES_WHEN_OBSCURED);
8661     }
8662 
8663     /**
8664      * Indicates whether the entire hierarchy under this view will save its
8665      * state when a state saving traversal occurs from its parent.  The default
8666      * is true; if false, these views will not be saved unless
8667      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8668      *
8669      * @return Returns true if the view state saving from parent is enabled, else false.
8670      *
8671      * @see #setSaveFromParentEnabled(boolean)
8672      */
isSaveFromParentEnabled()8673     public boolean isSaveFromParentEnabled() {
8674         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8675     }
8676 
8677     /**
8678      * Controls whether the entire hierarchy under this view will save its
8679      * state when a state saving traversal occurs from its parent.  The default
8680      * is true; if false, these views will not be saved unless
8681      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8682      *
8683      * @param enabled Set to false to <em>disable</em> state saving, or true
8684      * (the default) to allow it.
8685      *
8686      * @see #isSaveFromParentEnabled()
8687      * @see #setId(int)
8688      * @see #onSaveInstanceState()
8689      */
setSaveFromParentEnabled(boolean enabled)8690     public void setSaveFromParentEnabled(boolean enabled) {
8691         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8692     }
8693 
8694 
8695     /**
8696      * Returns whether this View is able to take focus.
8697      *
8698      * @return True if this view can take focus, or false otherwise.
8699      * @attr ref android.R.styleable#View_focusable
8700      */
8701     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()8702     public final boolean isFocusable() {
8703         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8704     }
8705 
8706     /**
8707      * When a view is focusable, it may not want to take focus when in touch mode.
8708      * For example, a button would like focus when the user is navigating via a D-pad
8709      * so that the user can click on it, but once the user starts touching the screen,
8710      * the button shouldn't take focus
8711      * @return Whether the view is focusable in touch mode.
8712      * @attr ref android.R.styleable#View_focusableInTouchMode
8713      */
8714     @ViewDebug.ExportedProperty
isFocusableInTouchMode()8715     public final boolean isFocusableInTouchMode() {
8716         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8717     }
8718 
8719     /**
8720      * Find the nearest view in the specified direction that can take focus.
8721      * This does not actually give focus to that view.
8722      *
8723      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8724      *
8725      * @return The nearest focusable in the specified direction, or null if none
8726      *         can be found.
8727      */
focusSearch(@ocusRealDirection int direction)8728     public View focusSearch(@FocusRealDirection int direction) {
8729         if (mParent != null) {
8730             return mParent.focusSearch(this, direction);
8731         } else {
8732             return null;
8733         }
8734     }
8735 
8736     /**
8737      * This method is the last chance for the focused view and its ancestors to
8738      * respond to an arrow key. This is called when the focused view did not
8739      * consume the key internally, nor could the view system find a new view in
8740      * the requested direction to give focus to.
8741      *
8742      * @param focused The currently focused view.
8743      * @param direction The direction focus wants to move. One of FOCUS_UP,
8744      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8745      * @return True if the this view consumed this unhandled move.
8746      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)8747     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8748         return false;
8749     }
8750 
8751     /**
8752      * If a user manually specified the next view id for a particular direction,
8753      * use the root to look up the view.
8754      * @param root The root view of the hierarchy containing this view.
8755      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8756      * or FOCUS_BACKWARD.
8757      * @return The user specified next view, or null if there is none.
8758      */
findUserSetNextFocus(View root, @FocusDirection int direction)8759     View findUserSetNextFocus(View root, @FocusDirection int direction) {
8760         switch (direction) {
8761             case FOCUS_LEFT:
8762                 if (mNextFocusLeftId == View.NO_ID) return null;
8763                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8764             case FOCUS_RIGHT:
8765                 if (mNextFocusRightId == View.NO_ID) return null;
8766                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
8767             case FOCUS_UP:
8768                 if (mNextFocusUpId == View.NO_ID) return null;
8769                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
8770             case FOCUS_DOWN:
8771                 if (mNextFocusDownId == View.NO_ID) return null;
8772                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
8773             case FOCUS_FORWARD:
8774                 if (mNextFocusForwardId == View.NO_ID) return null;
8775                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8776             case FOCUS_BACKWARD: {
8777                 if (mID == View.NO_ID) return null;
8778                 final int id = mID;
8779                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8780                     @Override
8781                     public boolean apply(View t) {
8782                         return t.mNextFocusForwardId == id;
8783                     }
8784                 });
8785             }
8786         }
8787         return null;
8788     }
8789 
findViewInsideOutShouldExist(View root, int id)8790     private View findViewInsideOutShouldExist(View root, int id) {
8791         if (mMatchIdPredicate == null) {
8792             mMatchIdPredicate = new MatchIdPredicate();
8793         }
8794         mMatchIdPredicate.mId = id;
8795         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8796         if (result == null) {
8797             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8798         }
8799         return result;
8800     }
8801 
8802     /**
8803      * Find and return all focusable views that are descendants of this view,
8804      * possibly including this view if it is focusable itself.
8805      *
8806      * @param direction The direction of the focus
8807      * @return A list of focusable views
8808      */
getFocusables(@ocusDirection int direction)8809     public ArrayList<View> getFocusables(@FocusDirection int direction) {
8810         ArrayList<View> result = new ArrayList<View>(24);
8811         addFocusables(result, direction);
8812         return result;
8813     }
8814 
8815     /**
8816      * Add any focusable views that are descendants of this view (possibly
8817      * including this view if it is focusable itself) to views.  If we are in touch mode,
8818      * only add views that are also focusable in touch mode.
8819      *
8820      * @param views Focusable views found so far
8821      * @param direction The direction of the focus
8822      */
addFocusables(ArrayList<View> views, @FocusDirection int direction)8823     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8824         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8825     }
8826 
8827     /**
8828      * Adds any focusable views that are descendants of this view (possibly
8829      * including this view if it is focusable itself) to views. This method
8830      * adds all focusable views regardless if we are in touch mode or
8831      * only views focusable in touch mode if we are in touch mode or
8832      * only views that can take accessibility focus if accessibility is enabled
8833      * depending on the focusable mode parameter.
8834      *
8835      * @param views Focusable views found so far or null if all we are interested is
8836      *        the number of focusables.
8837      * @param direction The direction of the focus.
8838      * @param focusableMode The type of focusables to be added.
8839      *
8840      * @see #FOCUSABLES_ALL
8841      * @see #FOCUSABLES_TOUCH_MODE
8842      */
addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)8843     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8844             @FocusableMode int focusableMode) {
8845         if (views == null) {
8846             return;
8847         }
8848         if (!isFocusable()) {
8849             return;
8850         }
8851         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8852                 && !isFocusableInTouchMode()) {
8853             return;
8854         }
8855         views.add(this);
8856     }
8857 
8858     /**
8859      * Finds the Views that contain given text. The containment is case insensitive.
8860      * The search is performed by either the text that the View renders or the content
8861      * description that describes the view for accessibility purposes and the view does
8862      * not render or both. Clients can specify how the search is to be performed via
8863      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8864      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8865      *
8866      * @param outViews The output list of matching Views.
8867      * @param searched The text to match against.
8868      *
8869      * @see #FIND_VIEWS_WITH_TEXT
8870      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8871      * @see #setContentDescription(CharSequence)
8872      */
findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)8873     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8874             @FindViewFlags int flags) {
8875         if (getAccessibilityNodeProvider() != null) {
8876             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8877                 outViews.add(this);
8878             }
8879         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8880                 && (searched != null && searched.length() > 0)
8881                 && (mContentDescription != null && mContentDescription.length() > 0)) {
8882             String searchedLowerCase = searched.toString().toLowerCase();
8883             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8884             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8885                 outViews.add(this);
8886             }
8887         }
8888     }
8889 
8890     /**
8891      * Find and return all touchable views that are descendants of this view,
8892      * possibly including this view if it is touchable itself.
8893      *
8894      * @return A list of touchable views
8895      */
getTouchables()8896     public ArrayList<View> getTouchables() {
8897         ArrayList<View> result = new ArrayList<View>();
8898         addTouchables(result);
8899         return result;
8900     }
8901 
8902     /**
8903      * Add any touchable views that are descendants of this view (possibly
8904      * including this view if it is touchable itself) to views.
8905      *
8906      * @param views Touchable views found so far
8907      */
addTouchables(ArrayList<View> views)8908     public void addTouchables(ArrayList<View> views) {
8909         final int viewFlags = mViewFlags;
8910 
8911         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8912                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8913                 && (viewFlags & ENABLED_MASK) == ENABLED) {
8914             views.add(this);
8915         }
8916     }
8917 
8918     /**
8919      * Returns whether this View is accessibility focused.
8920      *
8921      * @return True if this View is accessibility focused.
8922      */
isAccessibilityFocused()8923     public boolean isAccessibilityFocused() {
8924         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8925     }
8926 
8927     /**
8928      * Call this to try to give accessibility focus to this view.
8929      *
8930      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8931      * returns false or the view is no visible or the view already has accessibility
8932      * focus.
8933      *
8934      * See also {@link #focusSearch(int)}, which is what you call to say that you
8935      * have focus, and you want your parent to look for the next one.
8936      *
8937      * @return Whether this view actually took accessibility focus.
8938      *
8939      * @hide
8940      */
requestAccessibilityFocus()8941     public boolean requestAccessibilityFocus() {
8942         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8943         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8944             return false;
8945         }
8946         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8947             return false;
8948         }
8949         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8950             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8951             ViewRootImpl viewRootImpl = getViewRootImpl();
8952             if (viewRootImpl != null) {
8953                 viewRootImpl.setAccessibilityFocus(this, null);
8954             }
8955             invalidate();
8956             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8957             return true;
8958         }
8959         return false;
8960     }
8961 
8962     /**
8963      * Call this to try to clear accessibility focus of this view.
8964      *
8965      * See also {@link #focusSearch(int)}, which is what you call to say that you
8966      * have focus, and you want your parent to look for the next one.
8967      *
8968      * @hide
8969      */
clearAccessibilityFocus()8970     public void clearAccessibilityFocus() {
8971         clearAccessibilityFocusNoCallbacks(0);
8972 
8973         // Clear the global reference of accessibility focus if this view or
8974         // any of its descendants had accessibility focus. This will NOT send
8975         // an event or update internal state if focus is cleared from a
8976         // descendant view, which may leave views in inconsistent states.
8977         final ViewRootImpl viewRootImpl = getViewRootImpl();
8978         if (viewRootImpl != null) {
8979             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8980             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8981                 viewRootImpl.setAccessibilityFocus(null, null);
8982             }
8983         }
8984     }
8985 
sendAccessibilityHoverEvent(int eventType)8986     private void sendAccessibilityHoverEvent(int eventType) {
8987         // Since we are not delivering to a client accessibility events from not
8988         // important views (unless the clinet request that) we need to fire the
8989         // event from the deepest view exposed to the client. As a consequence if
8990         // the user crosses a not exposed view the client will see enter and exit
8991         // of the exposed predecessor followed by and enter and exit of that same
8992         // predecessor when entering and exiting the not exposed descendant. This
8993         // is fine since the client has a clear idea which view is hovered at the
8994         // price of a couple more events being sent. This is a simple and
8995         // working solution.
8996         View source = this;
8997         while (true) {
8998             if (source.includeForAccessibility()) {
8999                 source.sendAccessibilityEvent(eventType);
9000                 return;
9001             }
9002             ViewParent parent = source.getParent();
9003             if (parent instanceof View) {
9004                 source = (View) parent;
9005             } else {
9006                 return;
9007             }
9008         }
9009     }
9010 
9011     /**
9012      * Clears accessibility focus without calling any callback methods
9013      * normally invoked in {@link #clearAccessibilityFocus()}. This method
9014      * is used separately from that one for clearing accessibility focus when
9015      * giving this focus to another view.
9016      *
9017      * @param action The action, if any, that led to focus being cleared. Set to
9018      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9019      * the window.
9020      */
clearAccessibilityFocusNoCallbacks(int action)9021     void clearAccessibilityFocusNoCallbacks(int action) {
9022         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9023             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9024             invalidate();
9025             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9026                 AccessibilityEvent event = AccessibilityEvent.obtain(
9027                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9028                 event.setAction(action);
9029                 if (mAccessibilityDelegate != null) {
9030                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9031                 } else {
9032                     sendAccessibilityEventUnchecked(event);
9033                 }
9034             }
9035         }
9036     }
9037 
9038     /**
9039      * Call this to try to give focus to a specific view or to one of its
9040      * descendants.
9041      *
9042      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9043      * false), or if it is focusable and it is not focusable in touch mode
9044      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9045      *
9046      * See also {@link #focusSearch(int)}, which is what you call to say that you
9047      * have focus, and you want your parent to look for the next one.
9048      *
9049      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9050      * {@link #FOCUS_DOWN} and <code>null</code>.
9051      *
9052      * @return Whether this view or one of its descendants actually took focus.
9053      */
requestFocus()9054     public final boolean requestFocus() {
9055         return requestFocus(View.FOCUS_DOWN);
9056     }
9057 
9058     /**
9059      * Call this to try to give focus to a specific view or to one of its
9060      * descendants and give it a hint about what direction focus is heading.
9061      *
9062      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9063      * false), or if it is focusable and it is not focusable in touch mode
9064      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9065      *
9066      * See also {@link #focusSearch(int)}, which is what you call to say that you
9067      * have focus, and you want your parent to look for the next one.
9068      *
9069      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9070      * <code>null</code> set for the previously focused rectangle.
9071      *
9072      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9073      * @return Whether this view or one of its descendants actually took focus.
9074      */
requestFocus(int direction)9075     public final boolean requestFocus(int direction) {
9076         return requestFocus(direction, null);
9077     }
9078 
9079     /**
9080      * Call this to try to give focus to a specific view or to one of its descendants
9081      * and give it hints about the direction and a specific rectangle that the focus
9082      * is coming from.  The rectangle can help give larger views a finer grained hint
9083      * about where focus is coming from, and therefore, where to show selection, or
9084      * forward focus change internally.
9085      *
9086      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9087      * false), or if it is focusable and it is not focusable in touch mode
9088      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9089      *
9090      * A View will not take focus if it is not visible.
9091      *
9092      * A View will not take focus if one of its parents has
9093      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9094      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9095      *
9096      * See also {@link #focusSearch(int)}, which is what you call to say that you
9097      * have focus, and you want your parent to look for the next one.
9098      *
9099      * You may wish to override this method if your custom {@link View} has an internal
9100      * {@link View} that it wishes to forward the request to.
9101      *
9102      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9103      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9104      *        to give a finer grained hint about where focus is coming from.  May be null
9105      *        if there is no hint.
9106      * @return Whether this view or one of its descendants actually took focus.
9107      */
requestFocus(int direction, Rect previouslyFocusedRect)9108     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9109         return requestFocusNoSearch(direction, previouslyFocusedRect);
9110     }
9111 
requestFocusNoSearch(int direction, Rect previouslyFocusedRect)9112     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9113         // need to be focusable
9114         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9115                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9116             return false;
9117         }
9118 
9119         // need to be focusable in touch mode if in touch mode
9120         if (isInTouchMode() &&
9121             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9122                return false;
9123         }
9124 
9125         // need to not have any parents blocking us
9126         if (hasAncestorThatBlocksDescendantFocus()) {
9127             return false;
9128         }
9129 
9130         handleFocusGainInternal(direction, previouslyFocusedRect);
9131         return true;
9132     }
9133 
9134     /**
9135      * Call this to try to give focus to a specific view or to one of its descendants. This is a
9136      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9137      * touch mode to request focus when they are touched.
9138      *
9139      * @return Whether this view or one of its descendants actually took focus.
9140      *
9141      * @see #isInTouchMode()
9142      *
9143      */
requestFocusFromTouch()9144     public final boolean requestFocusFromTouch() {
9145         // Leave touch mode if we need to
9146         if (isInTouchMode()) {
9147             ViewRootImpl viewRoot = getViewRootImpl();
9148             if (viewRoot != null) {
9149                 viewRoot.ensureTouchMode(false);
9150             }
9151         }
9152         return requestFocus(View.FOCUS_DOWN);
9153     }
9154 
9155     /**
9156      * @return Whether any ancestor of this view blocks descendant focus.
9157      */
hasAncestorThatBlocksDescendantFocus()9158     private boolean hasAncestorThatBlocksDescendantFocus() {
9159         final boolean focusableInTouchMode = isFocusableInTouchMode();
9160         ViewParent ancestor = mParent;
9161         while (ancestor instanceof ViewGroup) {
9162             final ViewGroup vgAncestor = (ViewGroup) ancestor;
9163             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9164                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9165                 return true;
9166             } else {
9167                 ancestor = vgAncestor.getParent();
9168             }
9169         }
9170         return false;
9171     }
9172 
9173     /**
9174      * Gets the mode for determining whether this View is important for accessibility
9175      * which is if it fires accessibility events and if it is reported to
9176      * accessibility services that query the screen.
9177      *
9178      * @return The mode for determining whether a View is important for accessibility.
9179      *
9180      * @attr ref android.R.styleable#View_importantForAccessibility
9181      *
9182      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9183      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9184      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9185      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9186      */
9187     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9188             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9189             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9190             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9191             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9192                     to = "noHideDescendants")
9193         })
getImportantForAccessibility()9194     public int getImportantForAccessibility() {
9195         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9196                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9197     }
9198 
9199     /**
9200      * Sets the live region mode for this view. This indicates to accessibility
9201      * services whether they should automatically notify the user about changes
9202      * to the view's content description or text, or to the content descriptions
9203      * or text of the view's children (where applicable).
9204      * <p>
9205      * For example, in a login screen with a TextView that displays an "incorrect
9206      * password" notification, that view should be marked as a live region with
9207      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9208      * <p>
9209      * To disable change notifications for this view, use
9210      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9211      * mode for most views.
9212      * <p>
9213      * To indicate that the user should be notified of changes, use
9214      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9215      * <p>
9216      * If the view's changes should interrupt ongoing speech and notify the user
9217      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9218      *
9219      * @param mode The live region mode for this view, one of:
9220      *        <ul>
9221      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9222      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9223      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9224      *        </ul>
9225      * @attr ref android.R.styleable#View_accessibilityLiveRegion
9226      */
setAccessibilityLiveRegion(int mode)9227     public void setAccessibilityLiveRegion(int mode) {
9228         if (mode != getAccessibilityLiveRegion()) {
9229             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9230             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9231                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9232             notifyViewAccessibilityStateChangedIfNeeded(
9233                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9234         }
9235     }
9236 
9237     /**
9238      * Gets the live region mode for this View.
9239      *
9240      * @return The live region mode for the view.
9241      *
9242      * @attr ref android.R.styleable#View_accessibilityLiveRegion
9243      *
9244      * @see #setAccessibilityLiveRegion(int)
9245      */
getAccessibilityLiveRegion()9246     public int getAccessibilityLiveRegion() {
9247         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9248                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9249     }
9250 
9251     /**
9252      * Sets how to determine whether this view is important for accessibility
9253      * which is if it fires accessibility events and if it is reported to
9254      * accessibility services that query the screen.
9255      *
9256      * @param mode How to determine whether this view is important for accessibility.
9257      *
9258      * @attr ref android.R.styleable#View_importantForAccessibility
9259      *
9260      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9261      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9262      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9263      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9264      */
setImportantForAccessibility(int mode)9265     public void setImportantForAccessibility(int mode) {
9266         final int oldMode = getImportantForAccessibility();
9267         if (mode != oldMode) {
9268             final boolean hideDescendants =
9269                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9270 
9271             // If this node or its descendants are no longer important, try to
9272             // clear accessibility focus.
9273             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9274                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
9275                 if (focusHost != null) {
9276                     focusHost.clearAccessibilityFocus();
9277                 }
9278             }
9279 
9280             // If we're moving between AUTO and another state, we might not need
9281             // to send a subtree changed notification. We'll store the computed
9282             // importance, since we'll need to check it later to make sure.
9283             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9284                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9285             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9286             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9287             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9288                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9289             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9290                 notifySubtreeAccessibilityStateChangedIfNeeded();
9291             } else {
9292                 notifyViewAccessibilityStateChangedIfNeeded(
9293                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9294             }
9295         }
9296     }
9297 
9298     /**
9299      * Returns the view within this view's hierarchy that is hosting
9300      * accessibility focus.
9301      *
9302      * @param searchDescendants whether to search for focus in descendant views
9303      * @return the view hosting accessibility focus, or {@code null}
9304      */
findAccessibilityFocusHost(boolean searchDescendants)9305     private View findAccessibilityFocusHost(boolean searchDescendants) {
9306         if (isAccessibilityFocusedViewOrHost()) {
9307             return this;
9308         }
9309 
9310         if (searchDescendants) {
9311             final ViewRootImpl viewRoot = getViewRootImpl();
9312             if (viewRoot != null) {
9313                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
9314                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9315                     return focusHost;
9316                 }
9317             }
9318         }
9319 
9320         return null;
9321     }
9322 
9323     /**
9324      * Computes whether this view should be exposed for accessibility. In
9325      * general, views that are interactive or provide information are exposed
9326      * while views that serve only as containers are hidden.
9327      * <p>
9328      * If an ancestor of this view has importance
9329      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9330      * returns <code>false</code>.
9331      * <p>
9332      * Otherwise, the value is computed according to the view's
9333      * {@link #getImportantForAccessibility()} value:
9334      * <ol>
9335      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9336      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9337      * </code>
9338      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9339      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9340      * view satisfies any of the following:
9341      * <ul>
9342      * <li>Is actionable, e.g. {@link #isClickable()},
9343      * {@link #isLongClickable()}, or {@link #isFocusable()}
9344      * <li>Has an {@link AccessibilityDelegate}
9345      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9346      * {@link OnKeyListener}, etc.
9347      * <li>Is an accessibility live region, e.g.
9348      * {@link #getAccessibilityLiveRegion()} is not
9349      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9350      * </ul>
9351      * </ol>
9352      *
9353      * @return Whether the view is exposed for accessibility.
9354      * @see #setImportantForAccessibility(int)
9355      * @see #getImportantForAccessibility()
9356      */
isImportantForAccessibility()9357     public boolean isImportantForAccessibility() {
9358         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9359                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9360         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9361                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9362             return false;
9363         }
9364 
9365         // Check parent mode to ensure we're not hidden.
9366         ViewParent parent = mParent;
9367         while (parent instanceof View) {
9368             if (((View) parent).getImportantForAccessibility()
9369                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9370                 return false;
9371             }
9372             parent = parent.getParent();
9373         }
9374 
9375         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9376                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9377                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9378     }
9379 
9380     /**
9381      * Gets the parent for accessibility purposes. Note that the parent for
9382      * accessibility is not necessary the immediate parent. It is the first
9383      * predecessor that is important for accessibility.
9384      *
9385      * @return The parent for accessibility purposes.
9386      */
getParentForAccessibility()9387     public ViewParent getParentForAccessibility() {
9388         if (mParent instanceof View) {
9389             View parentView = (View) mParent;
9390             if (parentView.includeForAccessibility()) {
9391                 return mParent;
9392             } else {
9393                 return mParent.getParentForAccessibility();
9394             }
9395         }
9396         return null;
9397     }
9398 
9399     /**
9400      * Adds the children of this View relevant for accessibility to the given list
9401      * as output. Since some Views are not important for accessibility the added
9402      * child views are not necessarily direct children of this view, rather they are
9403      * the first level of descendants important for accessibility.
9404      *
9405      * @param outChildren The output list that will receive children for accessibility.
9406      */
addChildrenForAccessibility(ArrayList<View> outChildren)9407     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9408 
9409     }
9410 
9411     /**
9412      * Whether to regard this view for accessibility. A view is regarded for
9413      * accessibility if it is important for accessibility or the querying
9414      * accessibility service has explicitly requested that view not
9415      * important for accessibility are regarded.
9416      *
9417      * @return Whether to regard the view for accessibility.
9418      *
9419      * @hide
9420      */
includeForAccessibility()9421     public boolean includeForAccessibility() {
9422         if (mAttachInfo != null) {
9423             return (mAttachInfo.mAccessibilityFetchFlags
9424                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9425                     || isImportantForAccessibility();
9426         }
9427         return false;
9428     }
9429 
9430     /**
9431      * Returns whether the View is considered actionable from
9432      * accessibility perspective. Such view are important for
9433      * accessibility.
9434      *
9435      * @return True if the view is actionable for accessibility.
9436      *
9437      * @hide
9438      */
isActionableForAccessibility()9439     public boolean isActionableForAccessibility() {
9440         return (isClickable() || isLongClickable() || isFocusable());
9441     }
9442 
9443     /**
9444      * Returns whether the View has registered callbacks which makes it
9445      * important for accessibility.
9446      *
9447      * @return True if the view is actionable for accessibility.
9448      */
hasListenersForAccessibility()9449     private boolean hasListenersForAccessibility() {
9450         ListenerInfo info = getListenerInfo();
9451         return mTouchDelegate != null || info.mOnKeyListener != null
9452                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9453                 || info.mOnHoverListener != null || info.mOnDragListener != null;
9454     }
9455 
9456     /**
9457      * Notifies that the accessibility state of this view changed. The change
9458      * is local to this view and does not represent structural changes such
9459      * as children and parent. For example, the view became focusable. The
9460      * notification is at at most once every
9461      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9462      * to avoid unnecessary load to the system. Also once a view has a pending
9463      * notification this method is a NOP until the notification has been sent.
9464      *
9465      * @hide
9466      */
notifyViewAccessibilityStateChangedIfNeeded(int changeType)9467     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9468         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9469             return;
9470         }
9471         if (mSendViewStateChangedAccessibilityEvent == null) {
9472             mSendViewStateChangedAccessibilityEvent =
9473                     new SendViewStateChangedAccessibilityEvent();
9474         }
9475         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9476     }
9477 
9478     /**
9479      * Notifies that the accessibility state of this view changed. The change
9480      * is *not* local to this view and does represent structural changes such
9481      * as children and parent. For example, the view size changed. The
9482      * notification is at at most once every
9483      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9484      * to avoid unnecessary load to the system. Also once a view has a pending
9485      * notification this method is a NOP until the notification has been sent.
9486      *
9487      * @hide
9488      */
notifySubtreeAccessibilityStateChangedIfNeeded()9489     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9490         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9491             return;
9492         }
9493         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9494             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9495             if (mParent != null) {
9496                 try {
9497                     mParent.notifySubtreeAccessibilityStateChanged(
9498                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9499                 } catch (AbstractMethodError e) {
9500                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9501                             " does not fully implement ViewParent", e);
9502                 }
9503             }
9504         }
9505     }
9506 
9507     /**
9508      * Change the visibility of the View without triggering any other changes. This is
9509      * important for transitions, where visibility changes should not adjust focus or
9510      * trigger a new layout. This is only used when the visibility has already been changed
9511      * and we need a transient value during an animation. When the animation completes,
9512      * the original visibility value is always restored.
9513      *
9514      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9515      * @hide
9516      */
setTransitionVisibility(@isibility int visibility)9517     public void setTransitionVisibility(@Visibility int visibility) {
9518         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9519     }
9520 
9521     /**
9522      * Reset the flag indicating the accessibility state of the subtree rooted
9523      * at this view changed.
9524      */
resetSubtreeAccessibilityStateChanged()9525     void resetSubtreeAccessibilityStateChanged() {
9526         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9527     }
9528 
9529     /**
9530      * Report an accessibility action to this view's parents for delegated processing.
9531      *
9532      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9533      * call this method to delegate an accessibility action to a supporting parent. If the parent
9534      * returns true from its
9535      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9536      * method this method will return true to signify that the action was consumed.</p>
9537      *
9538      * <p>This method is useful for implementing nested scrolling child views. If
9539      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9540      * a custom view implementation may invoke this method to allow a parent to consume the
9541      * scroll first. If this method returns true the custom view should skip its own scrolling
9542      * behavior.</p>
9543      *
9544      * @param action Accessibility action to delegate
9545      * @param arguments Optional action arguments
9546      * @return true if the action was consumed by a parent
9547      */
dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments)9548     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9549         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9550             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9551                 return true;
9552             }
9553         }
9554         return false;
9555     }
9556 
9557     /**
9558      * Performs the specified accessibility action on the view. For
9559      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9560      * <p>
9561      * If an {@link AccessibilityDelegate} has been specified via calling
9562      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9563      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9564      * is responsible for handling this call.
9565      * </p>
9566      *
9567      * <p>The default implementation will delegate
9568      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9569      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9570      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9571      *
9572      * @param action The action to perform.
9573      * @param arguments Optional action arguments.
9574      * @return Whether the action was performed.
9575      */
performAccessibilityAction(int action, Bundle arguments)9576     public boolean performAccessibilityAction(int action, Bundle arguments) {
9577       if (mAccessibilityDelegate != null) {
9578           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9579       } else {
9580           return performAccessibilityActionInternal(action, arguments);
9581       }
9582     }
9583 
9584    /**
9585     * @see #performAccessibilityAction(int, Bundle)
9586     *
9587     * Note: Called from the default {@link AccessibilityDelegate}.
9588     *
9589     * @hide
9590     */
performAccessibilityActionInternal(int action, Bundle arguments)9591     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9592         if (isNestedScrollingEnabled()
9593                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9594                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9595                 || action == R.id.accessibilityActionScrollUp
9596                 || action == R.id.accessibilityActionScrollLeft
9597                 || action == R.id.accessibilityActionScrollDown
9598                 || action == R.id.accessibilityActionScrollRight)) {
9599             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9600                 return true;
9601             }
9602         }
9603 
9604         switch (action) {
9605             case AccessibilityNodeInfo.ACTION_CLICK: {
9606                 if (isClickable()) {
9607                     performClick();
9608                     return true;
9609                 }
9610             } break;
9611             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9612                 if (isLongClickable()) {
9613                     performLongClick();
9614                     return true;
9615                 }
9616             } break;
9617             case AccessibilityNodeInfo.ACTION_FOCUS: {
9618                 if (!hasFocus()) {
9619                     // Get out of touch mode since accessibility
9620                     // wants to move focus around.
9621                     getViewRootImpl().ensureTouchMode(false);
9622                     return requestFocus();
9623                 }
9624             } break;
9625             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9626                 if (hasFocus()) {
9627                     clearFocus();
9628                     return !isFocused();
9629                 }
9630             } break;
9631             case AccessibilityNodeInfo.ACTION_SELECT: {
9632                 if (!isSelected()) {
9633                     setSelected(true);
9634                     return isSelected();
9635                 }
9636             } break;
9637             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9638                 if (isSelected()) {
9639                     setSelected(false);
9640                     return !isSelected();
9641                 }
9642             } break;
9643             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9644                 if (!isAccessibilityFocused()) {
9645                     return requestAccessibilityFocus();
9646                 }
9647             } break;
9648             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9649                 if (isAccessibilityFocused()) {
9650                     clearAccessibilityFocus();
9651                     return true;
9652                 }
9653             } break;
9654             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9655                 if (arguments != null) {
9656                     final int granularity = arguments.getInt(
9657                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9658                     final boolean extendSelection = arguments.getBoolean(
9659                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9660                     return traverseAtGranularity(granularity, true, extendSelection);
9661                 }
9662             } break;
9663             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9664                 if (arguments != null) {
9665                     final int granularity = arguments.getInt(
9666                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9667                     final boolean extendSelection = arguments.getBoolean(
9668                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9669                     return traverseAtGranularity(granularity, false, extendSelection);
9670                 }
9671             } break;
9672             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9673                 CharSequence text = getIterableTextForAccessibility();
9674                 if (text == null) {
9675                     return false;
9676                 }
9677                 final int start = (arguments != null) ? arguments.getInt(
9678                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9679                 final int end = (arguments != null) ? arguments.getInt(
9680                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9681                 // Only cursor position can be specified (selection length == 0)
9682                 if ((getAccessibilitySelectionStart() != start
9683                         || getAccessibilitySelectionEnd() != end)
9684                         && (start == end)) {
9685                     setAccessibilitySelection(start, end);
9686                     notifyViewAccessibilityStateChangedIfNeeded(
9687                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9688                     return true;
9689                 }
9690             } break;
9691             case R.id.accessibilityActionShowOnScreen: {
9692                 if (mAttachInfo != null) {
9693                     final Rect r = mAttachInfo.mTmpInvalRect;
9694                     getDrawingRect(r);
9695                     return requestRectangleOnScreen(r, true);
9696                 }
9697             } break;
9698             case R.id.accessibilityActionContextClick: {
9699                 if (isContextClickable()) {
9700                     performContextClick();
9701                     return true;
9702                 }
9703             } break;
9704         }
9705         return false;
9706     }
9707 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)9708     private boolean traverseAtGranularity(int granularity, boolean forward,
9709             boolean extendSelection) {
9710         CharSequence text = getIterableTextForAccessibility();
9711         if (text == null || text.length() == 0) {
9712             return false;
9713         }
9714         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9715         if (iterator == null) {
9716             return false;
9717         }
9718         int current = getAccessibilitySelectionEnd();
9719         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9720             current = forward ? 0 : text.length();
9721         }
9722         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9723         if (range == null) {
9724             return false;
9725         }
9726         final int segmentStart = range[0];
9727         final int segmentEnd = range[1];
9728         int selectionStart;
9729         int selectionEnd;
9730         if (extendSelection && isAccessibilitySelectionExtendable()) {
9731             selectionStart = getAccessibilitySelectionStart();
9732             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9733                 selectionStart = forward ? segmentStart : segmentEnd;
9734             }
9735             selectionEnd = forward ? segmentEnd : segmentStart;
9736         } else {
9737             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9738         }
9739         setAccessibilitySelection(selectionStart, selectionEnd);
9740         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9741                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9742         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9743         return true;
9744     }
9745 
9746     /**
9747      * Gets the text reported for accessibility purposes.
9748      *
9749      * @return The accessibility text.
9750      *
9751      * @hide
9752      */
getIterableTextForAccessibility()9753     public CharSequence getIterableTextForAccessibility() {
9754         return getContentDescription();
9755     }
9756 
9757     /**
9758      * Gets whether accessibility selection can be extended.
9759      *
9760      * @return If selection is extensible.
9761      *
9762      * @hide
9763      */
isAccessibilitySelectionExtendable()9764     public boolean isAccessibilitySelectionExtendable() {
9765         return false;
9766     }
9767 
9768     /**
9769      * @hide
9770      */
getAccessibilitySelectionStart()9771     public int getAccessibilitySelectionStart() {
9772         return mAccessibilityCursorPosition;
9773     }
9774 
9775     /**
9776      * @hide
9777      */
getAccessibilitySelectionEnd()9778     public int getAccessibilitySelectionEnd() {
9779         return getAccessibilitySelectionStart();
9780     }
9781 
9782     /**
9783      * @hide
9784      */
setAccessibilitySelection(int start, int end)9785     public void setAccessibilitySelection(int start, int end) {
9786         if (start ==  end && end == mAccessibilityCursorPosition) {
9787             return;
9788         }
9789         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9790             mAccessibilityCursorPosition = start;
9791         } else {
9792             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9793         }
9794         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9795     }
9796 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)9797     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9798             int fromIndex, int toIndex) {
9799         if (mParent == null) {
9800             return;
9801         }
9802         AccessibilityEvent event = AccessibilityEvent.obtain(
9803                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9804         onInitializeAccessibilityEvent(event);
9805         onPopulateAccessibilityEvent(event);
9806         event.setFromIndex(fromIndex);
9807         event.setToIndex(toIndex);
9808         event.setAction(action);
9809         event.setMovementGranularity(granularity);
9810         mParent.requestSendAccessibilityEvent(this, event);
9811     }
9812 
9813     /**
9814      * @hide
9815      */
getIteratorForGranularity(int granularity)9816     public TextSegmentIterator getIteratorForGranularity(int granularity) {
9817         switch (granularity) {
9818             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9819                 CharSequence text = getIterableTextForAccessibility();
9820                 if (text != null && text.length() > 0) {
9821                     CharacterTextSegmentIterator iterator =
9822                         CharacterTextSegmentIterator.getInstance(
9823                                 mContext.getResources().getConfiguration().locale);
9824                     iterator.initialize(text.toString());
9825                     return iterator;
9826                 }
9827             } break;
9828             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9829                 CharSequence text = getIterableTextForAccessibility();
9830                 if (text != null && text.length() > 0) {
9831                     WordTextSegmentIterator iterator =
9832                         WordTextSegmentIterator.getInstance(
9833                                 mContext.getResources().getConfiguration().locale);
9834                     iterator.initialize(text.toString());
9835                     return iterator;
9836                 }
9837             } break;
9838             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9839                 CharSequence text = getIterableTextForAccessibility();
9840                 if (text != null && text.length() > 0) {
9841                     ParagraphTextSegmentIterator iterator =
9842                         ParagraphTextSegmentIterator.getInstance();
9843                     iterator.initialize(text.toString());
9844                     return iterator;
9845                 }
9846             } break;
9847         }
9848         return null;
9849     }
9850 
9851     /**
9852      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
9853      * and {@link #onFinishTemporaryDetach()}.
9854      *
9855      * <p>This method always returns {@code true} when called directly or indirectly from
9856      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
9857      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
9858      * <ul>
9859      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
9860      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
9861      * </ul>
9862      * </p>
9863      *
9864      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9865      * and {@link #onFinishTemporaryDetach()}.
9866      */
isTemporarilyDetached()9867     public final boolean isTemporarilyDetached() {
9868         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9869     }
9870 
9871     /**
9872      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9873      * a container View.
9874      */
9875     @CallSuper
dispatchStartTemporaryDetach()9876     public void dispatchStartTemporaryDetach() {
9877         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9878         onStartTemporaryDetach();
9879     }
9880 
9881     /**
9882      * This is called when a container is going to temporarily detach a child, with
9883      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9884      * It will either be followed by {@link #onFinishTemporaryDetach()} or
9885      * {@link #onDetachedFromWindow()} when the container is done.
9886      */
onStartTemporaryDetach()9887     public void onStartTemporaryDetach() {
9888         removeUnsetPressCallback();
9889         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9890     }
9891 
9892     /**
9893      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9894      * a container View.
9895      */
9896     @CallSuper
dispatchFinishTemporaryDetach()9897     public void dispatchFinishTemporaryDetach() {
9898         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9899         onFinishTemporaryDetach();
9900         if (hasWindowFocus() && hasFocus()) {
9901             InputMethodManager.getInstance().focusIn(this);
9902         }
9903     }
9904 
9905     /**
9906      * Called after {@link #onStartTemporaryDetach} when the container is done
9907      * changing the view.
9908      */
onFinishTemporaryDetach()9909     public void onFinishTemporaryDetach() {
9910     }
9911 
9912     /**
9913      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9914      * for this view's window.  Returns null if the view is not currently attached
9915      * to the window.  Normally you will not need to use this directly, but
9916      * just use the standard high-level event callbacks like
9917      * {@link #onKeyDown(int, KeyEvent)}.
9918      */
getKeyDispatcherState()9919     public KeyEvent.DispatcherState getKeyDispatcherState() {
9920         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9921     }
9922 
9923     /**
9924      * Dispatch a key event before it is processed by any input method
9925      * associated with the view hierarchy.  This can be used to intercept
9926      * key events in special situations before the IME consumes them; a
9927      * typical example would be handling the BACK key to update the application's
9928      * UI instead of allowing the IME to see it and close itself.
9929      *
9930      * @param event The key event to be dispatched.
9931      * @return True if the event was handled, false otherwise.
9932      */
dispatchKeyEventPreIme(KeyEvent event)9933     public boolean dispatchKeyEventPreIme(KeyEvent event) {
9934         return onKeyPreIme(event.getKeyCode(), event);
9935     }
9936 
9937     /**
9938      * Dispatch a key event to the next view on the focus path. This path runs
9939      * from the top of the view tree down to the currently focused view. If this
9940      * view has focus, it will dispatch to itself. Otherwise it will dispatch
9941      * the next node down the focus path. This method also fires any key
9942      * listeners.
9943      *
9944      * @param event The key event to be dispatched.
9945      * @return True if the event was handled, false otherwise.
9946      */
dispatchKeyEvent(KeyEvent event)9947     public boolean dispatchKeyEvent(KeyEvent event) {
9948         if (mInputEventConsistencyVerifier != null) {
9949             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9950         }
9951 
9952         // Give any attached key listener a first crack at the event.
9953         //noinspection SimplifiableIfStatement
9954         ListenerInfo li = mListenerInfo;
9955         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9956                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9957             return true;
9958         }
9959 
9960         if (event.dispatch(this, mAttachInfo != null
9961                 ? mAttachInfo.mKeyDispatchState : null, this)) {
9962             return true;
9963         }
9964 
9965         if (mInputEventConsistencyVerifier != null) {
9966             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9967         }
9968         return false;
9969     }
9970 
9971     /**
9972      * Dispatches a key shortcut event.
9973      *
9974      * @param event The key event to be dispatched.
9975      * @return True if the event was handled by the view, false otherwise.
9976      */
dispatchKeyShortcutEvent(KeyEvent event)9977     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9978         return onKeyShortcut(event.getKeyCode(), event);
9979     }
9980 
9981     /**
9982      * Pass the touch screen motion event down to the target view, or this
9983      * view if it is the target.
9984      *
9985      * @param event The motion event to be dispatched.
9986      * @return True if the event was handled by the view, false otherwise.
9987      */
dispatchTouchEvent(MotionEvent event)9988     public boolean dispatchTouchEvent(MotionEvent event) {
9989         // If the event should be handled by accessibility focus first.
9990         if (event.isTargetAccessibilityFocus()) {
9991             // We don't have focus or no virtual descendant has it, do not handle the event.
9992             if (!isAccessibilityFocusedViewOrHost()) {
9993                 return false;
9994             }
9995             // We have focus and got the event, then use normal event dispatch.
9996             event.setTargetAccessibilityFocus(false);
9997         }
9998 
9999         boolean result = false;
10000 
10001         if (mInputEventConsistencyVerifier != null) {
10002             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10003         }
10004 
10005         final int actionMasked = event.getActionMasked();
10006         if (actionMasked == MotionEvent.ACTION_DOWN) {
10007             // Defensive cleanup for new gesture
10008             stopNestedScroll();
10009         }
10010 
10011         if (onFilterTouchEventForSecurity(event)) {
10012             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10013                 result = true;
10014             }
10015             //noinspection SimplifiableIfStatement
10016             ListenerInfo li = mListenerInfo;
10017             if (li != null && li.mOnTouchListener != null
10018                     && (mViewFlags & ENABLED_MASK) == ENABLED
10019                     && li.mOnTouchListener.onTouch(this, event)) {
10020                 result = true;
10021             }
10022 
10023             if (!result && onTouchEvent(event)) {
10024                 result = true;
10025             }
10026         }
10027 
10028         if (!result && mInputEventConsistencyVerifier != null) {
10029             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10030         }
10031 
10032         // Clean up after nested scrolls if this is the end of a gesture;
10033         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10034         // of the gesture.
10035         if (actionMasked == MotionEvent.ACTION_UP ||
10036                 actionMasked == MotionEvent.ACTION_CANCEL ||
10037                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10038             stopNestedScroll();
10039         }
10040 
10041         return result;
10042     }
10043 
isAccessibilityFocusedViewOrHost()10044     boolean isAccessibilityFocusedViewOrHost() {
10045         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10046                 .getAccessibilityFocusedHost() == this);
10047     }
10048 
10049     /**
10050      * Filter the touch event to apply security policies.
10051      *
10052      * @param event The motion event to be filtered.
10053      * @return True if the event should be dispatched, false if the event should be dropped.
10054      *
10055      * @see #getFilterTouchesWhenObscured
10056      */
onFilterTouchEventForSecurity(MotionEvent event)10057     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10058         //noinspection RedundantIfStatement
10059         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10060                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10061             // Window is obscured, drop this touch.
10062             return false;
10063         }
10064         return true;
10065     }
10066 
10067     /**
10068      * Pass a trackball motion event down to the focused view.
10069      *
10070      * @param event The motion event to be dispatched.
10071      * @return True if the event was handled by the view, false otherwise.
10072      */
dispatchTrackballEvent(MotionEvent event)10073     public boolean dispatchTrackballEvent(MotionEvent event) {
10074         if (mInputEventConsistencyVerifier != null) {
10075             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10076         }
10077 
10078         return onTrackballEvent(event);
10079     }
10080 
10081     /**
10082      * Dispatch a generic motion event.
10083      * <p>
10084      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10085      * are delivered to the view under the pointer.  All other generic motion events are
10086      * delivered to the focused view.  Hover events are handled specially and are delivered
10087      * to {@link #onHoverEvent(MotionEvent)}.
10088      * </p>
10089      *
10090      * @param event The motion event to be dispatched.
10091      * @return True if the event was handled by the view, false otherwise.
10092      */
dispatchGenericMotionEvent(MotionEvent event)10093     public boolean dispatchGenericMotionEvent(MotionEvent event) {
10094         if (mInputEventConsistencyVerifier != null) {
10095             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10096         }
10097 
10098         final int source = event.getSource();
10099         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10100             final int action = event.getAction();
10101             if (action == MotionEvent.ACTION_HOVER_ENTER
10102                     || action == MotionEvent.ACTION_HOVER_MOVE
10103                     || action == MotionEvent.ACTION_HOVER_EXIT) {
10104                 if (dispatchHoverEvent(event)) {
10105                     return true;
10106                 }
10107             } else if (dispatchGenericPointerEvent(event)) {
10108                 return true;
10109             }
10110         } else if (dispatchGenericFocusedEvent(event)) {
10111             return true;
10112         }
10113 
10114         if (dispatchGenericMotionEventInternal(event)) {
10115             return true;
10116         }
10117 
10118         if (mInputEventConsistencyVerifier != null) {
10119             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10120         }
10121         return false;
10122     }
10123 
dispatchGenericMotionEventInternal(MotionEvent event)10124     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10125         //noinspection SimplifiableIfStatement
10126         ListenerInfo li = mListenerInfo;
10127         if (li != null && li.mOnGenericMotionListener != null
10128                 && (mViewFlags & ENABLED_MASK) == ENABLED
10129                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10130             return true;
10131         }
10132 
10133         if (onGenericMotionEvent(event)) {
10134             return true;
10135         }
10136 
10137         final int actionButton = event.getActionButton();
10138         switch (event.getActionMasked()) {
10139             case MotionEvent.ACTION_BUTTON_PRESS:
10140                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10141                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10142                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10143                     if (performContextClick(event.getX(), event.getY())) {
10144                         mInContextButtonPress = true;
10145                         setPressed(true, event.getX(), event.getY());
10146                         removeTapCallback();
10147                         removeLongPressCallback();
10148                         return true;
10149                     }
10150                 }
10151                 break;
10152 
10153             case MotionEvent.ACTION_BUTTON_RELEASE:
10154                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10155                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10156                     mInContextButtonPress = false;
10157                     mIgnoreNextUpEvent = true;
10158                 }
10159                 break;
10160         }
10161 
10162         if (mInputEventConsistencyVerifier != null) {
10163             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10164         }
10165         return false;
10166     }
10167 
10168     /**
10169      * Dispatch a hover event.
10170      * <p>
10171      * Do not call this method directly.
10172      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10173      * </p>
10174      *
10175      * @param event The motion event to be dispatched.
10176      * @return True if the event was handled by the view, false otherwise.
10177      */
dispatchHoverEvent(MotionEvent event)10178     protected boolean dispatchHoverEvent(MotionEvent event) {
10179         ListenerInfo li = mListenerInfo;
10180         //noinspection SimplifiableIfStatement
10181         if (li != null && li.mOnHoverListener != null
10182                 && (mViewFlags & ENABLED_MASK) == ENABLED
10183                 && li.mOnHoverListener.onHover(this, event)) {
10184             return true;
10185         }
10186 
10187         return onHoverEvent(event);
10188     }
10189 
10190     /**
10191      * Returns true if the view has a child to which it has recently sent
10192      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10193      * it does not have a hovered child, then it must be the innermost hovered view.
10194      * @hide
10195      */
hasHoveredChild()10196     protected boolean hasHoveredChild() {
10197         return false;
10198     }
10199 
10200     /**
10201      * Dispatch a generic motion event to the view under the first pointer.
10202      * <p>
10203      * Do not call this method directly.
10204      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10205      * </p>
10206      *
10207      * @param event The motion event to be dispatched.
10208      * @return True if the event was handled by the view, false otherwise.
10209      */
dispatchGenericPointerEvent(MotionEvent event)10210     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10211         return false;
10212     }
10213 
10214     /**
10215      * Dispatch a generic motion event to the currently focused view.
10216      * <p>
10217      * Do not call this method directly.
10218      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10219      * </p>
10220      *
10221      * @param event The motion event to be dispatched.
10222      * @return True if the event was handled by the view, false otherwise.
10223      */
dispatchGenericFocusedEvent(MotionEvent event)10224     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10225         return false;
10226     }
10227 
10228     /**
10229      * Dispatch a pointer event.
10230      * <p>
10231      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10232      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10233      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10234      * and should not be expected to handle other pointing device features.
10235      * </p>
10236      *
10237      * @param event The motion event to be dispatched.
10238      * @return True if the event was handled by the view, false otherwise.
10239      * @hide
10240      */
dispatchPointerEvent(MotionEvent event)10241     public final boolean dispatchPointerEvent(MotionEvent event) {
10242         if (event.isTouchEvent()) {
10243             return dispatchTouchEvent(event);
10244         } else {
10245             return dispatchGenericMotionEvent(event);
10246         }
10247     }
10248 
10249     /**
10250      * Called when the window containing this view gains or loses window focus.
10251      * ViewGroups should override to route to their children.
10252      *
10253      * @param hasFocus True if the window containing this view now has focus,
10254      *        false otherwise.
10255      */
dispatchWindowFocusChanged(boolean hasFocus)10256     public void dispatchWindowFocusChanged(boolean hasFocus) {
10257         onWindowFocusChanged(hasFocus);
10258     }
10259 
10260     /**
10261      * Called when the window containing this view gains or loses focus.  Note
10262      * that this is separate from view focus: to receive key events, both
10263      * your view and its window must have focus.  If a window is displayed
10264      * on top of yours that takes input focus, then your own window will lose
10265      * focus but the view focus will remain unchanged.
10266      *
10267      * @param hasWindowFocus True if the window containing this view now has
10268      *        focus, false otherwise.
10269      */
onWindowFocusChanged(boolean hasWindowFocus)10270     public void onWindowFocusChanged(boolean hasWindowFocus) {
10271         InputMethodManager imm = InputMethodManager.peekInstance();
10272         if (!hasWindowFocus) {
10273             if (isPressed()) {
10274                 setPressed(false);
10275             }
10276             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10277                 imm.focusOut(this);
10278             }
10279             removeLongPressCallback();
10280             removeTapCallback();
10281             onFocusLost();
10282         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10283             imm.focusIn(this);
10284         }
10285         refreshDrawableState();
10286     }
10287 
10288     /**
10289      * Returns true if this view is in a window that currently has window focus.
10290      * Note that this is not the same as the view itself having focus.
10291      *
10292      * @return True if this view is in a window that currently has window focus.
10293      */
hasWindowFocus()10294     public boolean hasWindowFocus() {
10295         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10296     }
10297 
10298     /**
10299      * Dispatch a view visibility change down the view hierarchy.
10300      * ViewGroups should override to route to their children.
10301      * @param changedView The view whose visibility changed. Could be 'this' or
10302      * an ancestor view.
10303      * @param visibility The new visibility of changedView: {@link #VISIBLE},
10304      * {@link #INVISIBLE} or {@link #GONE}.
10305      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)10306     protected void dispatchVisibilityChanged(@NonNull View changedView,
10307             @Visibility int visibility) {
10308         onVisibilityChanged(changedView, visibility);
10309     }
10310 
10311     /**
10312      * Called when the visibility of the view or an ancestor of the view has
10313      * changed.
10314      *
10315      * @param changedView The view whose visibility changed. May be
10316      *                    {@code this} or an ancestor view.
10317      * @param visibility The new visibility, one of {@link #VISIBLE},
10318      *                   {@link #INVISIBLE} or {@link #GONE}.
10319      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)10320     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10321     }
10322 
10323     /**
10324      * Dispatch a hint about whether this view is displayed. For instance, when
10325      * a View moves out of the screen, it might receives a display hint indicating
10326      * the view is not displayed. Applications should not <em>rely</em> on this hint
10327      * as there is no guarantee that they will receive one.
10328      *
10329      * @param hint A hint about whether or not this view is displayed:
10330      * {@link #VISIBLE} or {@link #INVISIBLE}.
10331      */
dispatchDisplayHint(@isibility int hint)10332     public void dispatchDisplayHint(@Visibility int hint) {
10333         onDisplayHint(hint);
10334     }
10335 
10336     /**
10337      * Gives this view a hint about whether is displayed or not. For instance, when
10338      * a View moves out of the screen, it might receives a display hint indicating
10339      * the view is not displayed. Applications should not <em>rely</em> on this hint
10340      * as there is no guarantee that they will receive one.
10341      *
10342      * @param hint A hint about whether or not this view is displayed:
10343      * {@link #VISIBLE} or {@link #INVISIBLE}.
10344      */
onDisplayHint(@isibility int hint)10345     protected void onDisplayHint(@Visibility int hint) {
10346     }
10347 
10348     /**
10349      * Dispatch a window visibility change down the view hierarchy.
10350      * ViewGroups should override to route to their children.
10351      *
10352      * @param visibility The new visibility of the window.
10353      *
10354      * @see #onWindowVisibilityChanged(int)
10355      */
dispatchWindowVisibilityChanged(@isibility int visibility)10356     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10357         onWindowVisibilityChanged(visibility);
10358     }
10359 
10360     /**
10361      * Called when the window containing has change its visibility
10362      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10363      * that this tells you whether or not your window is being made visible
10364      * to the window manager; this does <em>not</em> tell you whether or not
10365      * your window is obscured by other windows on the screen, even if it
10366      * is itself visible.
10367      *
10368      * @param visibility The new visibility of the window.
10369      */
onWindowVisibilityChanged(@isibility int visibility)10370     protected void onWindowVisibilityChanged(@Visibility int visibility) {
10371         if (visibility == VISIBLE) {
10372             initialAwakenScrollBars();
10373         }
10374     }
10375 
10376     /**
10377      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10378      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10379      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10380      *
10381      * @param isVisible true if this view's visibility to the user is uninterrupted by its
10382      *                  ancestors or by window visibility
10383      * @return true if this view is visible to the user, not counting clipping or overlapping
10384      */
dispatchVisibilityAggregated(boolean isVisible)10385     boolean dispatchVisibilityAggregated(boolean isVisible) {
10386         final boolean thisVisible = getVisibility() == VISIBLE;
10387         // If we're not visible but something is telling us we are, ignore it.
10388         if (thisVisible || !isVisible) {
10389             onVisibilityAggregated(isVisible);
10390         }
10391         return thisVisible && isVisible;
10392     }
10393 
10394     /**
10395      * Called when the user-visibility of this View is potentially affected by a change
10396      * to this view itself, an ancestor view or the window this view is attached to.
10397      *
10398      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10399      *                  and this view's window is also visible
10400      */
10401     @CallSuper
onVisibilityAggregated(boolean isVisible)10402     public void onVisibilityAggregated(boolean isVisible) {
10403         if (isVisible && mAttachInfo != null) {
10404             initialAwakenScrollBars();
10405         }
10406 
10407         final Drawable dr = mBackground;
10408         if (dr != null && isVisible != dr.isVisible()) {
10409             dr.setVisible(isVisible, false);
10410         }
10411         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10412         if (fg != null && isVisible != fg.isVisible()) {
10413             fg.setVisible(isVisible, false);
10414         }
10415     }
10416 
10417     /**
10418      * Returns the current visibility of the window this view is attached to
10419      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10420      *
10421      * @return Returns the current visibility of the view's window.
10422      */
10423     @Visibility
getWindowVisibility()10424     public int getWindowVisibility() {
10425         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10426     }
10427 
10428     /**
10429      * Retrieve the overall visible display size in which the window this view is
10430      * attached to has been positioned in.  This takes into account screen
10431      * decorations above the window, for both cases where the window itself
10432      * is being position inside of them or the window is being placed under
10433      * then and covered insets are used for the window to position its content
10434      * inside.  In effect, this tells you the available area where content can
10435      * be placed and remain visible to users.
10436      *
10437      * <p>This function requires an IPC back to the window manager to retrieve
10438      * the requested information, so should not be used in performance critical
10439      * code like drawing.
10440      *
10441      * @param outRect Filled in with the visible display frame.  If the view
10442      * is not attached to a window, this is simply the raw display size.
10443      */
getWindowVisibleDisplayFrame(Rect outRect)10444     public void getWindowVisibleDisplayFrame(Rect outRect) {
10445         if (mAttachInfo != null) {
10446             try {
10447                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10448             } catch (RemoteException e) {
10449                 return;
10450             }
10451             // XXX This is really broken, and probably all needs to be done
10452             // in the window manager, and we need to know more about whether
10453             // we want the area behind or in front of the IME.
10454             final Rect insets = mAttachInfo.mVisibleInsets;
10455             outRect.left += insets.left;
10456             outRect.top += insets.top;
10457             outRect.right -= insets.right;
10458             outRect.bottom -= insets.bottom;
10459             return;
10460         }
10461         // The view is not attached to a display so we don't have a context.
10462         // Make a best guess about the display size.
10463         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10464         d.getRectSize(outRect);
10465     }
10466 
10467     /**
10468      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10469      * is currently in without any insets.
10470      *
10471      * @hide
10472      */
getWindowDisplayFrame(Rect outRect)10473     public void getWindowDisplayFrame(Rect outRect) {
10474         if (mAttachInfo != null) {
10475             try {
10476                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10477             } catch (RemoteException e) {
10478                 return;
10479             }
10480             return;
10481         }
10482         // The view is not attached to a display so we don't have a context.
10483         // Make a best guess about the display size.
10484         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10485         d.getRectSize(outRect);
10486     }
10487 
10488     /**
10489      * Dispatch a notification about a resource configuration change down
10490      * the view hierarchy.
10491      * ViewGroups should override to route to their children.
10492      *
10493      * @param newConfig The new resource configuration.
10494      *
10495      * @see #onConfigurationChanged(android.content.res.Configuration)
10496      */
dispatchConfigurationChanged(Configuration newConfig)10497     public void dispatchConfigurationChanged(Configuration newConfig) {
10498         onConfigurationChanged(newConfig);
10499     }
10500 
10501     /**
10502      * Called when the current configuration of the resources being used
10503      * by the application have changed.  You can use this to decide when
10504      * to reload resources that can changed based on orientation and other
10505      * configuration characteristics.  You only need to use this if you are
10506      * not relying on the normal {@link android.app.Activity} mechanism of
10507      * recreating the activity instance upon a configuration change.
10508      *
10509      * @param newConfig The new resource configuration.
10510      */
onConfigurationChanged(Configuration newConfig)10511     protected void onConfigurationChanged(Configuration newConfig) {
10512     }
10513 
10514     /**
10515      * Private function to aggregate all per-view attributes in to the view
10516      * root.
10517      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)10518     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10519         performCollectViewAttributes(attachInfo, visibility);
10520     }
10521 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)10522     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10523         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10524             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10525                 attachInfo.mKeepScreenOn = true;
10526             }
10527             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10528             ListenerInfo li = mListenerInfo;
10529             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10530                 attachInfo.mHasSystemUiListeners = true;
10531             }
10532         }
10533     }
10534 
needGlobalAttributesUpdate(boolean force)10535     void needGlobalAttributesUpdate(boolean force) {
10536         final AttachInfo ai = mAttachInfo;
10537         if (ai != null && !ai.mRecomputeGlobalAttributes) {
10538             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10539                     || ai.mHasSystemUiListeners) {
10540                 ai.mRecomputeGlobalAttributes = true;
10541             }
10542         }
10543     }
10544 
10545     /**
10546      * Returns whether the device is currently in touch mode.  Touch mode is entered
10547      * once the user begins interacting with the device by touch, and affects various
10548      * things like whether focus is always visible to the user.
10549      *
10550      * @return Whether the device is in touch mode.
10551      */
10552     @ViewDebug.ExportedProperty
isInTouchMode()10553     public boolean isInTouchMode() {
10554         if (mAttachInfo != null) {
10555             return mAttachInfo.mInTouchMode;
10556         } else {
10557             return ViewRootImpl.isInTouchMode();
10558         }
10559     }
10560 
10561     /**
10562      * Returns the context the view is running in, through which it can
10563      * access the current theme, resources, etc.
10564      *
10565      * @return The view's Context.
10566      */
10567     @ViewDebug.CapturedViewProperty
getContext()10568     public final Context getContext() {
10569         return mContext;
10570     }
10571 
10572     /**
10573      * Handle a key event before it is processed by any input method
10574      * associated with the view hierarchy.  This can be used to intercept
10575      * key events in special situations before the IME consumes them; a
10576      * typical example would be handling the BACK key to update the application's
10577      * UI instead of allowing the IME to see it and close itself.
10578      *
10579      * @param keyCode The value in event.getKeyCode().
10580      * @param event Description of the key event.
10581      * @return If you handled the event, return true. If you want to allow the
10582      *         event to be handled by the next receiver, return false.
10583      */
onKeyPreIme(int keyCode, KeyEvent event)10584     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10585         return false;
10586     }
10587 
10588     /**
10589      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10590      * KeyEvent.Callback.onKeyDown()}: perform press of the view
10591      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10592      * is released, if the view is enabled and clickable.
10593      * <p>
10594      * Key presses in software keyboards will generally NOT trigger this
10595      * listener, although some may elect to do so in some situations. Do not
10596      * rely on this to catch software key presses.
10597      *
10598      * @param keyCode a key code that represents the button pressed, from
10599      *                {@link android.view.KeyEvent}
10600      * @param event the KeyEvent object that defines the button action
10601      */
onKeyDown(int keyCode, KeyEvent event)10602     public boolean onKeyDown(int keyCode, KeyEvent event) {
10603         if (KeyEvent.isConfirmKey(keyCode)) {
10604             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10605                 return true;
10606             }
10607 
10608             // Long clickable items don't necessarily have to be clickable.
10609             if (((mViewFlags & CLICKABLE) == CLICKABLE
10610                     || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10611                     && (event.getRepeatCount() == 0)) {
10612                 // For the purposes of menu anchoring and drawable hotspots,
10613                 // key events are considered to be at the center of the view.
10614                 final float x = getWidth() / 2f;
10615                 final float y = getHeight() / 2f;
10616                 setPressed(true, x, y);
10617                 checkForLongClick(0, x, y);
10618                 return true;
10619             }
10620         }
10621 
10622         return false;
10623     }
10624 
10625     /**
10626      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10627      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10628      * the event).
10629      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10630      * although some may elect to do so in some situations. Do not rely on this to
10631      * catch software key presses.
10632      */
onKeyLongPress(int keyCode, KeyEvent event)10633     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10634         return false;
10635     }
10636 
10637     /**
10638      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10639      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10640      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10641      * or {@link KeyEvent#KEYCODE_SPACE} is released.
10642      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10643      * although some may elect to do so in some situations. Do not rely on this to
10644      * catch software key presses.
10645      *
10646      * @param keyCode A key code that represents the button pressed, from
10647      *                {@link android.view.KeyEvent}.
10648      * @param event   The KeyEvent object that defines the button action.
10649      */
onKeyUp(int keyCode, KeyEvent event)10650     public boolean onKeyUp(int keyCode, KeyEvent event) {
10651         if (KeyEvent.isConfirmKey(keyCode)) {
10652             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10653                 return true;
10654             }
10655             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10656                 setPressed(false);
10657 
10658                 if (!mHasPerformedLongPress) {
10659                     // This is a tap, so remove the longpress check
10660                     removeLongPressCallback();
10661                     return performClick();
10662                 }
10663             }
10664         }
10665         return false;
10666     }
10667 
10668     /**
10669      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10670      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10671      * the event).
10672      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10673      * although some may elect to do so in some situations. Do not rely on this to
10674      * catch software key presses.
10675      *
10676      * @param keyCode     A key code that represents the button pressed, from
10677      *                    {@link android.view.KeyEvent}.
10678      * @param repeatCount The number of times the action was made.
10679      * @param event       The KeyEvent object that defines the button action.
10680      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)10681     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10682         return false;
10683     }
10684 
10685     /**
10686      * Called on the focused view when a key shortcut event is not handled.
10687      * Override this method to implement local key shortcuts for the View.
10688      * Key shortcuts can also be implemented by setting the
10689      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10690      *
10691      * @param keyCode The value in event.getKeyCode().
10692      * @param event Description of the key event.
10693      * @return If you handled the event, return true. If you want to allow the
10694      *         event to be handled by the next receiver, return false.
10695      */
onKeyShortcut(int keyCode, KeyEvent event)10696     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10697         return false;
10698     }
10699 
10700     /**
10701      * Check whether the called view is a text editor, in which case it
10702      * would make sense to automatically display a soft input window for
10703      * it.  Subclasses should override this if they implement
10704      * {@link #onCreateInputConnection(EditorInfo)} to return true if
10705      * a call on that method would return a non-null InputConnection, and
10706      * they are really a first-class editor that the user would normally
10707      * start typing on when the go into a window containing your view.
10708      *
10709      * <p>The default implementation always returns false.  This does
10710      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10711      * will not be called or the user can not otherwise perform edits on your
10712      * view; it is just a hint to the system that this is not the primary
10713      * purpose of this view.
10714      *
10715      * @return Returns true if this view is a text editor, else false.
10716      */
onCheckIsTextEditor()10717     public boolean onCheckIsTextEditor() {
10718         return false;
10719     }
10720 
10721     /**
10722      * Create a new InputConnection for an InputMethod to interact
10723      * with the view.  The default implementation returns null, since it doesn't
10724      * support input methods.  You can override this to implement such support.
10725      * This is only needed for views that take focus and text input.
10726      *
10727      * <p>When implementing this, you probably also want to implement
10728      * {@link #onCheckIsTextEditor()} to indicate you will return a
10729      * non-null InputConnection.</p>
10730      *
10731      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10732      * object correctly and in its entirety, so that the connected IME can rely
10733      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10734      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10735      * must be filled in with the correct cursor position for IMEs to work correctly
10736      * with your application.</p>
10737      *
10738      * @param outAttrs Fill in with attribute information about the connection.
10739      */
onCreateInputConnection(EditorInfo outAttrs)10740     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10741         return null;
10742     }
10743 
10744     /**
10745      * Called by the {@link android.view.inputmethod.InputMethodManager}
10746      * when a view who is not the current
10747      * input connection target is trying to make a call on the manager.  The
10748      * default implementation returns false; you can override this to return
10749      * true for certain views if you are performing InputConnection proxying
10750      * to them.
10751      * @param view The View that is making the InputMethodManager call.
10752      * @return Return true to allow the call, false to reject.
10753      */
checkInputConnectionProxy(View view)10754     public boolean checkInputConnectionProxy(View view) {
10755         return false;
10756     }
10757 
10758     /**
10759      * Show the context menu for this view. It is not safe to hold on to the
10760      * menu after returning from this method.
10761      *
10762      * You should normally not overload this method. Overload
10763      * {@link #onCreateContextMenu(ContextMenu)} or define an
10764      * {@link OnCreateContextMenuListener} to add items to the context menu.
10765      *
10766      * @param menu The context menu to populate
10767      */
createContextMenu(ContextMenu menu)10768     public void createContextMenu(ContextMenu menu) {
10769         ContextMenuInfo menuInfo = getContextMenuInfo();
10770 
10771         // Sets the current menu info so all items added to menu will have
10772         // my extra info set.
10773         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10774 
10775         onCreateContextMenu(menu);
10776         ListenerInfo li = mListenerInfo;
10777         if (li != null && li.mOnCreateContextMenuListener != null) {
10778             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10779         }
10780 
10781         // Clear the extra information so subsequent items that aren't mine don't
10782         // have my extra info.
10783         ((MenuBuilder)menu).setCurrentMenuInfo(null);
10784 
10785         if (mParent != null) {
10786             mParent.createContextMenu(menu);
10787         }
10788     }
10789 
10790     /**
10791      * Views should implement this if they have extra information to associate
10792      * with the context menu. The return result is supplied as a parameter to
10793      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10794      * callback.
10795      *
10796      * @return Extra information about the item for which the context menu
10797      *         should be shown. This information will vary across different
10798      *         subclasses of View.
10799      */
getContextMenuInfo()10800     protected ContextMenuInfo getContextMenuInfo() {
10801         return null;
10802     }
10803 
10804     /**
10805      * Views should implement this if the view itself is going to add items to
10806      * the context menu.
10807      *
10808      * @param menu the context menu to populate
10809      */
onCreateContextMenu(ContextMenu menu)10810     protected void onCreateContextMenu(ContextMenu menu) {
10811     }
10812 
10813     /**
10814      * Implement this method to handle trackball motion events.  The
10815      * <em>relative</em> movement of the trackball since the last event
10816      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10817      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10818      * that a movement of 1 corresponds to the user pressing one DPAD key (so
10819      * they will often be fractional values, representing the more fine-grained
10820      * movement information available from a trackball).
10821      *
10822      * @param event The motion event.
10823      * @return True if the event was handled, false otherwise.
10824      */
onTrackballEvent(MotionEvent event)10825     public boolean onTrackballEvent(MotionEvent event) {
10826         return false;
10827     }
10828 
10829     /**
10830      * Implement this method to handle generic motion events.
10831      * <p>
10832      * Generic motion events describe joystick movements, mouse hovers, track pad
10833      * touches, scroll wheel movements and other input events.  The
10834      * {@link MotionEvent#getSource() source} of the motion event specifies
10835      * the class of input that was received.  Implementations of this method
10836      * must examine the bits in the source before processing the event.
10837      * The following code example shows how this is done.
10838      * </p><p>
10839      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10840      * are delivered to the view under the pointer.  All other generic motion events are
10841      * delivered to the focused view.
10842      * </p>
10843      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10844      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10845      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10846      *             // process the joystick movement...
10847      *             return true;
10848      *         }
10849      *     }
10850      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10851      *         switch (event.getAction()) {
10852      *             case MotionEvent.ACTION_HOVER_MOVE:
10853      *                 // process the mouse hover movement...
10854      *                 return true;
10855      *             case MotionEvent.ACTION_SCROLL:
10856      *                 // process the scroll wheel movement...
10857      *                 return true;
10858      *         }
10859      *     }
10860      *     return super.onGenericMotionEvent(event);
10861      * }</pre>
10862      *
10863      * @param event The generic motion event being processed.
10864      * @return True if the event was handled, false otherwise.
10865      */
onGenericMotionEvent(MotionEvent event)10866     public boolean onGenericMotionEvent(MotionEvent event) {
10867         return false;
10868     }
10869 
10870     /**
10871      * Implement this method to handle hover events.
10872      * <p>
10873      * This method is called whenever a pointer is hovering into, over, or out of the
10874      * bounds of a view and the view is not currently being touched.
10875      * Hover events are represented as pointer events with action
10876      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10877      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10878      * </p>
10879      * <ul>
10880      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10881      * when the pointer enters the bounds of the view.</li>
10882      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10883      * when the pointer has already entered the bounds of the view and has moved.</li>
10884      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10885      * when the pointer has exited the bounds of the view or when the pointer is
10886      * about to go down due to a button click, tap, or similar user action that
10887      * causes the view to be touched.</li>
10888      * </ul>
10889      * <p>
10890      * The view should implement this method to return true to indicate that it is
10891      * handling the hover event, such as by changing its drawable state.
10892      * </p><p>
10893      * The default implementation calls {@link #setHovered} to update the hovered state
10894      * of the view when a hover enter or hover exit event is received, if the view
10895      * is enabled and is clickable.  The default implementation also sends hover
10896      * accessibility events.
10897      * </p>
10898      *
10899      * @param event The motion event that describes the hover.
10900      * @return True if the view handled the hover event.
10901      *
10902      * @see #isHovered
10903      * @see #setHovered
10904      * @see #onHoverChanged
10905      */
onHoverEvent(MotionEvent event)10906     public boolean onHoverEvent(MotionEvent event) {
10907         // The root view may receive hover (or touch) events that are outside the bounds of
10908         // the window.  This code ensures that we only send accessibility events for
10909         // hovers that are actually within the bounds of the root view.
10910         final int action = event.getActionMasked();
10911         if (!mSendingHoverAccessibilityEvents) {
10912             if ((action == MotionEvent.ACTION_HOVER_ENTER
10913                     || action == MotionEvent.ACTION_HOVER_MOVE)
10914                     && !hasHoveredChild()
10915                     && pointInView(event.getX(), event.getY())) {
10916                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10917                 mSendingHoverAccessibilityEvents = true;
10918             }
10919         } else {
10920             if (action == MotionEvent.ACTION_HOVER_EXIT
10921                     || (action == MotionEvent.ACTION_MOVE
10922                             && !pointInView(event.getX(), event.getY()))) {
10923                 mSendingHoverAccessibilityEvents = false;
10924                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10925             }
10926         }
10927 
10928         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10929                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
10930                 && isOnScrollbar(event.getX(), event.getY())) {
10931             awakenScrollBars();
10932         }
10933         if (isHoverable()) {
10934             switch (action) {
10935                 case MotionEvent.ACTION_HOVER_ENTER:
10936                     setHovered(true);
10937                     break;
10938                 case MotionEvent.ACTION_HOVER_EXIT:
10939                     setHovered(false);
10940                     break;
10941             }
10942 
10943             // Dispatch the event to onGenericMotionEvent before returning true.
10944             // This is to provide compatibility with existing applications that
10945             // handled HOVER_MOVE events in onGenericMotionEvent and that would
10946             // break because of the new default handling for hoverable views
10947             // in onHoverEvent.
10948             // Note that onGenericMotionEvent will be called by default when
10949             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10950             dispatchGenericMotionEventInternal(event);
10951             // The event was already handled by calling setHovered(), so always
10952             // return true.
10953             return true;
10954         }
10955 
10956         return false;
10957     }
10958 
10959     /**
10960      * Returns true if the view should handle {@link #onHoverEvent}
10961      * by calling {@link #setHovered} to change its hovered state.
10962      *
10963      * @return True if the view is hoverable.
10964      */
isHoverable()10965     private boolean isHoverable() {
10966         final int viewFlags = mViewFlags;
10967         if ((viewFlags & ENABLED_MASK) == DISABLED) {
10968             return false;
10969         }
10970 
10971         return (viewFlags & CLICKABLE) == CLICKABLE
10972                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10973                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10974     }
10975 
10976     /**
10977      * Returns true if the view is currently hovered.
10978      *
10979      * @return True if the view is currently hovered.
10980      *
10981      * @see #setHovered
10982      * @see #onHoverChanged
10983      */
10984     @ViewDebug.ExportedProperty
isHovered()10985     public boolean isHovered() {
10986         return (mPrivateFlags & PFLAG_HOVERED) != 0;
10987     }
10988 
10989     /**
10990      * Sets whether the view is currently hovered.
10991      * <p>
10992      * Calling this method also changes the drawable state of the view.  This
10993      * enables the view to react to hover by using different drawable resources
10994      * to change its appearance.
10995      * </p><p>
10996      * The {@link #onHoverChanged} method is called when the hovered state changes.
10997      * </p>
10998      *
10999      * @param hovered True if the view is hovered.
11000      *
11001      * @see #isHovered
11002      * @see #onHoverChanged
11003      */
setHovered(boolean hovered)11004     public void setHovered(boolean hovered) {
11005         if (hovered) {
11006             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11007                 mPrivateFlags |= PFLAG_HOVERED;
11008                 refreshDrawableState();
11009                 onHoverChanged(true);
11010             }
11011         } else {
11012             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11013                 mPrivateFlags &= ~PFLAG_HOVERED;
11014                 refreshDrawableState();
11015                 onHoverChanged(false);
11016             }
11017         }
11018     }
11019 
11020     /**
11021      * Implement this method to handle hover state changes.
11022      * <p>
11023      * This method is called whenever the hover state changes as a result of a
11024      * call to {@link #setHovered}.
11025      * </p>
11026      *
11027      * @param hovered The current hover state, as returned by {@link #isHovered}.
11028      *
11029      * @see #isHovered
11030      * @see #setHovered
11031      */
onHoverChanged(boolean hovered)11032     public void onHoverChanged(boolean hovered) {
11033     }
11034 
11035     /**
11036      * Handles scroll bar dragging by mouse input.
11037      *
11038      * @hide
11039      * @param event The motion event.
11040      *
11041      * @return true if the event was handled as a scroll bar dragging, false otherwise.
11042      */
handleScrollBarDragging(MotionEvent event)11043     protected boolean handleScrollBarDragging(MotionEvent event) {
11044         if (mScrollCache == null) {
11045             return false;
11046         }
11047         final float x = event.getX();
11048         final float y = event.getY();
11049         final int action = event.getAction();
11050         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11051                 && action != MotionEvent.ACTION_DOWN)
11052                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11053                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11054             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11055             return false;
11056         }
11057 
11058         switch (action) {
11059             case MotionEvent.ACTION_MOVE:
11060                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11061                     return false;
11062                 }
11063                 if (mScrollCache.mScrollBarDraggingState
11064                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11065                     final Rect bounds = mScrollCache.mScrollBarBounds;
11066                     getVerticalScrollBarBounds(bounds);
11067                     final int range = computeVerticalScrollRange();
11068                     final int offset = computeVerticalScrollOffset();
11069                     final int extent = computeVerticalScrollExtent();
11070 
11071                     final int thumbLength = ScrollBarUtils.getThumbLength(
11072                             bounds.height(), bounds.width(), extent, range);
11073                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
11074                             bounds.height(), thumbLength, extent, range, offset);
11075 
11076                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
11077                     final float maxThumbOffset = bounds.height() - thumbLength;
11078                     final float newThumbOffset =
11079                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11080                     final int height = getHeight();
11081                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11082                             && height > 0 && extent > 0) {
11083                         final int newY = Math.round((range - extent)
11084                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11085                         if (newY != getScrollY()) {
11086                             mScrollCache.mScrollBarDraggingPos = y;
11087                             setScrollY(newY);
11088                         }
11089                     }
11090                     return true;
11091                 }
11092                 if (mScrollCache.mScrollBarDraggingState
11093                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11094                     final Rect bounds = mScrollCache.mScrollBarBounds;
11095                     getHorizontalScrollBarBounds(bounds);
11096                     final int range = computeHorizontalScrollRange();
11097                     final int offset = computeHorizontalScrollOffset();
11098                     final int extent = computeHorizontalScrollExtent();
11099 
11100                     final int thumbLength = ScrollBarUtils.getThumbLength(
11101                             bounds.width(), bounds.height(), extent, range);
11102                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
11103                             bounds.width(), thumbLength, extent, range, offset);
11104 
11105                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
11106                     final float maxThumbOffset = bounds.width() - thumbLength;
11107                     final float newThumbOffset =
11108                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11109                     final int width = getWidth();
11110                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11111                             && width > 0 && extent > 0) {
11112                         final int newX = Math.round((range - extent)
11113                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11114                         if (newX != getScrollX()) {
11115                             mScrollCache.mScrollBarDraggingPos = x;
11116                             setScrollX(newX);
11117                         }
11118                     }
11119                     return true;
11120                 }
11121             case MotionEvent.ACTION_DOWN:
11122                 if (mScrollCache.state == ScrollabilityCache.OFF) {
11123                     return false;
11124                 }
11125                 if (isOnVerticalScrollbarThumb(x, y)) {
11126                     mScrollCache.mScrollBarDraggingState =
11127                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11128                     mScrollCache.mScrollBarDraggingPos = y;
11129                     return true;
11130                 }
11131                 if (isOnHorizontalScrollbarThumb(x, y)) {
11132                     mScrollCache.mScrollBarDraggingState =
11133                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11134                     mScrollCache.mScrollBarDraggingPos = x;
11135                     return true;
11136                 }
11137         }
11138         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11139         return false;
11140     }
11141 
11142     /**
11143      * Implement this method to handle touch screen motion events.
11144      * <p>
11145      * If this method is used to detect click actions, it is recommended that
11146      * the actions be performed by implementing and calling
11147      * {@link #performClick()}. This will ensure consistent system behavior,
11148      * including:
11149      * <ul>
11150      * <li>obeying click sound preferences
11151      * <li>dispatching OnClickListener calls
11152      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11153      * accessibility features are enabled
11154      * </ul>
11155      *
11156      * @param event The motion event.
11157      * @return True if the event was handled, false otherwise.
11158      */
onTouchEvent(MotionEvent event)11159     public boolean onTouchEvent(MotionEvent event) {
11160         final float x = event.getX();
11161         final float y = event.getY();
11162         final int viewFlags = mViewFlags;
11163         final int action = event.getAction();
11164 
11165         if ((viewFlags & ENABLED_MASK) == DISABLED) {
11166             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11167                 setPressed(false);
11168             }
11169             // A disabled view that is clickable still consumes the touch
11170             // events, it just doesn't respond to them.
11171             return (((viewFlags & CLICKABLE) == CLICKABLE
11172                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11173                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11174         }
11175         if (mTouchDelegate != null) {
11176             if (mTouchDelegate.onTouchEvent(event)) {
11177                 return true;
11178             }
11179         }
11180 
11181         if (((viewFlags & CLICKABLE) == CLICKABLE ||
11182                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11183                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11184             switch (action) {
11185                 case MotionEvent.ACTION_UP:
11186                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11187                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11188                         // take focus if we don't have it already and we should in
11189                         // touch mode.
11190                         boolean focusTaken = false;
11191                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11192                             focusTaken = requestFocus();
11193                         }
11194 
11195                         if (prepressed) {
11196                             // The button is being released before we actually
11197                             // showed it as pressed.  Make it show the pressed
11198                             // state now (before scheduling the click) to ensure
11199                             // the user sees it.
11200                             setPressed(true, x, y);
11201                        }
11202 
11203                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11204                             // This is a tap, so remove the longpress check
11205                             removeLongPressCallback();
11206 
11207                             // Only perform take click actions if we were in the pressed state
11208                             if (!focusTaken) {
11209                                 // Use a Runnable and post this rather than calling
11210                                 // performClick directly. This lets other visual state
11211                                 // of the view update before click actions start.
11212                                 if (mPerformClick == null) {
11213                                     mPerformClick = new PerformClick();
11214                                 }
11215                                 if (!post(mPerformClick)) {
11216                                     performClick();
11217                                 }
11218                             }
11219                         }
11220 
11221                         if (mUnsetPressedState == null) {
11222                             mUnsetPressedState = new UnsetPressedState();
11223                         }
11224 
11225                         if (prepressed) {
11226                             postDelayed(mUnsetPressedState,
11227                                     ViewConfiguration.getPressedStateDuration());
11228                         } else if (!post(mUnsetPressedState)) {
11229                             // If the post failed, unpress right now
11230                             mUnsetPressedState.run();
11231                         }
11232 
11233                         removeTapCallback();
11234                     }
11235                     mIgnoreNextUpEvent = false;
11236                     break;
11237 
11238                 case MotionEvent.ACTION_DOWN:
11239                     mHasPerformedLongPress = false;
11240 
11241                     if (performButtonActionOnTouchDown(event)) {
11242                         break;
11243                     }
11244 
11245                     // Walk up the hierarchy to determine if we're inside a scrolling container.
11246                     boolean isInScrollingContainer = isInScrollingContainer();
11247 
11248                     // For views inside a scrolling container, delay the pressed feedback for
11249                     // a short period in case this is a scroll.
11250                     if (isInScrollingContainer) {
11251                         mPrivateFlags |= PFLAG_PREPRESSED;
11252                         if (mPendingCheckForTap == null) {
11253                             mPendingCheckForTap = new CheckForTap();
11254                         }
11255                         mPendingCheckForTap.x = event.getX();
11256                         mPendingCheckForTap.y = event.getY();
11257                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11258                     } else {
11259                         // Not inside a scrolling container, so show the feedback right away
11260                         setPressed(true, x, y);
11261                         checkForLongClick(0, x, y);
11262                     }
11263                     break;
11264 
11265                 case MotionEvent.ACTION_CANCEL:
11266                     setPressed(false);
11267                     removeTapCallback();
11268                     removeLongPressCallback();
11269                     mInContextButtonPress = false;
11270                     mHasPerformedLongPress = false;
11271                     mIgnoreNextUpEvent = false;
11272                     break;
11273 
11274                 case MotionEvent.ACTION_MOVE:
11275                     drawableHotspotChanged(x, y);
11276 
11277                     // Be lenient about moving outside of buttons
11278                     if (!pointInView(x, y, mTouchSlop)) {
11279                         // Outside button
11280                         removeTapCallback();
11281                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11282                             // Remove any future long press/tap checks
11283                             removeLongPressCallback();
11284 
11285                             setPressed(false);
11286                         }
11287                     }
11288                     break;
11289             }
11290 
11291             return true;
11292         }
11293 
11294         return false;
11295     }
11296 
11297     /**
11298      * @hide
11299      */
isInScrollingContainer()11300     public boolean isInScrollingContainer() {
11301         ViewParent p = getParent();
11302         while (p != null && p instanceof ViewGroup) {
11303             if (((ViewGroup) p).shouldDelayChildPressedState()) {
11304                 return true;
11305             }
11306             p = p.getParent();
11307         }
11308         return false;
11309     }
11310 
11311     /**
11312      * Remove the longpress detection timer.
11313      */
removeLongPressCallback()11314     private void removeLongPressCallback() {
11315         if (mPendingCheckForLongPress != null) {
11316           removeCallbacks(mPendingCheckForLongPress);
11317         }
11318     }
11319 
11320     /**
11321      * Remove the pending click action
11322      */
removePerformClickCallback()11323     private void removePerformClickCallback() {
11324         if (mPerformClick != null) {
11325             removeCallbacks(mPerformClick);
11326         }
11327     }
11328 
11329     /**
11330      * Remove the prepress detection timer.
11331      */
removeUnsetPressCallback()11332     private void removeUnsetPressCallback() {
11333         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11334             setPressed(false);
11335             removeCallbacks(mUnsetPressedState);
11336         }
11337     }
11338 
11339     /**
11340      * Remove the tap detection timer.
11341      */
removeTapCallback()11342     private void removeTapCallback() {
11343         if (mPendingCheckForTap != null) {
11344             mPrivateFlags &= ~PFLAG_PREPRESSED;
11345             removeCallbacks(mPendingCheckForTap);
11346         }
11347     }
11348 
11349     /**
11350      * Cancels a pending long press.  Your subclass can use this if you
11351      * want the context menu to come up if the user presses and holds
11352      * at the same place, but you don't want it to come up if they press
11353      * and then move around enough to cause scrolling.
11354      */
cancelLongPress()11355     public void cancelLongPress() {
11356         removeLongPressCallback();
11357 
11358         /*
11359          * The prepressed state handled by the tap callback is a display
11360          * construct, but the tap callback will post a long press callback
11361          * less its own timeout. Remove it here.
11362          */
11363         removeTapCallback();
11364     }
11365 
11366     /**
11367      * Remove the pending callback for sending a
11368      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11369      */
removeSendViewScrolledAccessibilityEventCallback()11370     private void removeSendViewScrolledAccessibilityEventCallback() {
11371         if (mSendViewScrolledAccessibilityEvent != null) {
11372             removeCallbacks(mSendViewScrolledAccessibilityEvent);
11373             mSendViewScrolledAccessibilityEvent.mIsPending = false;
11374         }
11375     }
11376 
11377     /**
11378      * Sets the TouchDelegate for this View.
11379      */
setTouchDelegate(TouchDelegate delegate)11380     public void setTouchDelegate(TouchDelegate delegate) {
11381         mTouchDelegate = delegate;
11382     }
11383 
11384     /**
11385      * Gets the TouchDelegate for this View.
11386      */
getTouchDelegate()11387     public TouchDelegate getTouchDelegate() {
11388         return mTouchDelegate;
11389     }
11390 
11391     /**
11392      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11393      *
11394      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11395      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11396      * available. This method should only be called for touch events.
11397      *
11398      * <p class="note">This api is not intended for most applications. Buffered dispatch
11399      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11400      * streams will not improve your input latency. Side effects include: increased latency,
11401      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11402      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11403      * you.</p>
11404      */
requestUnbufferedDispatch(MotionEvent event)11405     public final void requestUnbufferedDispatch(MotionEvent event) {
11406         final int action = event.getAction();
11407         if (mAttachInfo == null
11408                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11409                 || !event.isTouchEvent()) {
11410             return;
11411         }
11412         mAttachInfo.mUnbufferedDispatchRequested = true;
11413     }
11414 
11415     /**
11416      * Set flags controlling behavior of this view.
11417      *
11418      * @param flags Constant indicating the value which should be set
11419      * @param mask Constant indicating the bit range that should be changed
11420      */
setFlags(int flags, int mask)11421     void setFlags(int flags, int mask) {
11422         final boolean accessibilityEnabled =
11423                 AccessibilityManager.getInstance(mContext).isEnabled();
11424         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11425 
11426         int old = mViewFlags;
11427         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11428 
11429         int changed = mViewFlags ^ old;
11430         if (changed == 0) {
11431             return;
11432         }
11433         int privateFlags = mPrivateFlags;
11434 
11435         /* Check if the FOCUSABLE bit has changed */
11436         if (((changed & FOCUSABLE_MASK) != 0) &&
11437                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11438             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11439                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11440                 /* Give up focus if we are no longer focusable */
11441                 clearFocus();
11442             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11443                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11444                 /*
11445                  * Tell the view system that we are now available to take focus
11446                  * if no one else already has it.
11447                  */
11448                 if (mParent != null) mParent.focusableViewAvailable(this);
11449             }
11450         }
11451 
11452         final int newVisibility = flags & VISIBILITY_MASK;
11453         if (newVisibility == VISIBLE) {
11454             if ((changed & VISIBILITY_MASK) != 0) {
11455                 /*
11456                  * If this view is becoming visible, invalidate it in case it changed while
11457                  * it was not visible. Marking it drawn ensures that the invalidation will
11458                  * go through.
11459                  */
11460                 mPrivateFlags |= PFLAG_DRAWN;
11461                 invalidate(true);
11462 
11463                 needGlobalAttributesUpdate(true);
11464 
11465                 // a view becoming visible is worth notifying the parent
11466                 // about in case nothing has focus.  even if this specific view
11467                 // isn't focusable, it may contain something that is, so let
11468                 // the root view try to give this focus if nothing else does.
11469                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11470                     mParent.focusableViewAvailable(this);
11471                 }
11472             }
11473         }
11474 
11475         /* Check if the GONE bit has changed */
11476         if ((changed & GONE) != 0) {
11477             needGlobalAttributesUpdate(false);
11478             requestLayout();
11479 
11480             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11481                 if (hasFocus()) clearFocus();
11482                 clearAccessibilityFocus();
11483                 destroyDrawingCache();
11484                 if (mParent instanceof View) {
11485                     // GONE views noop invalidation, so invalidate the parent
11486                     ((View) mParent).invalidate(true);
11487                 }
11488                 // Mark the view drawn to ensure that it gets invalidated properly the next
11489                 // time it is visible and gets invalidated
11490                 mPrivateFlags |= PFLAG_DRAWN;
11491             }
11492             if (mAttachInfo != null) {
11493                 mAttachInfo.mViewVisibilityChanged = true;
11494             }
11495         }
11496 
11497         /* Check if the VISIBLE bit has changed */
11498         if ((changed & INVISIBLE) != 0) {
11499             needGlobalAttributesUpdate(false);
11500             /*
11501              * If this view is becoming invisible, set the DRAWN flag so that
11502              * the next invalidate() will not be skipped.
11503              */
11504             mPrivateFlags |= PFLAG_DRAWN;
11505 
11506             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11507                 // root view becoming invisible shouldn't clear focus and accessibility focus
11508                 if (getRootView() != this) {
11509                     if (hasFocus()) clearFocus();
11510                     clearAccessibilityFocus();
11511                 }
11512             }
11513             if (mAttachInfo != null) {
11514                 mAttachInfo.mViewVisibilityChanged = true;
11515             }
11516         }
11517 
11518         if ((changed & VISIBILITY_MASK) != 0) {
11519             // If the view is invisible, cleanup its display list to free up resources
11520             if (newVisibility != VISIBLE && mAttachInfo != null) {
11521                 cleanupDraw();
11522             }
11523 
11524             if (mParent instanceof ViewGroup) {
11525                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
11526                         (changed & VISIBILITY_MASK), newVisibility);
11527                 ((View) mParent).invalidate(true);
11528             } else if (mParent != null) {
11529                 mParent.invalidateChild(this, null);
11530             }
11531 
11532             if (mAttachInfo != null) {
11533                 dispatchVisibilityChanged(this, newVisibility);
11534 
11535                 // Aggregated visibility changes are dispatched to attached views
11536                 // in visible windows where the parent is currently shown/drawn
11537                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11538                 // discounting clipping or overlapping. This makes it a good place
11539                 // to change animation states.
11540                 if (mParent != null && getWindowVisibility() == VISIBLE &&
11541                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11542                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
11543                 }
11544                 notifySubtreeAccessibilityStateChangedIfNeeded();
11545             }
11546         }
11547 
11548         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11549             destroyDrawingCache();
11550         }
11551 
11552         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11553             destroyDrawingCache();
11554             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11555             invalidateParentCaches();
11556         }
11557 
11558         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11559             destroyDrawingCache();
11560             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11561         }
11562 
11563         if ((changed & DRAW_MASK) != 0) {
11564             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11565                 if (mBackground != null
11566                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11567                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11568                 } else {
11569                     mPrivateFlags |= PFLAG_SKIP_DRAW;
11570                 }
11571             } else {
11572                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11573             }
11574             requestLayout();
11575             invalidate(true);
11576         }
11577 
11578         if ((changed & KEEP_SCREEN_ON) != 0) {
11579             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11580                 mParent.recomputeViewAttributes(this);
11581             }
11582         }
11583 
11584         if (accessibilityEnabled) {
11585             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11586                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11587                     || (changed & CONTEXT_CLICKABLE) != 0) {
11588                 if (oldIncludeForAccessibility != includeForAccessibility()) {
11589                     notifySubtreeAccessibilityStateChangedIfNeeded();
11590                 } else {
11591                     notifyViewAccessibilityStateChangedIfNeeded(
11592                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11593                 }
11594             } else if ((changed & ENABLED_MASK) != 0) {
11595                 notifyViewAccessibilityStateChangedIfNeeded(
11596                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11597             }
11598         }
11599     }
11600 
11601     /**
11602      * Change the view's z order in the tree, so it's on top of other sibling
11603      * views. This ordering change may affect layout, if the parent container
11604      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11605      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11606      * method should be followed by calls to {@link #requestLayout()} and
11607      * {@link View#invalidate()} on the view's parent to force the parent to redraw
11608      * with the new child ordering.
11609      *
11610      * @see ViewGroup#bringChildToFront(View)
11611      */
bringToFront()11612     public void bringToFront() {
11613         if (mParent != null) {
11614             mParent.bringChildToFront(this);
11615         }
11616     }
11617 
11618     /**
11619      * This is called in response to an internal scroll in this view (i.e., the
11620      * view scrolled its own contents). This is typically as a result of
11621      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11622      * called.
11623      *
11624      * @param l Current horizontal scroll origin.
11625      * @param t Current vertical scroll origin.
11626      * @param oldl Previous horizontal scroll origin.
11627      * @param oldt Previous vertical scroll origin.
11628      */
onScrollChanged(int l, int t, int oldl, int oldt)11629     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11630         notifySubtreeAccessibilityStateChangedIfNeeded();
11631 
11632         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11633             postSendViewScrolledAccessibilityEventCallback();
11634         }
11635 
11636         mBackgroundSizeChanged = true;
11637         if (mForegroundInfo != null) {
11638             mForegroundInfo.mBoundsChanged = true;
11639         }
11640 
11641         final AttachInfo ai = mAttachInfo;
11642         if (ai != null) {
11643             ai.mViewScrollChanged = true;
11644         }
11645 
11646         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11647             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11648         }
11649     }
11650 
11651     /**
11652      * Interface definition for a callback to be invoked when the scroll
11653      * X or Y positions of a view change.
11654      * <p>
11655      * <b>Note:</b> Some views handle scrolling independently from View and may
11656      * have their own separate listeners for scroll-type events. For example,
11657      * {@link android.widget.ListView ListView} allows clients to register an
11658      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11659      * to listen for changes in list scroll position.
11660      *
11661      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11662      */
11663     public interface OnScrollChangeListener {
11664         /**
11665          * Called when the scroll position of a view changes.
11666          *
11667          * @param v The view whose scroll position has changed.
11668          * @param scrollX Current horizontal scroll origin.
11669          * @param scrollY Current vertical scroll origin.
11670          * @param oldScrollX Previous horizontal scroll origin.
11671          * @param oldScrollY Previous vertical scroll origin.
11672          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)11673         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11674     }
11675 
11676     /**
11677      * Interface definition for a callback to be invoked when the layout bounds of a view
11678      * changes due to layout processing.
11679      */
11680     public interface OnLayoutChangeListener {
11681         /**
11682          * Called when the layout bounds of a view changes due to layout processing.
11683          *
11684          * @param v The view whose bounds have changed.
11685          * @param left The new value of the view's left property.
11686          * @param top The new value of the view's top property.
11687          * @param right The new value of the view's right property.
11688          * @param bottom The new value of the view's bottom property.
11689          * @param oldLeft The previous value of the view's left property.
11690          * @param oldTop The previous value of the view's top property.
11691          * @param oldRight The previous value of the view's right property.
11692          * @param oldBottom The previous value of the view's bottom property.
11693          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)11694         void onLayoutChange(View v, int left, int top, int right, int bottom,
11695             int oldLeft, int oldTop, int oldRight, int oldBottom);
11696     }
11697 
11698     /**
11699      * This is called during layout when the size of this view has changed. If
11700      * you were just added to the view hierarchy, you're called with the old
11701      * values of 0.
11702      *
11703      * @param w Current width of this view.
11704      * @param h Current height of this view.
11705      * @param oldw Old width of this view.
11706      * @param oldh Old height of this view.
11707      */
onSizeChanged(int w, int h, int oldw, int oldh)11708     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11709     }
11710 
11711     /**
11712      * Called by draw to draw the child views. This may be overridden
11713      * by derived classes to gain control just before its children are drawn
11714      * (but after its own view has been drawn).
11715      * @param canvas the canvas on which to draw the view
11716      */
dispatchDraw(Canvas canvas)11717     protected void dispatchDraw(Canvas canvas) {
11718 
11719     }
11720 
11721     /**
11722      * Gets the parent of this view. Note that the parent is a
11723      * ViewParent and not necessarily a View.
11724      *
11725      * @return Parent of this view.
11726      */
getParent()11727     public final ViewParent getParent() {
11728         return mParent;
11729     }
11730 
11731     /**
11732      * Set the horizontal scrolled position of your view. This will cause a call to
11733      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11734      * invalidated.
11735      * @param value the x position to scroll to
11736      */
setScrollX(int value)11737     public void setScrollX(int value) {
11738         scrollTo(value, mScrollY);
11739     }
11740 
11741     /**
11742      * Set the vertical scrolled position of your view. This will cause a call to
11743      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11744      * invalidated.
11745      * @param value the y position to scroll to
11746      */
setScrollY(int value)11747     public void setScrollY(int value) {
11748         scrollTo(mScrollX, value);
11749     }
11750 
11751     /**
11752      * Return the scrolled left position of this view. This is the left edge of
11753      * the displayed part of your view. You do not need to draw any pixels
11754      * farther left, since those are outside of the frame of your view on
11755      * screen.
11756      *
11757      * @return The left edge of the displayed part of your view, in pixels.
11758      */
getScrollX()11759     public final int getScrollX() {
11760         return mScrollX;
11761     }
11762 
11763     /**
11764      * Return the scrolled top position of this view. This is the top edge of
11765      * the displayed part of your view. You do not need to draw any pixels above
11766      * it, since those are outside of the frame of your view on screen.
11767      *
11768      * @return The top edge of the displayed part of your view, in pixels.
11769      */
getScrollY()11770     public final int getScrollY() {
11771         return mScrollY;
11772     }
11773 
11774     /**
11775      * Return the width of the your view.
11776      *
11777      * @return The width of your view, in pixels.
11778      */
11779     @ViewDebug.ExportedProperty(category = "layout")
getWidth()11780     public final int getWidth() {
11781         return mRight - mLeft;
11782     }
11783 
11784     /**
11785      * Return the height of your view.
11786      *
11787      * @return The height of your view, in pixels.
11788      */
11789     @ViewDebug.ExportedProperty(category = "layout")
getHeight()11790     public final int getHeight() {
11791         return mBottom - mTop;
11792     }
11793 
11794     /**
11795      * Return the visible drawing bounds of your view. Fills in the output
11796      * rectangle with the values from getScrollX(), getScrollY(),
11797      * getWidth(), and getHeight(). These bounds do not account for any
11798      * transformation properties currently set on the view, such as
11799      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11800      *
11801      * @param outRect The (scrolled) drawing bounds of the view.
11802      */
getDrawingRect(Rect outRect)11803     public void getDrawingRect(Rect outRect) {
11804         outRect.left = mScrollX;
11805         outRect.top = mScrollY;
11806         outRect.right = mScrollX + (mRight - mLeft);
11807         outRect.bottom = mScrollY + (mBottom - mTop);
11808     }
11809 
11810     /**
11811      * Like {@link #getMeasuredWidthAndState()}, but only returns the
11812      * raw width component (that is the result is masked by
11813      * {@link #MEASURED_SIZE_MASK}).
11814      *
11815      * @return The raw measured width of this view.
11816      */
getMeasuredWidth()11817     public final int getMeasuredWidth() {
11818         return mMeasuredWidth & MEASURED_SIZE_MASK;
11819     }
11820 
11821     /**
11822      * Return the full width measurement information for this view as computed
11823      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11824      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11825      * This should be used during measurement and layout calculations only. Use
11826      * {@link #getWidth()} to see how wide a view is after layout.
11827      *
11828      * @return The measured width of this view as a bit mask.
11829      */
11830     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11831             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11832                     name = "MEASURED_STATE_TOO_SMALL"),
11833     })
getMeasuredWidthAndState()11834     public final int getMeasuredWidthAndState() {
11835         return mMeasuredWidth;
11836     }
11837 
11838     /**
11839      * Like {@link #getMeasuredHeightAndState()}, but only returns the
11840      * raw width component (that is the result is masked by
11841      * {@link #MEASURED_SIZE_MASK}).
11842      *
11843      * @return The raw measured height of this view.
11844      */
getMeasuredHeight()11845     public final int getMeasuredHeight() {
11846         return mMeasuredHeight & MEASURED_SIZE_MASK;
11847     }
11848 
11849     /**
11850      * Return the full height measurement information for this view as computed
11851      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11852      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11853      * This should be used during measurement and layout calculations only. Use
11854      * {@link #getHeight()} to see how wide a view is after layout.
11855      *
11856      * @return The measured width of this view as a bit mask.
11857      */
11858     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11859             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11860                     name = "MEASURED_STATE_TOO_SMALL"),
11861     })
getMeasuredHeightAndState()11862     public final int getMeasuredHeightAndState() {
11863         return mMeasuredHeight;
11864     }
11865 
11866     /**
11867      * Return only the state bits of {@link #getMeasuredWidthAndState()}
11868      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11869      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11870      * and the height component is at the shifted bits
11871      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11872      */
getMeasuredState()11873     public final int getMeasuredState() {
11874         return (mMeasuredWidth&MEASURED_STATE_MASK)
11875                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11876                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11877     }
11878 
11879     /**
11880      * The transform matrix of this view, which is calculated based on the current
11881      * rotation, scale, and pivot properties.
11882      *
11883      * @see #getRotation()
11884      * @see #getScaleX()
11885      * @see #getScaleY()
11886      * @see #getPivotX()
11887      * @see #getPivotY()
11888      * @return The current transform matrix for the view
11889      */
getMatrix()11890     public Matrix getMatrix() {
11891         ensureTransformationInfo();
11892         final Matrix matrix = mTransformationInfo.mMatrix;
11893         mRenderNode.getMatrix(matrix);
11894         return matrix;
11895     }
11896 
11897     /**
11898      * Returns true if the transform matrix is the identity matrix.
11899      * Recomputes the matrix if necessary.
11900      *
11901      * @return True if the transform matrix is the identity matrix, false otherwise.
11902      */
hasIdentityMatrix()11903     final boolean hasIdentityMatrix() {
11904         return mRenderNode.hasIdentityMatrix();
11905     }
11906 
ensureTransformationInfo()11907     void ensureTransformationInfo() {
11908         if (mTransformationInfo == null) {
11909             mTransformationInfo = new TransformationInfo();
11910         }
11911     }
11912 
11913     /**
11914      * Utility method to retrieve the inverse of the current mMatrix property.
11915      * We cache the matrix to avoid recalculating it when transform properties
11916      * have not changed.
11917      *
11918      * @return The inverse of the current matrix of this view.
11919      * @hide
11920      */
getInverseMatrix()11921     public final Matrix getInverseMatrix() {
11922         ensureTransformationInfo();
11923         if (mTransformationInfo.mInverseMatrix == null) {
11924             mTransformationInfo.mInverseMatrix = new Matrix();
11925         }
11926         final Matrix matrix = mTransformationInfo.mInverseMatrix;
11927         mRenderNode.getInverseMatrix(matrix);
11928         return matrix;
11929     }
11930 
11931     /**
11932      * Gets the distance along the Z axis from the camera to this view.
11933      *
11934      * @see #setCameraDistance(float)
11935      *
11936      * @return The distance along the Z axis.
11937      */
getCameraDistance()11938     public float getCameraDistance() {
11939         final float dpi = mResources.getDisplayMetrics().densityDpi;
11940         return -(mRenderNode.getCameraDistance() * dpi);
11941     }
11942 
11943     /**
11944      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11945      * views are drawn) from the camera to this view. The camera's distance
11946      * affects 3D transformations, for instance rotations around the X and Y
11947      * axis. If the rotationX or rotationY properties are changed and this view is
11948      * large (more than half the size of the screen), it is recommended to always
11949      * use a camera distance that's greater than the height (X axis rotation) or
11950      * the width (Y axis rotation) of this view.</p>
11951      *
11952      * <p>The distance of the camera from the view plane can have an affect on the
11953      * perspective distortion of the view when it is rotated around the x or y axis.
11954      * For example, a large distance will result in a large viewing angle, and there
11955      * will not be much perspective distortion of the view as it rotates. A short
11956      * distance may cause much more perspective distortion upon rotation, and can
11957      * also result in some drawing artifacts if the rotated view ends up partially
11958      * behind the camera (which is why the recommendation is to use a distance at
11959      * least as far as the size of the view, if the view is to be rotated.)</p>
11960      *
11961      * <p>The distance is expressed in "depth pixels." The default distance depends
11962      * on the screen density. For instance, on a medium density display, the
11963      * default distance is 1280. On a high density display, the default distance
11964      * is 1920.</p>
11965      *
11966      * <p>If you want to specify a distance that leads to visually consistent
11967      * results across various densities, use the following formula:</p>
11968      * <pre>
11969      * float scale = context.getResources().getDisplayMetrics().density;
11970      * view.setCameraDistance(distance * scale);
11971      * </pre>
11972      *
11973      * <p>The density scale factor of a high density display is 1.5,
11974      * and 1920 = 1280 * 1.5.</p>
11975      *
11976      * @param distance The distance in "depth pixels", if negative the opposite
11977      *        value is used
11978      *
11979      * @see #setRotationX(float)
11980      * @see #setRotationY(float)
11981      */
setCameraDistance(float distance)11982     public void setCameraDistance(float distance) {
11983         final float dpi = mResources.getDisplayMetrics().densityDpi;
11984 
11985         invalidateViewProperty(true, false);
11986         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11987         invalidateViewProperty(false, false);
11988 
11989         invalidateParentIfNeededAndWasQuickRejected();
11990     }
11991 
11992     /**
11993      * The degrees that the view is rotated around the pivot point.
11994      *
11995      * @see #setRotation(float)
11996      * @see #getPivotX()
11997      * @see #getPivotY()
11998      *
11999      * @return The degrees of rotation.
12000      */
12001     @ViewDebug.ExportedProperty(category = "drawing")
getRotation()12002     public float getRotation() {
12003         return mRenderNode.getRotation();
12004     }
12005 
12006     /**
12007      * Sets the degrees that the view is rotated around the pivot point. Increasing values
12008      * result in clockwise rotation.
12009      *
12010      * @param rotation The degrees of rotation.
12011      *
12012      * @see #getRotation()
12013      * @see #getPivotX()
12014      * @see #getPivotY()
12015      * @see #setRotationX(float)
12016      * @see #setRotationY(float)
12017      *
12018      * @attr ref android.R.styleable#View_rotation
12019      */
setRotation(float rotation)12020     public void setRotation(float rotation) {
12021         if (rotation != getRotation()) {
12022             // Double-invalidation is necessary to capture view's old and new areas
12023             invalidateViewProperty(true, false);
12024             mRenderNode.setRotation(rotation);
12025             invalidateViewProperty(false, true);
12026 
12027             invalidateParentIfNeededAndWasQuickRejected();
12028             notifySubtreeAccessibilityStateChangedIfNeeded();
12029         }
12030     }
12031 
12032     /**
12033      * The degrees that the view is rotated around the vertical axis through the pivot point.
12034      *
12035      * @see #getPivotX()
12036      * @see #getPivotY()
12037      * @see #setRotationY(float)
12038      *
12039      * @return The degrees of Y rotation.
12040      */
12041     @ViewDebug.ExportedProperty(category = "drawing")
getRotationY()12042     public float getRotationY() {
12043         return mRenderNode.getRotationY();
12044     }
12045 
12046     /**
12047      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12048      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12049      * down the y axis.
12050      *
12051      * When rotating large views, it is recommended to adjust the camera distance
12052      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12053      *
12054      * @param rotationY The degrees of Y rotation.
12055      *
12056      * @see #getRotationY()
12057      * @see #getPivotX()
12058      * @see #getPivotY()
12059      * @see #setRotation(float)
12060      * @see #setRotationX(float)
12061      * @see #setCameraDistance(float)
12062      *
12063      * @attr ref android.R.styleable#View_rotationY
12064      */
setRotationY(float rotationY)12065     public void setRotationY(float rotationY) {
12066         if (rotationY != getRotationY()) {
12067             invalidateViewProperty(true, false);
12068             mRenderNode.setRotationY(rotationY);
12069             invalidateViewProperty(false, true);
12070 
12071             invalidateParentIfNeededAndWasQuickRejected();
12072             notifySubtreeAccessibilityStateChangedIfNeeded();
12073         }
12074     }
12075 
12076     /**
12077      * The degrees that the view is rotated around the horizontal axis through the pivot point.
12078      *
12079      * @see #getPivotX()
12080      * @see #getPivotY()
12081      * @see #setRotationX(float)
12082      *
12083      * @return The degrees of X rotation.
12084      */
12085     @ViewDebug.ExportedProperty(category = "drawing")
getRotationX()12086     public float getRotationX() {
12087         return mRenderNode.getRotationX();
12088     }
12089 
12090     /**
12091      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12092      * Increasing values result in clockwise rotation from the viewpoint of looking down the
12093      * x axis.
12094      *
12095      * When rotating large views, it is recommended to adjust the camera distance
12096      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12097      *
12098      * @param rotationX The degrees of X rotation.
12099      *
12100      * @see #getRotationX()
12101      * @see #getPivotX()
12102      * @see #getPivotY()
12103      * @see #setRotation(float)
12104      * @see #setRotationY(float)
12105      * @see #setCameraDistance(float)
12106      *
12107      * @attr ref android.R.styleable#View_rotationX
12108      */
setRotationX(float rotationX)12109     public void setRotationX(float rotationX) {
12110         if (rotationX != getRotationX()) {
12111             invalidateViewProperty(true, false);
12112             mRenderNode.setRotationX(rotationX);
12113             invalidateViewProperty(false, true);
12114 
12115             invalidateParentIfNeededAndWasQuickRejected();
12116             notifySubtreeAccessibilityStateChangedIfNeeded();
12117         }
12118     }
12119 
12120     /**
12121      * The amount that the view is scaled in x around the pivot point, as a proportion of
12122      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12123      *
12124      * <p>By default, this is 1.0f.
12125      *
12126      * @see #getPivotX()
12127      * @see #getPivotY()
12128      * @return The scaling factor.
12129      */
12130     @ViewDebug.ExportedProperty(category = "drawing")
getScaleX()12131     public float getScaleX() {
12132         return mRenderNode.getScaleX();
12133     }
12134 
12135     /**
12136      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12137      * the view's unscaled width. A value of 1 means that no scaling is applied.
12138      *
12139      * @param scaleX The scaling factor.
12140      * @see #getPivotX()
12141      * @see #getPivotY()
12142      *
12143      * @attr ref android.R.styleable#View_scaleX
12144      */
setScaleX(float scaleX)12145     public void setScaleX(float scaleX) {
12146         if (scaleX != getScaleX()) {
12147             invalidateViewProperty(true, false);
12148             mRenderNode.setScaleX(scaleX);
12149             invalidateViewProperty(false, true);
12150 
12151             invalidateParentIfNeededAndWasQuickRejected();
12152             notifySubtreeAccessibilityStateChangedIfNeeded();
12153         }
12154     }
12155 
12156     /**
12157      * The amount that the view is scaled in y around the pivot point, as a proportion of
12158      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12159      *
12160      * <p>By default, this is 1.0f.
12161      *
12162      * @see #getPivotX()
12163      * @see #getPivotY()
12164      * @return The scaling factor.
12165      */
12166     @ViewDebug.ExportedProperty(category = "drawing")
getScaleY()12167     public float getScaleY() {
12168         return mRenderNode.getScaleY();
12169     }
12170 
12171     /**
12172      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12173      * the view's unscaled width. A value of 1 means that no scaling is applied.
12174      *
12175      * @param scaleY The scaling factor.
12176      * @see #getPivotX()
12177      * @see #getPivotY()
12178      *
12179      * @attr ref android.R.styleable#View_scaleY
12180      */
setScaleY(float scaleY)12181     public void setScaleY(float scaleY) {
12182         if (scaleY != getScaleY()) {
12183             invalidateViewProperty(true, false);
12184             mRenderNode.setScaleY(scaleY);
12185             invalidateViewProperty(false, true);
12186 
12187             invalidateParentIfNeededAndWasQuickRejected();
12188             notifySubtreeAccessibilityStateChangedIfNeeded();
12189         }
12190     }
12191 
12192     /**
12193      * The x location of the point around which the view is {@link #setRotation(float) rotated}
12194      * and {@link #setScaleX(float) scaled}.
12195      *
12196      * @see #getRotation()
12197      * @see #getScaleX()
12198      * @see #getScaleY()
12199      * @see #getPivotY()
12200      * @return The x location of the pivot point.
12201      *
12202      * @attr ref android.R.styleable#View_transformPivotX
12203      */
12204     @ViewDebug.ExportedProperty(category = "drawing")
getPivotX()12205     public float getPivotX() {
12206         return mRenderNode.getPivotX();
12207     }
12208 
12209     /**
12210      * Sets the x location of the point around which the view is
12211      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12212      * By default, the pivot point is centered on the object.
12213      * Setting this property disables this behavior and causes the view to use only the
12214      * explicitly set pivotX and pivotY values.
12215      *
12216      * @param pivotX The x location of the pivot point.
12217      * @see #getRotation()
12218      * @see #getScaleX()
12219      * @see #getScaleY()
12220      * @see #getPivotY()
12221      *
12222      * @attr ref android.R.styleable#View_transformPivotX
12223      */
setPivotX(float pivotX)12224     public void setPivotX(float pivotX) {
12225         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12226             invalidateViewProperty(true, false);
12227             mRenderNode.setPivotX(pivotX);
12228             invalidateViewProperty(false, true);
12229 
12230             invalidateParentIfNeededAndWasQuickRejected();
12231         }
12232     }
12233 
12234     /**
12235      * The y location of the point around which the view is {@link #setRotation(float) rotated}
12236      * and {@link #setScaleY(float) scaled}.
12237      *
12238      * @see #getRotation()
12239      * @see #getScaleX()
12240      * @see #getScaleY()
12241      * @see #getPivotY()
12242      * @return The y location of the pivot point.
12243      *
12244      * @attr ref android.R.styleable#View_transformPivotY
12245      */
12246     @ViewDebug.ExportedProperty(category = "drawing")
getPivotY()12247     public float getPivotY() {
12248         return mRenderNode.getPivotY();
12249     }
12250 
12251     /**
12252      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12253      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12254      * Setting this property disables this behavior and causes the view to use only the
12255      * explicitly set pivotX and pivotY values.
12256      *
12257      * @param pivotY The y location of the pivot point.
12258      * @see #getRotation()
12259      * @see #getScaleX()
12260      * @see #getScaleY()
12261      * @see #getPivotY()
12262      *
12263      * @attr ref android.R.styleable#View_transformPivotY
12264      */
setPivotY(float pivotY)12265     public void setPivotY(float pivotY) {
12266         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12267             invalidateViewProperty(true, false);
12268             mRenderNode.setPivotY(pivotY);
12269             invalidateViewProperty(false, true);
12270 
12271             invalidateParentIfNeededAndWasQuickRejected();
12272         }
12273     }
12274 
12275     /**
12276      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12277      * completely transparent and 1 means the view is completely opaque.
12278      *
12279      * <p>By default this is 1.0f.
12280      * @return The opacity of the view.
12281      */
12282     @ViewDebug.ExportedProperty(category = "drawing")
getAlpha()12283     public float getAlpha() {
12284         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12285     }
12286 
12287     /**
12288      * Sets the behavior for overlapping rendering for this view (see {@link
12289      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12290      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12291      * providing the value which is then used internally. That is, when {@link
12292      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12293      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12294      * instead.
12295      *
12296      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12297      * instead of that returned by {@link #hasOverlappingRendering()}.
12298      *
12299      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12300      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)12301     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12302         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12303         if (hasOverlappingRendering) {
12304             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12305         } else {
12306             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12307         }
12308     }
12309 
12310     /**
12311      * Returns the value for overlapping rendering that is used internally. This is either
12312      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12313      * the return value of {@link #hasOverlappingRendering()}, otherwise.
12314      *
12315      * @return The value for overlapping rendering being used internally.
12316      */
getHasOverlappingRendering()12317     public final boolean getHasOverlappingRendering() {
12318         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12319                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12320                 hasOverlappingRendering();
12321     }
12322 
12323     /**
12324      * Returns whether this View has content which overlaps.
12325      *
12326      * <p>This function, intended to be overridden by specific View types, is an optimization when
12327      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12328      * an offscreen buffer and then composited into place, which can be expensive. If the view has
12329      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12330      * directly. An example of overlapping rendering is a TextView with a background image, such as
12331      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12332      * ImageView with only the foreground image. The default implementation returns true; subclasses
12333      * should override if they have cases which can be optimized.</p>
12334      *
12335      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12336      * necessitates that a View return true if it uses the methods internally without passing the
12337      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12338      *
12339      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12340      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12341      *
12342      * @return true if the content in this view might overlap, false otherwise.
12343      */
12344     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()12345     public boolean hasOverlappingRendering() {
12346         return true;
12347     }
12348 
12349     /**
12350      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12351      * completely transparent and 1 means the view is completely opaque.
12352      *
12353      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12354      * can have significant performance implications, especially for large views. It is best to use
12355      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12356      *
12357      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12358      * strongly recommended for performance reasons to either override
12359      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12360      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12361      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12362      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12363      * of rendering cost, even for simple or small views. Starting with
12364      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12365      * applied to the view at the rendering level.</p>
12366      *
12367      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12368      * responsible for applying the opacity itself.</p>
12369      *
12370      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12371      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12372      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12373      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12374      *
12375      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12376      * value will clip a View to its bounds, unless the View returns <code>false</code> from
12377      * {@link #hasOverlappingRendering}.</p>
12378      *
12379      * @param alpha The opacity of the view.
12380      *
12381      * @see #hasOverlappingRendering()
12382      * @see #setLayerType(int, android.graphics.Paint)
12383      *
12384      * @attr ref android.R.styleable#View_alpha
12385      */
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)12386     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12387         ensureTransformationInfo();
12388         if (mTransformationInfo.mAlpha != alpha) {
12389             // Report visibility changes, which can affect children, to accessibility
12390             if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12391                 notifySubtreeAccessibilityStateChangedIfNeeded();
12392             }
12393             mTransformationInfo.mAlpha = alpha;
12394             if (onSetAlpha((int) (alpha * 255))) {
12395                 mPrivateFlags |= PFLAG_ALPHA_SET;
12396                 // subclass is handling alpha - don't optimize rendering cache invalidation
12397                 invalidateParentCaches();
12398                 invalidate(true);
12399             } else {
12400                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12401                 invalidateViewProperty(true, false);
12402                 mRenderNode.setAlpha(getFinalAlpha());
12403             }
12404         }
12405     }
12406 
12407     /**
12408      * Faster version of setAlpha() which performs the same steps except there are
12409      * no calls to invalidate(). The caller of this function should perform proper invalidation
12410      * on the parent and this object. The return value indicates whether the subclass handles
12411      * alpha (the return value for onSetAlpha()).
12412      *
12413      * @param alpha The new value for the alpha property
12414      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12415      *         the new value for the alpha property is different from the old value
12416      */
setAlphaNoInvalidation(float alpha)12417     boolean setAlphaNoInvalidation(float alpha) {
12418         ensureTransformationInfo();
12419         if (mTransformationInfo.mAlpha != alpha) {
12420             mTransformationInfo.mAlpha = alpha;
12421             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12422             if (subclassHandlesAlpha) {
12423                 mPrivateFlags |= PFLAG_ALPHA_SET;
12424                 return true;
12425             } else {
12426                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12427                 mRenderNode.setAlpha(getFinalAlpha());
12428             }
12429         }
12430         return false;
12431     }
12432 
12433     /**
12434      * This property is hidden and intended only for use by the Fade transition, which
12435      * animates it to produce a visual translucency that does not side-effect (or get
12436      * affected by) the real alpha property. This value is composited with the other
12437      * alpha value (and the AlphaAnimation value, when that is present) to produce
12438      * a final visual translucency result, which is what is passed into the DisplayList.
12439      *
12440      * @hide
12441      */
setTransitionAlpha(float alpha)12442     public void setTransitionAlpha(float alpha) {
12443         ensureTransformationInfo();
12444         if (mTransformationInfo.mTransitionAlpha != alpha) {
12445             mTransformationInfo.mTransitionAlpha = alpha;
12446             mPrivateFlags &= ~PFLAG_ALPHA_SET;
12447             invalidateViewProperty(true, false);
12448             mRenderNode.setAlpha(getFinalAlpha());
12449         }
12450     }
12451 
12452     /**
12453      * Calculates the visual alpha of this view, which is a combination of the actual
12454      * alpha value and the transitionAlpha value (if set).
12455      */
getFinalAlpha()12456     private float getFinalAlpha() {
12457         if (mTransformationInfo != null) {
12458             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12459         }
12460         return 1;
12461     }
12462 
12463     /**
12464      * This property is hidden and intended only for use by the Fade transition, which
12465      * animates it to produce a visual translucency that does not side-effect (or get
12466      * affected by) the real alpha property. This value is composited with the other
12467      * alpha value (and the AlphaAnimation value, when that is present) to produce
12468      * a final visual translucency result, which is what is passed into the DisplayList.
12469      *
12470      * @hide
12471      */
12472     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()12473     public float getTransitionAlpha() {
12474         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12475     }
12476 
12477     /**
12478      * Top position of this view relative to its parent.
12479      *
12480      * @return The top of this view, in pixels.
12481      */
12482     @ViewDebug.CapturedViewProperty
getTop()12483     public final int getTop() {
12484         return mTop;
12485     }
12486 
12487     /**
12488      * Sets the top position of this view relative to its parent. This method is meant to be called
12489      * by the layout system and should not generally be called otherwise, because the property
12490      * may be changed at any time by the layout.
12491      *
12492      * @param top The top of this view, in pixels.
12493      */
setTop(int top)12494     public final void setTop(int top) {
12495         if (top != mTop) {
12496             final boolean matrixIsIdentity = hasIdentityMatrix();
12497             if (matrixIsIdentity) {
12498                 if (mAttachInfo != null) {
12499                     int minTop;
12500                     int yLoc;
12501                     if (top < mTop) {
12502                         minTop = top;
12503                         yLoc = top - mTop;
12504                     } else {
12505                         minTop = mTop;
12506                         yLoc = 0;
12507                     }
12508                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12509                 }
12510             } else {
12511                 // Double-invalidation is necessary to capture view's old and new areas
12512                 invalidate(true);
12513             }
12514 
12515             int width = mRight - mLeft;
12516             int oldHeight = mBottom - mTop;
12517 
12518             mTop = top;
12519             mRenderNode.setTop(mTop);
12520 
12521             sizeChange(width, mBottom - mTop, width, oldHeight);
12522 
12523             if (!matrixIsIdentity) {
12524                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12525                 invalidate(true);
12526             }
12527             mBackgroundSizeChanged = true;
12528             if (mForegroundInfo != null) {
12529                 mForegroundInfo.mBoundsChanged = true;
12530             }
12531             invalidateParentIfNeeded();
12532             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12533                 // View was rejected last time it was drawn by its parent; this may have changed
12534                 invalidateParentIfNeeded();
12535             }
12536         }
12537     }
12538 
12539     /**
12540      * Bottom position of this view relative to its parent.
12541      *
12542      * @return The bottom of this view, in pixels.
12543      */
12544     @ViewDebug.CapturedViewProperty
getBottom()12545     public final int getBottom() {
12546         return mBottom;
12547     }
12548 
12549     /**
12550      * True if this view has changed since the last time being drawn.
12551      *
12552      * @return The dirty state of this view.
12553      */
isDirty()12554     public boolean isDirty() {
12555         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12556     }
12557 
12558     /**
12559      * Sets the bottom position of this view relative to its parent. This method is meant to be
12560      * called by the layout system and should not generally be called otherwise, because the
12561      * property may be changed at any time by the layout.
12562      *
12563      * @param bottom The bottom of this view, in pixels.
12564      */
setBottom(int bottom)12565     public final void setBottom(int bottom) {
12566         if (bottom != mBottom) {
12567             final boolean matrixIsIdentity = hasIdentityMatrix();
12568             if (matrixIsIdentity) {
12569                 if (mAttachInfo != null) {
12570                     int maxBottom;
12571                     if (bottom < mBottom) {
12572                         maxBottom = mBottom;
12573                     } else {
12574                         maxBottom = bottom;
12575                     }
12576                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12577                 }
12578             } else {
12579                 // Double-invalidation is necessary to capture view's old and new areas
12580                 invalidate(true);
12581             }
12582 
12583             int width = mRight - mLeft;
12584             int oldHeight = mBottom - mTop;
12585 
12586             mBottom = bottom;
12587             mRenderNode.setBottom(mBottom);
12588 
12589             sizeChange(width, mBottom - mTop, width, oldHeight);
12590 
12591             if (!matrixIsIdentity) {
12592                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12593                 invalidate(true);
12594             }
12595             mBackgroundSizeChanged = true;
12596             if (mForegroundInfo != null) {
12597                 mForegroundInfo.mBoundsChanged = true;
12598             }
12599             invalidateParentIfNeeded();
12600             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12601                 // View was rejected last time it was drawn by its parent; this may have changed
12602                 invalidateParentIfNeeded();
12603             }
12604         }
12605     }
12606 
12607     /**
12608      * Left position of this view relative to its parent.
12609      *
12610      * @return The left edge of this view, in pixels.
12611      */
12612     @ViewDebug.CapturedViewProperty
getLeft()12613     public final int getLeft() {
12614         return mLeft;
12615     }
12616 
12617     /**
12618      * Sets the left position of this view relative to its parent. This method is meant to be called
12619      * by the layout system and should not generally be called otherwise, because the property
12620      * may be changed at any time by the layout.
12621      *
12622      * @param left The left of this view, in pixels.
12623      */
setLeft(int left)12624     public final void setLeft(int left) {
12625         if (left != mLeft) {
12626             final boolean matrixIsIdentity = hasIdentityMatrix();
12627             if (matrixIsIdentity) {
12628                 if (mAttachInfo != null) {
12629                     int minLeft;
12630                     int xLoc;
12631                     if (left < mLeft) {
12632                         minLeft = left;
12633                         xLoc = left - mLeft;
12634                     } else {
12635                         minLeft = mLeft;
12636                         xLoc = 0;
12637                     }
12638                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12639                 }
12640             } else {
12641                 // Double-invalidation is necessary to capture view's old and new areas
12642                 invalidate(true);
12643             }
12644 
12645             int oldWidth = mRight - mLeft;
12646             int height = mBottom - mTop;
12647 
12648             mLeft = left;
12649             mRenderNode.setLeft(left);
12650 
12651             sizeChange(mRight - mLeft, height, oldWidth, height);
12652 
12653             if (!matrixIsIdentity) {
12654                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12655                 invalidate(true);
12656             }
12657             mBackgroundSizeChanged = true;
12658             if (mForegroundInfo != null) {
12659                 mForegroundInfo.mBoundsChanged = true;
12660             }
12661             invalidateParentIfNeeded();
12662             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12663                 // View was rejected last time it was drawn by its parent; this may have changed
12664                 invalidateParentIfNeeded();
12665             }
12666         }
12667     }
12668 
12669     /**
12670      * Right position of this view relative to its parent.
12671      *
12672      * @return The right edge of this view, in pixels.
12673      */
12674     @ViewDebug.CapturedViewProperty
getRight()12675     public final int getRight() {
12676         return mRight;
12677     }
12678 
12679     /**
12680      * Sets the right position of this view relative to its parent. This method is meant to be called
12681      * by the layout system and should not generally be called otherwise, because the property
12682      * may be changed at any time by the layout.
12683      *
12684      * @param right The right of this view, in pixels.
12685      */
setRight(int right)12686     public final void setRight(int right) {
12687         if (right != mRight) {
12688             final boolean matrixIsIdentity = hasIdentityMatrix();
12689             if (matrixIsIdentity) {
12690                 if (mAttachInfo != null) {
12691                     int maxRight;
12692                     if (right < mRight) {
12693                         maxRight = mRight;
12694                     } else {
12695                         maxRight = right;
12696                     }
12697                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12698                 }
12699             } else {
12700                 // Double-invalidation is necessary to capture view's old and new areas
12701                 invalidate(true);
12702             }
12703 
12704             int oldWidth = mRight - mLeft;
12705             int height = mBottom - mTop;
12706 
12707             mRight = right;
12708             mRenderNode.setRight(mRight);
12709 
12710             sizeChange(mRight - mLeft, height, oldWidth, height);
12711 
12712             if (!matrixIsIdentity) {
12713                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12714                 invalidate(true);
12715             }
12716             mBackgroundSizeChanged = true;
12717             if (mForegroundInfo != null) {
12718                 mForegroundInfo.mBoundsChanged = true;
12719             }
12720             invalidateParentIfNeeded();
12721             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12722                 // View was rejected last time it was drawn by its parent; this may have changed
12723                 invalidateParentIfNeeded();
12724             }
12725         }
12726     }
12727 
12728     /**
12729      * The visual x position of this view, in pixels. This is equivalent to the
12730      * {@link #setTranslationX(float) translationX} property plus the current
12731      * {@link #getLeft() left} property.
12732      *
12733      * @return The visual x position of this view, in pixels.
12734      */
12735     @ViewDebug.ExportedProperty(category = "drawing")
getX()12736     public float getX() {
12737         return mLeft + getTranslationX();
12738     }
12739 
12740     /**
12741      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12742      * {@link #setTranslationX(float) translationX} property to be the difference between
12743      * the x value passed in and the current {@link #getLeft() left} property.
12744      *
12745      * @param x The visual x position of this view, in pixels.
12746      */
setX(float x)12747     public void setX(float x) {
12748         setTranslationX(x - mLeft);
12749     }
12750 
12751     /**
12752      * The visual y position of this view, in pixels. This is equivalent to the
12753      * {@link #setTranslationY(float) translationY} property plus the current
12754      * {@link #getTop() top} property.
12755      *
12756      * @return The visual y position of this view, in pixels.
12757      */
12758     @ViewDebug.ExportedProperty(category = "drawing")
getY()12759     public float getY() {
12760         return mTop + getTranslationY();
12761     }
12762 
12763     /**
12764      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12765      * {@link #setTranslationY(float) translationY} property to be the difference between
12766      * the y value passed in and the current {@link #getTop() top} property.
12767      *
12768      * @param y The visual y position of this view, in pixels.
12769      */
setY(float y)12770     public void setY(float y) {
12771         setTranslationY(y - mTop);
12772     }
12773 
12774     /**
12775      * The visual z position of this view, in pixels. This is equivalent to the
12776      * {@link #setTranslationZ(float) translationZ} property plus the current
12777      * {@link #getElevation() elevation} property.
12778      *
12779      * @return The visual z position of this view, in pixels.
12780      */
12781     @ViewDebug.ExportedProperty(category = "drawing")
getZ()12782     public float getZ() {
12783         return getElevation() + getTranslationZ();
12784     }
12785 
12786     /**
12787      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12788      * {@link #setTranslationZ(float) translationZ} property to be the difference between
12789      * the x value passed in and the current {@link #getElevation() elevation} property.
12790      *
12791      * @param z The visual z position of this view, in pixels.
12792      */
setZ(float z)12793     public void setZ(float z) {
12794         setTranslationZ(z - getElevation());
12795     }
12796 
12797     /**
12798      * The base elevation of this view relative to its parent, in pixels.
12799      *
12800      * @return The base depth position of the view, in pixels.
12801      */
12802     @ViewDebug.ExportedProperty(category = "drawing")
getElevation()12803     public float getElevation() {
12804         return mRenderNode.getElevation();
12805     }
12806 
12807     /**
12808      * Sets the base elevation of this view, in pixels.
12809      *
12810      * @attr ref android.R.styleable#View_elevation
12811      */
setElevation(float elevation)12812     public void setElevation(float elevation) {
12813         if (elevation != getElevation()) {
12814             invalidateViewProperty(true, false);
12815             mRenderNode.setElevation(elevation);
12816             invalidateViewProperty(false, true);
12817 
12818             invalidateParentIfNeededAndWasQuickRejected();
12819         }
12820     }
12821 
12822     /**
12823      * The horizontal location of this view relative to its {@link #getLeft() left} position.
12824      * This position is post-layout, in addition to wherever the object's
12825      * layout placed it.
12826      *
12827      * @return The horizontal position of this view relative to its left position, in pixels.
12828      */
12829     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationX()12830     public float getTranslationX() {
12831         return mRenderNode.getTranslationX();
12832     }
12833 
12834     /**
12835      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12836      * This effectively positions the object post-layout, in addition to wherever the object's
12837      * layout placed it.
12838      *
12839      * @param translationX The horizontal position of this view relative to its left position,
12840      * in pixels.
12841      *
12842      * @attr ref android.R.styleable#View_translationX
12843      */
setTranslationX(float translationX)12844     public void setTranslationX(float translationX) {
12845         if (translationX != getTranslationX()) {
12846             invalidateViewProperty(true, false);
12847             mRenderNode.setTranslationX(translationX);
12848             invalidateViewProperty(false, true);
12849 
12850             invalidateParentIfNeededAndWasQuickRejected();
12851             notifySubtreeAccessibilityStateChangedIfNeeded();
12852         }
12853     }
12854 
12855     /**
12856      * The vertical location of this view relative to its {@link #getTop() top} position.
12857      * This position is post-layout, in addition to wherever the object's
12858      * layout placed it.
12859      *
12860      * @return The vertical position of this view relative to its top position,
12861      * in pixels.
12862      */
12863     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationY()12864     public float getTranslationY() {
12865         return mRenderNode.getTranslationY();
12866     }
12867 
12868     /**
12869      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12870      * This effectively positions the object post-layout, in addition to wherever the object's
12871      * layout placed it.
12872      *
12873      * @param translationY The vertical position of this view relative to its top position,
12874      * in pixels.
12875      *
12876      * @attr ref android.R.styleable#View_translationY
12877      */
setTranslationY(float translationY)12878     public void setTranslationY(float translationY) {
12879         if (translationY != getTranslationY()) {
12880             invalidateViewProperty(true, false);
12881             mRenderNode.setTranslationY(translationY);
12882             invalidateViewProperty(false, true);
12883 
12884             invalidateParentIfNeededAndWasQuickRejected();
12885             notifySubtreeAccessibilityStateChangedIfNeeded();
12886         }
12887     }
12888 
12889     /**
12890      * The depth location of this view relative to its {@link #getElevation() elevation}.
12891      *
12892      * @return The depth of this view relative to its elevation.
12893      */
12894     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationZ()12895     public float getTranslationZ() {
12896         return mRenderNode.getTranslationZ();
12897     }
12898 
12899     /**
12900      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12901      *
12902      * @attr ref android.R.styleable#View_translationZ
12903      */
setTranslationZ(float translationZ)12904     public void setTranslationZ(float translationZ) {
12905         if (translationZ != getTranslationZ()) {
12906             invalidateViewProperty(true, false);
12907             mRenderNode.setTranslationZ(translationZ);
12908             invalidateViewProperty(false, true);
12909 
12910             invalidateParentIfNeededAndWasQuickRejected();
12911         }
12912     }
12913 
12914     /** @hide */
setAnimationMatrix(Matrix matrix)12915     public void setAnimationMatrix(Matrix matrix) {
12916         invalidateViewProperty(true, false);
12917         mRenderNode.setAnimationMatrix(matrix);
12918         invalidateViewProperty(false, true);
12919 
12920         invalidateParentIfNeededAndWasQuickRejected();
12921     }
12922 
12923     /**
12924      * Returns the current StateListAnimator if exists.
12925      *
12926      * @return StateListAnimator or null if it does not exists
12927      * @see    #setStateListAnimator(android.animation.StateListAnimator)
12928      */
getStateListAnimator()12929     public StateListAnimator getStateListAnimator() {
12930         return mStateListAnimator;
12931     }
12932 
12933     /**
12934      * Attaches the provided StateListAnimator to this View.
12935      * <p>
12936      * Any previously attached StateListAnimator will be detached.
12937      *
12938      * @param stateListAnimator The StateListAnimator to update the view
12939      * @see android.animation.StateListAnimator
12940      */
setStateListAnimator(StateListAnimator stateListAnimator)12941     public void setStateListAnimator(StateListAnimator stateListAnimator) {
12942         if (mStateListAnimator == stateListAnimator) {
12943             return;
12944         }
12945         if (mStateListAnimator != null) {
12946             mStateListAnimator.setTarget(null);
12947         }
12948         mStateListAnimator = stateListAnimator;
12949         if (stateListAnimator != null) {
12950             stateListAnimator.setTarget(this);
12951             if (isAttachedToWindow()) {
12952                 stateListAnimator.setState(getDrawableState());
12953             }
12954         }
12955     }
12956 
12957     /**
12958      * Returns whether the Outline should be used to clip the contents of the View.
12959      * <p>
12960      * Note that this flag will only be respected if the View's Outline returns true from
12961      * {@link Outline#canClip()}.
12962      *
12963      * @see #setOutlineProvider(ViewOutlineProvider)
12964      * @see #setClipToOutline(boolean)
12965      */
getClipToOutline()12966     public final boolean getClipToOutline() {
12967         return mRenderNode.getClipToOutline();
12968     }
12969 
12970     /**
12971      * Sets whether the View's Outline should be used to clip the contents of the View.
12972      * <p>
12973      * Only a single non-rectangular clip can be applied on a View at any time.
12974      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12975      * circular reveal} animation take priority over Outline clipping, and
12976      * child Outline clipping takes priority over Outline clipping done by a
12977      * parent.
12978      * <p>
12979      * Note that this flag will only be respected if the View's Outline returns true from
12980      * {@link Outline#canClip()}.
12981      *
12982      * @see #setOutlineProvider(ViewOutlineProvider)
12983      * @see #getClipToOutline()
12984      */
setClipToOutline(boolean clipToOutline)12985     public void setClipToOutline(boolean clipToOutline) {
12986         damageInParent();
12987         if (getClipToOutline() != clipToOutline) {
12988             mRenderNode.setClipToOutline(clipToOutline);
12989         }
12990     }
12991 
12992     // correspond to the enum values of View_outlineProvider
12993     private static final int PROVIDER_BACKGROUND = 0;
12994     private static final int PROVIDER_NONE = 1;
12995     private static final int PROVIDER_BOUNDS = 2;
12996     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)12997     private void setOutlineProviderFromAttribute(int providerInt) {
12998         switch (providerInt) {
12999             case PROVIDER_BACKGROUND:
13000                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13001                 break;
13002             case PROVIDER_NONE:
13003                 setOutlineProvider(null);
13004                 break;
13005             case PROVIDER_BOUNDS:
13006                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
13007                 break;
13008             case PROVIDER_PADDED_BOUNDS:
13009                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13010                 break;
13011         }
13012     }
13013 
13014     /**
13015      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13016      * the shape of the shadow it casts, and enables outline clipping.
13017      * <p>
13018      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13019      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13020      * outline provider with this method allows this behavior to be overridden.
13021      * <p>
13022      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13023      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13024      * <p>
13025      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13026      *
13027      * @see #setClipToOutline(boolean)
13028      * @see #getClipToOutline()
13029      * @see #getOutlineProvider()
13030      */
setOutlineProvider(ViewOutlineProvider provider)13031     public void setOutlineProvider(ViewOutlineProvider provider) {
13032         mOutlineProvider = provider;
13033         invalidateOutline();
13034     }
13035 
13036     /**
13037      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13038      * that defines the shape of the shadow it casts, and enables outline clipping.
13039      *
13040      * @see #setOutlineProvider(ViewOutlineProvider)
13041      */
getOutlineProvider()13042     public ViewOutlineProvider getOutlineProvider() {
13043         return mOutlineProvider;
13044     }
13045 
13046     /**
13047      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13048      *
13049      * @see #setOutlineProvider(ViewOutlineProvider)
13050      */
invalidateOutline()13051     public void invalidateOutline() {
13052         rebuildOutline();
13053 
13054         notifySubtreeAccessibilityStateChangedIfNeeded();
13055         invalidateViewProperty(false, false);
13056     }
13057 
13058     /**
13059      * Internal version of {@link #invalidateOutline()} which invalidates the
13060      * outline without invalidating the view itself. This is intended to be called from
13061      * within methods in the View class itself which are the result of the view being
13062      * invalidated already. For example, when we are drawing the background of a View,
13063      * we invalidate the outline in case it changed in the meantime, but we do not
13064      * need to invalidate the view because we're already drawing the background as part
13065      * of drawing the view in response to an earlier invalidation of the view.
13066      */
rebuildOutline()13067     private void rebuildOutline() {
13068         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13069         if (mAttachInfo == null) return;
13070 
13071         if (mOutlineProvider == null) {
13072             // no provider, remove outline
13073             mRenderNode.setOutline(null);
13074         } else {
13075             final Outline outline = mAttachInfo.mTmpOutline;
13076             outline.setEmpty();
13077             outline.setAlpha(1.0f);
13078 
13079             mOutlineProvider.getOutline(this, outline);
13080             mRenderNode.setOutline(outline);
13081         }
13082     }
13083 
13084     /**
13085      * HierarchyViewer only
13086      *
13087      * @hide
13088      */
13089     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()13090     public boolean hasShadow() {
13091         return mRenderNode.hasShadow();
13092     }
13093 
13094 
13095     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)13096     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13097         mRenderNode.setRevealClip(shouldClip, x, y, radius);
13098         invalidateViewProperty(false, false);
13099     }
13100 
13101     /**
13102      * Hit rectangle in parent's coordinates
13103      *
13104      * @param outRect The hit rectangle of the view.
13105      */
getHitRect(Rect outRect)13106     public void getHitRect(Rect outRect) {
13107         if (hasIdentityMatrix() || mAttachInfo == null) {
13108             outRect.set(mLeft, mTop, mRight, mBottom);
13109         } else {
13110             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13111             tmpRect.set(0, 0, getWidth(), getHeight());
13112             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13113             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13114                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13115         }
13116     }
13117 
13118     /**
13119      * Determines whether the given point, in local coordinates is inside the view.
13120      */
pointInView(float localX, float localY)13121     /*package*/ final boolean pointInView(float localX, float localY) {
13122         return pointInView(localX, localY, 0);
13123     }
13124 
13125     /**
13126      * Utility method to determine whether the given point, in local coordinates,
13127      * is inside the view, where the area of the view is expanded by the slop factor.
13128      * This method is called while processing touch-move events to determine if the event
13129      * is still within the view.
13130      *
13131      * @hide
13132      */
pointInView(float localX, float localY, float slop)13133     public boolean pointInView(float localX, float localY, float slop) {
13134         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13135                 localY < ((mBottom - mTop) + slop);
13136     }
13137 
13138     /**
13139      * When a view has focus and the user navigates away from it, the next view is searched for
13140      * starting from the rectangle filled in by this method.
13141      *
13142      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13143      * of the view.  However, if your view maintains some idea of internal selection,
13144      * such as a cursor, or a selected row or column, you should override this method and
13145      * fill in a more specific rectangle.
13146      *
13147      * @param r The rectangle to fill in, in this view's coordinates.
13148      */
getFocusedRect(Rect r)13149     public void getFocusedRect(Rect r) {
13150         getDrawingRect(r);
13151     }
13152 
13153     /**
13154      * If some part of this view is not clipped by any of its parents, then
13155      * return that area in r in global (root) coordinates. To convert r to local
13156      * coordinates (without taking possible View rotations into account), offset
13157      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13158      * If the view is completely clipped or translated out, return false.
13159      *
13160      * @param r If true is returned, r holds the global coordinates of the
13161      *        visible portion of this view.
13162      * @param globalOffset If true is returned, globalOffset holds the dx,dy
13163      *        between this view and its root. globalOffet may be null.
13164      * @return true if r is non-empty (i.e. part of the view is visible at the
13165      *         root level.
13166      */
getGlobalVisibleRect(Rect r, Point globalOffset)13167     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13168         int width = mRight - mLeft;
13169         int height = mBottom - mTop;
13170         if (width > 0 && height > 0) {
13171             r.set(0, 0, width, height);
13172             if (globalOffset != null) {
13173                 globalOffset.set(-mScrollX, -mScrollY);
13174             }
13175             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13176         }
13177         return false;
13178     }
13179 
getGlobalVisibleRect(Rect r)13180     public final boolean getGlobalVisibleRect(Rect r) {
13181         return getGlobalVisibleRect(r, null);
13182     }
13183 
getLocalVisibleRect(Rect r)13184     public final boolean getLocalVisibleRect(Rect r) {
13185         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13186         if (getGlobalVisibleRect(r, offset)) {
13187             r.offset(-offset.x, -offset.y); // make r local
13188             return true;
13189         }
13190         return false;
13191     }
13192 
13193     /**
13194      * Offset this view's vertical location by the specified number of pixels.
13195      *
13196      * @param offset the number of pixels to offset the view by
13197      */
offsetTopAndBottom(int offset)13198     public void offsetTopAndBottom(int offset) {
13199         if (offset != 0) {
13200             final boolean matrixIsIdentity = hasIdentityMatrix();
13201             if (matrixIsIdentity) {
13202                 if (isHardwareAccelerated()) {
13203                     invalidateViewProperty(false, false);
13204                 } else {
13205                     final ViewParent p = mParent;
13206                     if (p != null && mAttachInfo != null) {
13207                         final Rect r = mAttachInfo.mTmpInvalRect;
13208                         int minTop;
13209                         int maxBottom;
13210                         int yLoc;
13211                         if (offset < 0) {
13212                             minTop = mTop + offset;
13213                             maxBottom = mBottom;
13214                             yLoc = offset;
13215                         } else {
13216                             minTop = mTop;
13217                             maxBottom = mBottom + offset;
13218                             yLoc = 0;
13219                         }
13220                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13221                         p.invalidateChild(this, r);
13222                     }
13223                 }
13224             } else {
13225                 invalidateViewProperty(false, false);
13226             }
13227 
13228             mTop += offset;
13229             mBottom += offset;
13230             mRenderNode.offsetTopAndBottom(offset);
13231             if (isHardwareAccelerated()) {
13232                 invalidateViewProperty(false, false);
13233                 invalidateParentIfNeededAndWasQuickRejected();
13234             } else {
13235                 if (!matrixIsIdentity) {
13236                     invalidateViewProperty(false, true);
13237                 }
13238                 invalidateParentIfNeeded();
13239             }
13240             notifySubtreeAccessibilityStateChangedIfNeeded();
13241         }
13242     }
13243 
13244     /**
13245      * Offset this view's horizontal location by the specified amount of pixels.
13246      *
13247      * @param offset the number of pixels to offset the view by
13248      */
offsetLeftAndRight(int offset)13249     public void offsetLeftAndRight(int offset) {
13250         if (offset != 0) {
13251             final boolean matrixIsIdentity = hasIdentityMatrix();
13252             if (matrixIsIdentity) {
13253                 if (isHardwareAccelerated()) {
13254                     invalidateViewProperty(false, false);
13255                 } else {
13256                     final ViewParent p = mParent;
13257                     if (p != null && mAttachInfo != null) {
13258                         final Rect r = mAttachInfo.mTmpInvalRect;
13259                         int minLeft;
13260                         int maxRight;
13261                         if (offset < 0) {
13262                             minLeft = mLeft + offset;
13263                             maxRight = mRight;
13264                         } else {
13265                             minLeft = mLeft;
13266                             maxRight = mRight + offset;
13267                         }
13268                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13269                         p.invalidateChild(this, r);
13270                     }
13271                 }
13272             } else {
13273                 invalidateViewProperty(false, false);
13274             }
13275 
13276             mLeft += offset;
13277             mRight += offset;
13278             mRenderNode.offsetLeftAndRight(offset);
13279             if (isHardwareAccelerated()) {
13280                 invalidateViewProperty(false, false);
13281                 invalidateParentIfNeededAndWasQuickRejected();
13282             } else {
13283                 if (!matrixIsIdentity) {
13284                     invalidateViewProperty(false, true);
13285                 }
13286                 invalidateParentIfNeeded();
13287             }
13288             notifySubtreeAccessibilityStateChangedIfNeeded();
13289         }
13290     }
13291 
13292     /**
13293      * Get the LayoutParams associated with this view. All views should have
13294      * layout parameters. These supply parameters to the <i>parent</i> of this
13295      * view specifying how it should be arranged. There are many subclasses of
13296      * ViewGroup.LayoutParams, and these correspond to the different subclasses
13297      * of ViewGroup that are responsible for arranging their children.
13298      *
13299      * This method may return null if this View is not attached to a parent
13300      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13301      * was not invoked successfully. When a View is attached to a parent
13302      * ViewGroup, this method must not return null.
13303      *
13304      * @return The LayoutParams associated with this view, or null if no
13305      *         parameters have been set yet
13306      */
13307     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()13308     public ViewGroup.LayoutParams getLayoutParams() {
13309         return mLayoutParams;
13310     }
13311 
13312     /**
13313      * Set the layout parameters associated with this view. These supply
13314      * parameters to the <i>parent</i> of this view specifying how it should be
13315      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13316      * correspond to the different subclasses of ViewGroup that are responsible
13317      * for arranging their children.
13318      *
13319      * @param params The layout parameters for this view, cannot be null
13320      */
setLayoutParams(ViewGroup.LayoutParams params)13321     public void setLayoutParams(ViewGroup.LayoutParams params) {
13322         if (params == null) {
13323             throw new NullPointerException("Layout parameters cannot be null");
13324         }
13325         mLayoutParams = params;
13326         resolveLayoutParams();
13327         if (mParent instanceof ViewGroup) {
13328             ((ViewGroup) mParent).onSetLayoutParams(this, params);
13329         }
13330         requestLayout();
13331     }
13332 
13333     /**
13334      * Resolve the layout parameters depending on the resolved layout direction
13335      *
13336      * @hide
13337      */
resolveLayoutParams()13338     public void resolveLayoutParams() {
13339         if (mLayoutParams != null) {
13340             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13341         }
13342     }
13343 
13344     /**
13345      * Set the scrolled position of your view. This will cause a call to
13346      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13347      * invalidated.
13348      * @param x the x position to scroll to
13349      * @param y the y position to scroll to
13350      */
scrollTo(int x, int y)13351     public void scrollTo(int x, int y) {
13352         if (mScrollX != x || mScrollY != y) {
13353             int oldX = mScrollX;
13354             int oldY = mScrollY;
13355             mScrollX = x;
13356             mScrollY = y;
13357             invalidateParentCaches();
13358             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13359             if (!awakenScrollBars()) {
13360                 postInvalidateOnAnimation();
13361             }
13362         }
13363     }
13364 
13365     /**
13366      * Move the 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 x the amount of pixels to scroll by horizontally
13370      * @param y the amount of pixels to scroll by vertically
13371      */
scrollBy(int x, int y)13372     public void scrollBy(int x, int y) {
13373         scrollTo(mScrollX + x, mScrollY + y);
13374     }
13375 
13376     /**
13377      * <p>Trigger the scrollbars to draw. When invoked this method starts an
13378      * animation to fade the scrollbars out after a default delay. If a subclass
13379      * provides animated scrolling, the start delay should equal the duration
13380      * of the scrolling animation.</p>
13381      *
13382      * <p>The animation starts only if at least one of the scrollbars is
13383      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13384      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13385      * this method returns true, and false otherwise. If the animation is
13386      * started, this method calls {@link #invalidate()}; in that case the
13387      * caller should not call {@link #invalidate()}.</p>
13388      *
13389      * <p>This method should be invoked every time a subclass directly updates
13390      * the scroll parameters.</p>
13391      *
13392      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13393      * and {@link #scrollTo(int, int)}.</p>
13394      *
13395      * @return true if the animation is played, false otherwise
13396      *
13397      * @see #awakenScrollBars(int)
13398      * @see #scrollBy(int, int)
13399      * @see #scrollTo(int, int)
13400      * @see #isHorizontalScrollBarEnabled()
13401      * @see #isVerticalScrollBarEnabled()
13402      * @see #setHorizontalScrollBarEnabled(boolean)
13403      * @see #setVerticalScrollBarEnabled(boolean)
13404      */
awakenScrollBars()13405     protected boolean awakenScrollBars() {
13406         return mScrollCache != null &&
13407                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13408     }
13409 
13410     /**
13411      * Trigger the scrollbars to draw.
13412      * This method differs from awakenScrollBars() only in its default duration.
13413      * initialAwakenScrollBars() will show the scroll bars for longer than
13414      * usual to give the user more of a chance to notice them.
13415      *
13416      * @return true if the animation is played, false otherwise.
13417      */
initialAwakenScrollBars()13418     private boolean initialAwakenScrollBars() {
13419         return mScrollCache != null &&
13420                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13421     }
13422 
13423     /**
13424      * <p>
13425      * Trigger the scrollbars to draw. When invoked this method starts an
13426      * animation to fade the scrollbars out after a fixed delay. If a subclass
13427      * provides animated scrolling, the start delay should equal the duration of
13428      * the scrolling animation.
13429      * </p>
13430      *
13431      * <p>
13432      * The animation starts only if at least one of the scrollbars is enabled,
13433      * as specified by {@link #isHorizontalScrollBarEnabled()} and
13434      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13435      * this method returns true, and false otherwise. If the animation is
13436      * started, this method calls {@link #invalidate()}; in that case the caller
13437      * should not call {@link #invalidate()}.
13438      * </p>
13439      *
13440      * <p>
13441      * This method should be invoked every time a subclass directly updates the
13442      * scroll parameters.
13443      * </p>
13444      *
13445      * @param startDelay the delay, in milliseconds, after which the animation
13446      *        should start; when the delay is 0, the animation starts
13447      *        immediately
13448      * @return true if the animation is played, false otherwise
13449      *
13450      * @see #scrollBy(int, int)
13451      * @see #scrollTo(int, int)
13452      * @see #isHorizontalScrollBarEnabled()
13453      * @see #isVerticalScrollBarEnabled()
13454      * @see #setHorizontalScrollBarEnabled(boolean)
13455      * @see #setVerticalScrollBarEnabled(boolean)
13456      */
awakenScrollBars(int startDelay)13457     protected boolean awakenScrollBars(int startDelay) {
13458         return awakenScrollBars(startDelay, true);
13459     }
13460 
13461     /**
13462      * <p>
13463      * Trigger the scrollbars to draw. When invoked this method starts an
13464      * animation to fade the scrollbars out after a fixed delay. If a subclass
13465      * provides animated scrolling, the start delay should equal the duration of
13466      * the scrolling animation.
13467      * </p>
13468      *
13469      * <p>
13470      * The animation starts only if at least one of the scrollbars is enabled,
13471      * as specified by {@link #isHorizontalScrollBarEnabled()} and
13472      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13473      * this method returns true, and false otherwise. If the animation is
13474      * started, this method calls {@link #invalidate()} if the invalidate parameter
13475      * is set to true; in that case the caller
13476      * should not call {@link #invalidate()}.
13477      * </p>
13478      *
13479      * <p>
13480      * This method should be invoked every time a subclass directly updates the
13481      * scroll parameters.
13482      * </p>
13483      *
13484      * @param startDelay the delay, in milliseconds, after which the animation
13485      *        should start; when the delay is 0, the animation starts
13486      *        immediately
13487      *
13488      * @param invalidate Whether this method should call invalidate
13489      *
13490      * @return true if the animation is played, false otherwise
13491      *
13492      * @see #scrollBy(int, int)
13493      * @see #scrollTo(int, int)
13494      * @see #isHorizontalScrollBarEnabled()
13495      * @see #isVerticalScrollBarEnabled()
13496      * @see #setHorizontalScrollBarEnabled(boolean)
13497      * @see #setVerticalScrollBarEnabled(boolean)
13498      */
awakenScrollBars(int startDelay, boolean invalidate)13499     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13500         final ScrollabilityCache scrollCache = mScrollCache;
13501 
13502         if (scrollCache == null || !scrollCache.fadeScrollBars) {
13503             return false;
13504         }
13505 
13506         if (scrollCache.scrollBar == null) {
13507             scrollCache.scrollBar = new ScrollBarDrawable();
13508             scrollCache.scrollBar.setState(getDrawableState());
13509             scrollCache.scrollBar.setCallback(this);
13510         }
13511 
13512         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13513 
13514             if (invalidate) {
13515                 // Invalidate to show the scrollbars
13516                 postInvalidateOnAnimation();
13517             }
13518 
13519             if (scrollCache.state == ScrollabilityCache.OFF) {
13520                 // FIXME: this is copied from WindowManagerService.
13521                 // We should get this value from the system when it
13522                 // is possible to do so.
13523                 final int KEY_REPEAT_FIRST_DELAY = 750;
13524                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13525             }
13526 
13527             // Tell mScrollCache when we should start fading. This may
13528             // extend the fade start time if one was already scheduled
13529             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13530             scrollCache.fadeStartTime = fadeStartTime;
13531             scrollCache.state = ScrollabilityCache.ON;
13532 
13533             // Schedule our fader to run, unscheduling any old ones first
13534             if (mAttachInfo != null) {
13535                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
13536                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13537             }
13538 
13539             return true;
13540         }
13541 
13542         return false;
13543     }
13544 
13545     /**
13546      * Do not invalidate views which are not visible and which are not running an animation. They
13547      * will not get drawn and they should not set dirty flags as if they will be drawn
13548      */
skipInvalidate()13549     private boolean skipInvalidate() {
13550         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13551                 (!(mParent instanceof ViewGroup) ||
13552                         !((ViewGroup) mParent).isViewTransitioning(this));
13553     }
13554 
13555     /**
13556      * Mark the area defined by dirty as needing to be drawn. If the view is
13557      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13558      * point in the future.
13559      * <p>
13560      * This must be called from a UI thread. To call from a non-UI thread, call
13561      * {@link #postInvalidate()}.
13562      * <p>
13563      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13564      * {@code dirty}.
13565      *
13566      * @param dirty the rectangle representing the bounds of the dirty region
13567      */
invalidate(Rect dirty)13568     public void invalidate(Rect dirty) {
13569         final int scrollX = mScrollX;
13570         final int scrollY = mScrollY;
13571         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13572                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13573     }
13574 
13575     /**
13576      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13577      * coordinates of the dirty rect are relative to the view. If the view is
13578      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13579      * point in the future.
13580      * <p>
13581      * This must be called from a UI thread. To call from a non-UI thread, call
13582      * {@link #postInvalidate()}.
13583      *
13584      * @param l the left position of the dirty region
13585      * @param t the top position of the dirty region
13586      * @param r the right position of the dirty region
13587      * @param b the bottom position of the dirty region
13588      */
invalidate(int l, int t, int r, int b)13589     public void invalidate(int l, int t, int r, int b) {
13590         final int scrollX = mScrollX;
13591         final int scrollY = mScrollY;
13592         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13593     }
13594 
13595     /**
13596      * Invalidate the whole view. If the view is visible,
13597      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13598      * the future.
13599      * <p>
13600      * This must be called from a UI thread. To call from a non-UI thread, call
13601      * {@link #postInvalidate()}.
13602      */
invalidate()13603     public void invalidate() {
13604         invalidate(true);
13605     }
13606 
13607     /**
13608      * This is where the invalidate() work actually happens. A full invalidate()
13609      * causes the drawing cache to be invalidated, but this function can be
13610      * called with invalidateCache set to false to skip that invalidation step
13611      * for cases that do not need it (for example, a component that remains at
13612      * the same dimensions with the same content).
13613      *
13614      * @param invalidateCache Whether the drawing cache for this view should be
13615      *            invalidated as well. This is usually true for a full
13616      *            invalidate, but may be set to false if the View's contents or
13617      *            dimensions have not changed.
13618      */
invalidate(boolean invalidateCache)13619     void invalidate(boolean invalidateCache) {
13620         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13621     }
13622 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)13623     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13624             boolean fullInvalidate) {
13625         if (mGhostView != null) {
13626             mGhostView.invalidate(true);
13627             return;
13628         }
13629 
13630         if (skipInvalidate()) {
13631             return;
13632         }
13633 
13634         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13635                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13636                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13637                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13638             if (fullInvalidate) {
13639                 mLastIsOpaque = isOpaque();
13640                 mPrivateFlags &= ~PFLAG_DRAWN;
13641             }
13642 
13643             mPrivateFlags |= PFLAG_DIRTY;
13644 
13645             if (invalidateCache) {
13646                 mPrivateFlags |= PFLAG_INVALIDATED;
13647                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13648             }
13649 
13650             // Propagate the damage rectangle to the parent view.
13651             final AttachInfo ai = mAttachInfo;
13652             final ViewParent p = mParent;
13653             if (p != null && ai != null && l < r && t < b) {
13654                 final Rect damage = ai.mTmpInvalRect;
13655                 damage.set(l, t, r, b);
13656                 p.invalidateChild(this, damage);
13657             }
13658 
13659             // Damage the entire projection receiver, if necessary.
13660             if (mBackground != null && mBackground.isProjected()) {
13661                 final View receiver = getProjectionReceiver();
13662                 if (receiver != null) {
13663                     receiver.damageInParent();
13664                 }
13665             }
13666 
13667             // Damage the entire IsolatedZVolume receiving this view's shadow.
13668             if (isHardwareAccelerated() && getZ() != 0) {
13669                 damageShadowReceiver();
13670             }
13671         }
13672     }
13673 
13674     /**
13675      * @return this view's projection receiver, or {@code null} if none exists
13676      */
getProjectionReceiver()13677     private View getProjectionReceiver() {
13678         ViewParent p = getParent();
13679         while (p != null && p instanceof View) {
13680             final View v = (View) p;
13681             if (v.isProjectionReceiver()) {
13682                 return v;
13683             }
13684             p = p.getParent();
13685         }
13686 
13687         return null;
13688     }
13689 
13690     /**
13691      * @return whether the view is a projection receiver
13692      */
isProjectionReceiver()13693     private boolean isProjectionReceiver() {
13694         return mBackground != null;
13695     }
13696 
13697     /**
13698      * Damage area of the screen that can be covered by this View's shadow.
13699      *
13700      * This method will guarantee that any changes to shadows cast by a View
13701      * are damaged on the screen for future redraw.
13702      */
damageShadowReceiver()13703     private void damageShadowReceiver() {
13704         final AttachInfo ai = mAttachInfo;
13705         if (ai != null) {
13706             ViewParent p = getParent();
13707             if (p != null && p instanceof ViewGroup) {
13708                 final ViewGroup vg = (ViewGroup) p;
13709                 vg.damageInParent();
13710             }
13711         }
13712     }
13713 
13714     /**
13715      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13716      * set any flags or handle all of the cases handled by the default invalidation methods.
13717      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13718      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13719      * walk up the hierarchy, transforming the dirty rect as necessary.
13720      *
13721      * The method also handles normal invalidation logic if display list properties are not
13722      * being used in this view. The invalidateParent and forceRedraw flags are used by that
13723      * backup approach, to handle these cases used in the various property-setting methods.
13724      *
13725      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13726      * are not being used in this view
13727      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13728      * list properties are not being used in this view
13729      */
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)13730     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13731         if (!isHardwareAccelerated()
13732                 || !mRenderNode.isValid()
13733                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13734             if (invalidateParent) {
13735                 invalidateParentCaches();
13736             }
13737             if (forceRedraw) {
13738                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13739             }
13740             invalidate(false);
13741         } else {
13742             damageInParent();
13743         }
13744         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13745             damageShadowReceiver();
13746         }
13747     }
13748 
13749     /**
13750      * Tells the parent view to damage this view's bounds.
13751      *
13752      * @hide
13753      */
damageInParent()13754     protected void damageInParent() {
13755         final AttachInfo ai = mAttachInfo;
13756         final ViewParent p = mParent;
13757         if (p != null && ai != null) {
13758             final Rect r = ai.mTmpInvalRect;
13759             r.set(0, 0, mRight - mLeft, mBottom - mTop);
13760             if (mParent instanceof ViewGroup) {
13761                 ((ViewGroup) mParent).damageChild(this, r);
13762             } else {
13763                 mParent.invalidateChild(this, r);
13764             }
13765         }
13766     }
13767 
13768     /**
13769      * Utility method to transform a given Rect by the current matrix of this view.
13770      */
transformRect(final Rect rect)13771     void transformRect(final Rect rect) {
13772         if (!getMatrix().isIdentity()) {
13773             RectF boundingRect = mAttachInfo.mTmpTransformRect;
13774             boundingRect.set(rect);
13775             getMatrix().mapRect(boundingRect);
13776             rect.set((int) Math.floor(boundingRect.left),
13777                     (int) Math.floor(boundingRect.top),
13778                     (int) Math.ceil(boundingRect.right),
13779                     (int) Math.ceil(boundingRect.bottom));
13780         }
13781     }
13782 
13783     /**
13784      * Used to indicate that the parent of this view should clear its caches. This functionality
13785      * is used to force the parent to rebuild its display list (when hardware-accelerated),
13786      * which is necessary when various parent-managed properties of the view change, such as
13787      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13788      * clears the parent caches and does not causes an invalidate event.
13789      *
13790      * @hide
13791      */
invalidateParentCaches()13792     protected void invalidateParentCaches() {
13793         if (mParent instanceof View) {
13794             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13795         }
13796     }
13797 
13798     /**
13799      * Used to indicate that the parent of this view should be invalidated. This functionality
13800      * is used to force the parent to rebuild its display list (when hardware-accelerated),
13801      * which is necessary when various parent-managed properties of the view change, such as
13802      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13803      * an invalidation event to the parent.
13804      *
13805      * @hide
13806      */
invalidateParentIfNeeded()13807     protected void invalidateParentIfNeeded() {
13808         if (isHardwareAccelerated() && mParent instanceof View) {
13809             ((View) mParent).invalidate(true);
13810         }
13811     }
13812 
13813     /**
13814      * @hide
13815      */
invalidateParentIfNeededAndWasQuickRejected()13816     protected void invalidateParentIfNeededAndWasQuickRejected() {
13817         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13818             // View was rejected last time it was drawn by its parent; this may have changed
13819             invalidateParentIfNeeded();
13820         }
13821     }
13822 
13823     /**
13824      * Indicates whether this View is opaque. An opaque View guarantees that it will
13825      * draw all the pixels overlapping its bounds using a fully opaque color.
13826      *
13827      * Subclasses of View should override this method whenever possible to indicate
13828      * whether an instance is opaque. Opaque Views are treated in a special way by
13829      * the View hierarchy, possibly allowing it to perform optimizations during
13830      * invalidate/draw passes.
13831      *
13832      * @return True if this View is guaranteed to be fully opaque, false otherwise.
13833      */
13834     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()13835     public boolean isOpaque() {
13836         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13837                 getFinalAlpha() >= 1.0f;
13838     }
13839 
13840     /**
13841      * @hide
13842      */
computeOpaqueFlags()13843     protected void computeOpaqueFlags() {
13844         // Opaque if:
13845         //   - Has a background
13846         //   - Background is opaque
13847         //   - Doesn't have scrollbars or scrollbars overlay
13848 
13849         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13850             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13851         } else {
13852             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13853         }
13854 
13855         final int flags = mViewFlags;
13856         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13857                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13858                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13859             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13860         } else {
13861             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13862         }
13863     }
13864 
13865     /**
13866      * @hide
13867      */
hasOpaqueScrollbars()13868     protected boolean hasOpaqueScrollbars() {
13869         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13870     }
13871 
13872     /**
13873      * @return A handler associated with the thread running the View. This
13874      * handler can be used to pump events in the UI events queue.
13875      */
getHandler()13876     public Handler getHandler() {
13877         final AttachInfo attachInfo = mAttachInfo;
13878         if (attachInfo != null) {
13879             return attachInfo.mHandler;
13880         }
13881         return null;
13882     }
13883 
13884     /**
13885      * Returns the queue of runnable for this view.
13886      *
13887      * @return the queue of runnables for this view
13888      */
getRunQueue()13889     private HandlerActionQueue getRunQueue() {
13890         if (mRunQueue == null) {
13891             mRunQueue = new HandlerActionQueue();
13892         }
13893         return mRunQueue;
13894     }
13895 
13896     /**
13897      * Gets the view root associated with the View.
13898      * @return The view root, or null if none.
13899      * @hide
13900      */
getViewRootImpl()13901     public ViewRootImpl getViewRootImpl() {
13902         if (mAttachInfo != null) {
13903             return mAttachInfo.mViewRootImpl;
13904         }
13905         return null;
13906     }
13907 
13908     /**
13909      * @hide
13910      */
getHardwareRenderer()13911     public ThreadedRenderer getHardwareRenderer() {
13912         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13913     }
13914 
13915     /**
13916      * <p>Causes the Runnable to be added to the message queue.
13917      * The runnable will be run on the user interface thread.</p>
13918      *
13919      * @param action The Runnable that will be executed.
13920      *
13921      * @return Returns true if the Runnable was successfully placed in to the
13922      *         message queue.  Returns false on failure, usually because the
13923      *         looper processing the message queue is exiting.
13924      *
13925      * @see #postDelayed
13926      * @see #removeCallbacks
13927      */
post(Runnable action)13928     public boolean post(Runnable action) {
13929         final AttachInfo attachInfo = mAttachInfo;
13930         if (attachInfo != null) {
13931             return attachInfo.mHandler.post(action);
13932         }
13933 
13934         // Postpone the runnable until we know on which thread it needs to run.
13935         // Assume that the runnable will be successfully placed after attach.
13936         getRunQueue().post(action);
13937         return true;
13938     }
13939 
13940     /**
13941      * <p>Causes the Runnable to be added to the message queue, to be run
13942      * after the specified amount of time elapses.
13943      * The runnable will be run on the user interface thread.</p>
13944      *
13945      * @param action The Runnable that will be executed.
13946      * @param delayMillis The delay (in milliseconds) until the Runnable
13947      *        will be executed.
13948      *
13949      * @return true if the Runnable was successfully placed in to the
13950      *         message queue.  Returns false on failure, usually because the
13951      *         looper processing the message queue is exiting.  Note that a
13952      *         result of true does not mean the Runnable will be processed --
13953      *         if the looper is quit before the delivery time of the message
13954      *         occurs then the message will be dropped.
13955      *
13956      * @see #post
13957      * @see #removeCallbacks
13958      */
postDelayed(Runnable action, long delayMillis)13959     public boolean postDelayed(Runnable action, long delayMillis) {
13960         final AttachInfo attachInfo = mAttachInfo;
13961         if (attachInfo != null) {
13962             return attachInfo.mHandler.postDelayed(action, delayMillis);
13963         }
13964 
13965         // Postpone the runnable until we know on which thread it needs to run.
13966         // Assume that the runnable will be successfully placed after attach.
13967         getRunQueue().postDelayed(action, delayMillis);
13968         return true;
13969     }
13970 
13971     /**
13972      * <p>Causes the Runnable to execute on the next animation time step.
13973      * The runnable will be run on the user interface thread.</p>
13974      *
13975      * @param action The Runnable that will be executed.
13976      *
13977      * @see #postOnAnimationDelayed
13978      * @see #removeCallbacks
13979      */
postOnAnimation(Runnable action)13980     public void postOnAnimation(Runnable action) {
13981         final AttachInfo attachInfo = mAttachInfo;
13982         if (attachInfo != null) {
13983             attachInfo.mViewRootImpl.mChoreographer.postCallback(
13984                     Choreographer.CALLBACK_ANIMATION, action, null);
13985         } else {
13986             // Postpone the runnable until we know
13987             // on which thread it needs to run.
13988             getRunQueue().post(action);
13989         }
13990     }
13991 
13992     /**
13993      * <p>Causes the Runnable to execute on the next animation time step,
13994      * after the specified amount of time elapses.
13995      * The runnable will be run on the user interface thread.</p>
13996      *
13997      * @param action The Runnable that will be executed.
13998      * @param delayMillis The delay (in milliseconds) until the Runnable
13999      *        will be executed.
14000      *
14001      * @see #postOnAnimation
14002      * @see #removeCallbacks
14003      */
postOnAnimationDelayed(Runnable action, long delayMillis)14004     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14005         final AttachInfo attachInfo = mAttachInfo;
14006         if (attachInfo != null) {
14007             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14008                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14009         } else {
14010             // Postpone the runnable until we know
14011             // on which thread it needs to run.
14012             getRunQueue().postDelayed(action, delayMillis);
14013         }
14014     }
14015 
14016     /**
14017      * <p>Removes the specified Runnable from the message queue.</p>
14018      *
14019      * @param action The Runnable to remove from the message handling queue
14020      *
14021      * @return true if this view could ask the Handler to remove the Runnable,
14022      *         false otherwise. When the returned value is true, the Runnable
14023      *         may or may not have been actually removed from the message queue
14024      *         (for instance, if the Runnable was not in the queue already.)
14025      *
14026      * @see #post
14027      * @see #postDelayed
14028      * @see #postOnAnimation
14029      * @see #postOnAnimationDelayed
14030      */
removeCallbacks(Runnable action)14031     public boolean removeCallbacks(Runnable action) {
14032         if (action != null) {
14033             final AttachInfo attachInfo = mAttachInfo;
14034             if (attachInfo != null) {
14035                 attachInfo.mHandler.removeCallbacks(action);
14036                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14037                         Choreographer.CALLBACK_ANIMATION, action, null);
14038             }
14039             getRunQueue().removeCallbacks(action);
14040         }
14041         return true;
14042     }
14043 
14044     /**
14045      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14046      * Use this to invalidate the View from a non-UI thread.</p>
14047      *
14048      * <p>This method can be invoked from outside of the UI thread
14049      * only when this View is attached to a window.</p>
14050      *
14051      * @see #invalidate()
14052      * @see #postInvalidateDelayed(long)
14053      */
postInvalidate()14054     public void postInvalidate() {
14055         postInvalidateDelayed(0);
14056     }
14057 
14058     /**
14059      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14060      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14061      *
14062      * <p>This method can be invoked from outside of the UI thread
14063      * only when this View is attached to a window.</p>
14064      *
14065      * @param left The left coordinate of the rectangle to invalidate.
14066      * @param top The top coordinate of the rectangle to invalidate.
14067      * @param right The right coordinate of the rectangle to invalidate.
14068      * @param bottom The bottom coordinate of the rectangle to invalidate.
14069      *
14070      * @see #invalidate(int, int, int, int)
14071      * @see #invalidate(Rect)
14072      * @see #postInvalidateDelayed(long, int, int, int, int)
14073      */
postInvalidate(int left, int top, int right, int bottom)14074     public void postInvalidate(int left, int top, int right, int bottom) {
14075         postInvalidateDelayed(0, left, top, right, bottom);
14076     }
14077 
14078     /**
14079      * <p>Cause an invalidate to happen on a subsequent cycle through the event
14080      * loop. Waits for the specified amount of time.</p>
14081      *
14082      * <p>This method can be invoked from outside of the UI thread
14083      * only when this View is attached to a window.</p>
14084      *
14085      * @param delayMilliseconds the duration in milliseconds to delay the
14086      *         invalidation by
14087      *
14088      * @see #invalidate()
14089      * @see #postInvalidate()
14090      */
postInvalidateDelayed(long delayMilliseconds)14091     public void postInvalidateDelayed(long delayMilliseconds) {
14092         // We try only with the AttachInfo because there's no point in invalidating
14093         // if we are not attached to our window
14094         final AttachInfo attachInfo = mAttachInfo;
14095         if (attachInfo != null) {
14096             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14097         }
14098     }
14099 
14100     /**
14101      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14102      * through the event loop. Waits for the specified amount of time.</p>
14103      *
14104      * <p>This method can be invoked from outside of the UI thread
14105      * only when this View is attached to a window.</p>
14106      *
14107      * @param delayMilliseconds the duration in milliseconds to delay the
14108      *         invalidation by
14109      * @param left The left coordinate of the rectangle to invalidate.
14110      * @param top The top coordinate of the rectangle to invalidate.
14111      * @param right The right coordinate of the rectangle to invalidate.
14112      * @param bottom The bottom coordinate of the rectangle to invalidate.
14113      *
14114      * @see #invalidate(int, int, int, int)
14115      * @see #invalidate(Rect)
14116      * @see #postInvalidate(int, int, int, int)
14117      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)14118     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14119             int right, int bottom) {
14120 
14121         // We try only with the AttachInfo because there's no point in invalidating
14122         // if we are not attached to our window
14123         final AttachInfo attachInfo = mAttachInfo;
14124         if (attachInfo != null) {
14125             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14126             info.target = this;
14127             info.left = left;
14128             info.top = top;
14129             info.right = right;
14130             info.bottom = bottom;
14131 
14132             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14133         }
14134     }
14135 
14136     /**
14137      * <p>Cause an invalidate to happen on the next animation time step, typically the
14138      * next display frame.</p>
14139      *
14140      * <p>This method can be invoked from outside of the UI thread
14141      * only when this View is attached to a window.</p>
14142      *
14143      * @see #invalidate()
14144      */
postInvalidateOnAnimation()14145     public void postInvalidateOnAnimation() {
14146         // We try only with the AttachInfo because there's no point in invalidating
14147         // if we are not attached to our window
14148         final AttachInfo attachInfo = mAttachInfo;
14149         if (attachInfo != null) {
14150             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14151         }
14152     }
14153 
14154     /**
14155      * <p>Cause an invalidate of the specified area to happen on the next animation
14156      * time step, typically the next display frame.</p>
14157      *
14158      * <p>This method can be invoked from outside of the UI thread
14159      * only when this View is attached to a window.</p>
14160      *
14161      * @param left The left coordinate of the rectangle to invalidate.
14162      * @param top The top coordinate of the rectangle to invalidate.
14163      * @param right The right coordinate of the rectangle to invalidate.
14164      * @param bottom The bottom coordinate of the rectangle to invalidate.
14165      *
14166      * @see #invalidate(int, int, int, int)
14167      * @see #invalidate(Rect)
14168      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)14169     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14170         // We try only with the AttachInfo because there's no point in invalidating
14171         // if we are not attached to our window
14172         final AttachInfo attachInfo = mAttachInfo;
14173         if (attachInfo != null) {
14174             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14175             info.target = this;
14176             info.left = left;
14177             info.top = top;
14178             info.right = right;
14179             info.bottom = bottom;
14180 
14181             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14182         }
14183     }
14184 
14185     /**
14186      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14187      * This event is sent at most once every
14188      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14189      */
postSendViewScrolledAccessibilityEventCallback()14190     private void postSendViewScrolledAccessibilityEventCallback() {
14191         if (mSendViewScrolledAccessibilityEvent == null) {
14192             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14193         }
14194         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14195             mSendViewScrolledAccessibilityEvent.mIsPending = true;
14196             postDelayed(mSendViewScrolledAccessibilityEvent,
14197                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14198         }
14199     }
14200 
14201     /**
14202      * Called by a parent to request that a child update its values for mScrollX
14203      * and mScrollY if necessary. This will typically be done if the child is
14204      * animating a scroll using a {@link android.widget.Scroller Scroller}
14205      * object.
14206      */
computeScroll()14207     public void computeScroll() {
14208     }
14209 
14210     /**
14211      * <p>Indicate whether the horizontal edges are faded when the view is
14212      * scrolled horizontally.</p>
14213      *
14214      * @return true if the horizontal edges should are faded on scroll, false
14215      *         otherwise
14216      *
14217      * @see #setHorizontalFadingEdgeEnabled(boolean)
14218      *
14219      * @attr ref android.R.styleable#View_requiresFadingEdge
14220      */
isHorizontalFadingEdgeEnabled()14221     public boolean isHorizontalFadingEdgeEnabled() {
14222         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14223     }
14224 
14225     /**
14226      * <p>Define whether the horizontal edges should be faded when this view
14227      * is scrolled horizontally.</p>
14228      *
14229      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14230      *                                    be faded when the view is scrolled
14231      *                                    horizontally
14232      *
14233      * @see #isHorizontalFadingEdgeEnabled()
14234      *
14235      * @attr ref android.R.styleable#View_requiresFadingEdge
14236      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)14237     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14238         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14239             if (horizontalFadingEdgeEnabled) {
14240                 initScrollCache();
14241             }
14242 
14243             mViewFlags ^= FADING_EDGE_HORIZONTAL;
14244         }
14245     }
14246 
14247     /**
14248      * <p>Indicate whether the vertical edges are faded when the view is
14249      * scrolled horizontally.</p>
14250      *
14251      * @return true if the vertical edges should are faded on scroll, false
14252      *         otherwise
14253      *
14254      * @see #setVerticalFadingEdgeEnabled(boolean)
14255      *
14256      * @attr ref android.R.styleable#View_requiresFadingEdge
14257      */
isVerticalFadingEdgeEnabled()14258     public boolean isVerticalFadingEdgeEnabled() {
14259         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14260     }
14261 
14262     /**
14263      * <p>Define whether the vertical edges should be faded when this view
14264      * is scrolled vertically.</p>
14265      *
14266      * @param verticalFadingEdgeEnabled true if the vertical edges should
14267      *                                  be faded when the view is scrolled
14268      *                                  vertically
14269      *
14270      * @see #isVerticalFadingEdgeEnabled()
14271      *
14272      * @attr ref android.R.styleable#View_requiresFadingEdge
14273      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)14274     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14275         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14276             if (verticalFadingEdgeEnabled) {
14277                 initScrollCache();
14278             }
14279 
14280             mViewFlags ^= FADING_EDGE_VERTICAL;
14281         }
14282     }
14283 
14284     /**
14285      * Returns the strength, or intensity, of the top faded edge. The strength is
14286      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14287      * returns 0.0 or 1.0 but no value in between.
14288      *
14289      * Subclasses should override this method to provide a smoother fade transition
14290      * when scrolling occurs.
14291      *
14292      * @return the intensity of the top fade as a float between 0.0f and 1.0f
14293      */
getTopFadingEdgeStrength()14294     protected float getTopFadingEdgeStrength() {
14295         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14296     }
14297 
14298     /**
14299      * Returns the strength, or intensity, of the bottom faded edge. The strength is
14300      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14301      * returns 0.0 or 1.0 but no value in between.
14302      *
14303      * Subclasses should override this method to provide a smoother fade transition
14304      * when scrolling occurs.
14305      *
14306      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14307      */
getBottomFadingEdgeStrength()14308     protected float getBottomFadingEdgeStrength() {
14309         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14310                 computeVerticalScrollRange() ? 1.0f : 0.0f;
14311     }
14312 
14313     /**
14314      * Returns the strength, or intensity, of the left faded edge. The strength is
14315      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14316      * returns 0.0 or 1.0 but no value in between.
14317      *
14318      * Subclasses should override this method to provide a smoother fade transition
14319      * when scrolling occurs.
14320      *
14321      * @return the intensity of the left fade as a float between 0.0f and 1.0f
14322      */
getLeftFadingEdgeStrength()14323     protected float getLeftFadingEdgeStrength() {
14324         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14325     }
14326 
14327     /**
14328      * Returns the strength, or intensity, of the right faded edge. The strength is
14329      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14330      * returns 0.0 or 1.0 but no value in between.
14331      *
14332      * Subclasses should override this method to provide a smoother fade transition
14333      * when scrolling occurs.
14334      *
14335      * @return the intensity of the right fade as a float between 0.0f and 1.0f
14336      */
getRightFadingEdgeStrength()14337     protected float getRightFadingEdgeStrength() {
14338         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14339                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
14340     }
14341 
14342     /**
14343      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14344      * scrollbar is not drawn by default.</p>
14345      *
14346      * @return true if the horizontal scrollbar should be painted, false
14347      *         otherwise
14348      *
14349      * @see #setHorizontalScrollBarEnabled(boolean)
14350      */
isHorizontalScrollBarEnabled()14351     public boolean isHorizontalScrollBarEnabled() {
14352         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14353     }
14354 
14355     /**
14356      * <p>Define whether the horizontal scrollbar should be drawn or not. The
14357      * scrollbar is not drawn by default.</p>
14358      *
14359      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14360      *                                   be painted
14361      *
14362      * @see #isHorizontalScrollBarEnabled()
14363      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)14364     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14365         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14366             mViewFlags ^= SCROLLBARS_HORIZONTAL;
14367             computeOpaqueFlags();
14368             resolvePadding();
14369         }
14370     }
14371 
14372     /**
14373      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14374      * scrollbar is not drawn by default.</p>
14375      *
14376      * @return true if the vertical scrollbar should be painted, false
14377      *         otherwise
14378      *
14379      * @see #setVerticalScrollBarEnabled(boolean)
14380      */
isVerticalScrollBarEnabled()14381     public boolean isVerticalScrollBarEnabled() {
14382         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14383     }
14384 
14385     /**
14386      * <p>Define whether the vertical scrollbar should be drawn or not. The
14387      * scrollbar is not drawn by default.</p>
14388      *
14389      * @param verticalScrollBarEnabled true if the vertical scrollbar should
14390      *                                 be painted
14391      *
14392      * @see #isVerticalScrollBarEnabled()
14393      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)14394     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14395         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14396             mViewFlags ^= SCROLLBARS_VERTICAL;
14397             computeOpaqueFlags();
14398             resolvePadding();
14399         }
14400     }
14401 
14402     /**
14403      * @hide
14404      */
recomputePadding()14405     protected void recomputePadding() {
14406         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14407     }
14408 
14409     /**
14410      * Define whether scrollbars will fade when the view is not scrolling.
14411      *
14412      * @param fadeScrollbars whether to enable fading
14413      *
14414      * @attr ref android.R.styleable#View_fadeScrollbars
14415      */
setScrollbarFadingEnabled(boolean fadeScrollbars)14416     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14417         initScrollCache();
14418         final ScrollabilityCache scrollabilityCache = mScrollCache;
14419         scrollabilityCache.fadeScrollBars = fadeScrollbars;
14420         if (fadeScrollbars) {
14421             scrollabilityCache.state = ScrollabilityCache.OFF;
14422         } else {
14423             scrollabilityCache.state = ScrollabilityCache.ON;
14424         }
14425     }
14426 
14427     /**
14428      *
14429      * Returns true if scrollbars will fade when this view is not scrolling
14430      *
14431      * @return true if scrollbar fading is enabled
14432      *
14433      * @attr ref android.R.styleable#View_fadeScrollbars
14434      */
isScrollbarFadingEnabled()14435     public boolean isScrollbarFadingEnabled() {
14436         return mScrollCache != null && mScrollCache.fadeScrollBars;
14437     }
14438 
14439     /**
14440      *
14441      * Returns the delay before scrollbars fade.
14442      *
14443      * @return the delay before scrollbars fade
14444      *
14445      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14446      */
getScrollBarDefaultDelayBeforeFade()14447     public int getScrollBarDefaultDelayBeforeFade() {
14448         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14449                 mScrollCache.scrollBarDefaultDelayBeforeFade;
14450     }
14451 
14452     /**
14453      * Define the delay before scrollbars fade.
14454      *
14455      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14456      *
14457      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14458      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)14459     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14460         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14461     }
14462 
14463     /**
14464      *
14465      * Returns the scrollbar fade duration.
14466      *
14467      * @return the scrollbar fade duration
14468      *
14469      * @attr ref android.R.styleable#View_scrollbarFadeDuration
14470      */
getScrollBarFadeDuration()14471     public int getScrollBarFadeDuration() {
14472         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14473                 mScrollCache.scrollBarFadeDuration;
14474     }
14475 
14476     /**
14477      * Define the scrollbar fade duration.
14478      *
14479      * @param scrollBarFadeDuration - the scrollbar fade duration
14480      *
14481      * @attr ref android.R.styleable#View_scrollbarFadeDuration
14482      */
setScrollBarFadeDuration(int scrollBarFadeDuration)14483     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14484         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14485     }
14486 
14487     /**
14488      *
14489      * Returns the scrollbar size.
14490      *
14491      * @return the scrollbar size
14492      *
14493      * @attr ref android.R.styleable#View_scrollbarSize
14494      */
getScrollBarSize()14495     public int getScrollBarSize() {
14496         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14497                 mScrollCache.scrollBarSize;
14498     }
14499 
14500     /**
14501      * Define the scrollbar size.
14502      *
14503      * @param scrollBarSize - the scrollbar size
14504      *
14505      * @attr ref android.R.styleable#View_scrollbarSize
14506      */
setScrollBarSize(int scrollBarSize)14507     public void setScrollBarSize(int scrollBarSize) {
14508         getScrollCache().scrollBarSize = scrollBarSize;
14509     }
14510 
14511     /**
14512      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14513      * inset. When inset, they add to the padding of the view. And the scrollbars
14514      * can be drawn inside the padding area or on the edge of the view. For example,
14515      * if a view has a background drawable and you want to draw the scrollbars
14516      * inside the padding specified by the drawable, you can use
14517      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14518      * appear at the edge of the view, ignoring the padding, then you can use
14519      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14520      * @param style the style of the scrollbars. Should be one of
14521      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14522      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14523      * @see #SCROLLBARS_INSIDE_OVERLAY
14524      * @see #SCROLLBARS_INSIDE_INSET
14525      * @see #SCROLLBARS_OUTSIDE_OVERLAY
14526      * @see #SCROLLBARS_OUTSIDE_INSET
14527      *
14528      * @attr ref android.R.styleable#View_scrollbarStyle
14529      */
setScrollBarStyle(@crollBarStyle int style)14530     public void setScrollBarStyle(@ScrollBarStyle int style) {
14531         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14532             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14533             computeOpaqueFlags();
14534             resolvePadding();
14535         }
14536     }
14537 
14538     /**
14539      * <p>Returns the current scrollbar style.</p>
14540      * @return the current scrollbar style
14541      * @see #SCROLLBARS_INSIDE_OVERLAY
14542      * @see #SCROLLBARS_INSIDE_INSET
14543      * @see #SCROLLBARS_OUTSIDE_OVERLAY
14544      * @see #SCROLLBARS_OUTSIDE_INSET
14545      *
14546      * @attr ref android.R.styleable#View_scrollbarStyle
14547      */
14548     @ViewDebug.ExportedProperty(mapping = {
14549             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14550             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14551             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14552             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14553     })
14554     @ScrollBarStyle
getScrollBarStyle()14555     public int getScrollBarStyle() {
14556         return mViewFlags & SCROLLBARS_STYLE_MASK;
14557     }
14558 
14559     /**
14560      * <p>Compute the horizontal range that the horizontal scrollbar
14561      * represents.</p>
14562      *
14563      * <p>The range is expressed in arbitrary units that must be the same as the
14564      * units used by {@link #computeHorizontalScrollExtent()} and
14565      * {@link #computeHorizontalScrollOffset()}.</p>
14566      *
14567      * <p>The default range is the drawing width of this view.</p>
14568      *
14569      * @return the total horizontal range represented by the horizontal
14570      *         scrollbar
14571      *
14572      * @see #computeHorizontalScrollExtent()
14573      * @see #computeHorizontalScrollOffset()
14574      * @see android.widget.ScrollBarDrawable
14575      */
computeHorizontalScrollRange()14576     protected int computeHorizontalScrollRange() {
14577         return getWidth();
14578     }
14579 
14580     /**
14581      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14582      * within the horizontal range. This value is used to compute the position
14583      * of the thumb within the scrollbar's track.</p>
14584      *
14585      * <p>The range is expressed in arbitrary units that must be the same as the
14586      * units used by {@link #computeHorizontalScrollRange()} and
14587      * {@link #computeHorizontalScrollExtent()}.</p>
14588      *
14589      * <p>The default offset is the scroll offset of this view.</p>
14590      *
14591      * @return the horizontal offset of the scrollbar's thumb
14592      *
14593      * @see #computeHorizontalScrollRange()
14594      * @see #computeHorizontalScrollExtent()
14595      * @see android.widget.ScrollBarDrawable
14596      */
computeHorizontalScrollOffset()14597     protected int computeHorizontalScrollOffset() {
14598         return mScrollX;
14599     }
14600 
14601     /**
14602      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14603      * within the horizontal range. This value is used to compute the length
14604      * of the thumb within the scrollbar's track.</p>
14605      *
14606      * <p>The range is expressed in arbitrary units that must be the same as the
14607      * units used by {@link #computeHorizontalScrollRange()} and
14608      * {@link #computeHorizontalScrollOffset()}.</p>
14609      *
14610      * <p>The default extent is the drawing width of this view.</p>
14611      *
14612      * @return the horizontal extent of the scrollbar's thumb
14613      *
14614      * @see #computeHorizontalScrollRange()
14615      * @see #computeHorizontalScrollOffset()
14616      * @see android.widget.ScrollBarDrawable
14617      */
computeHorizontalScrollExtent()14618     protected int computeHorizontalScrollExtent() {
14619         return getWidth();
14620     }
14621 
14622     /**
14623      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14624      *
14625      * <p>The range is expressed in arbitrary units that must be the same as the
14626      * units used by {@link #computeVerticalScrollExtent()} and
14627      * {@link #computeVerticalScrollOffset()}.</p>
14628      *
14629      * @return the total vertical range represented by the vertical scrollbar
14630      *
14631      * <p>The default range is the drawing height of this view.</p>
14632      *
14633      * @see #computeVerticalScrollExtent()
14634      * @see #computeVerticalScrollOffset()
14635      * @see android.widget.ScrollBarDrawable
14636      */
computeVerticalScrollRange()14637     protected int computeVerticalScrollRange() {
14638         return getHeight();
14639     }
14640 
14641     /**
14642      * <p>Compute the vertical offset of the vertical scrollbar's thumb
14643      * within the horizontal range. This value is used to compute the position
14644      * of the thumb within the scrollbar's track.</p>
14645      *
14646      * <p>The range is expressed in arbitrary units that must be the same as the
14647      * units used by {@link #computeVerticalScrollRange()} and
14648      * {@link #computeVerticalScrollExtent()}.</p>
14649      *
14650      * <p>The default offset is the scroll offset of this view.</p>
14651      *
14652      * @return the vertical offset of the scrollbar's thumb
14653      *
14654      * @see #computeVerticalScrollRange()
14655      * @see #computeVerticalScrollExtent()
14656      * @see android.widget.ScrollBarDrawable
14657      */
computeVerticalScrollOffset()14658     protected int computeVerticalScrollOffset() {
14659         return mScrollY;
14660     }
14661 
14662     /**
14663      * <p>Compute the vertical extent of the vertical scrollbar's thumb
14664      * within the vertical range. This value is used to compute the length
14665      * of the thumb within the scrollbar's track.</p>
14666      *
14667      * <p>The range is expressed in arbitrary units that must be the same as the
14668      * units used by {@link #computeVerticalScrollRange()} and
14669      * {@link #computeVerticalScrollOffset()}.</p>
14670      *
14671      * <p>The default extent is the drawing height of this view.</p>
14672      *
14673      * @return the vertical extent of the scrollbar's thumb
14674      *
14675      * @see #computeVerticalScrollRange()
14676      * @see #computeVerticalScrollOffset()
14677      * @see android.widget.ScrollBarDrawable
14678      */
computeVerticalScrollExtent()14679     protected int computeVerticalScrollExtent() {
14680         return getHeight();
14681     }
14682 
14683     /**
14684      * Check if this view can be scrolled horizontally in a certain direction.
14685      *
14686      * @param direction Negative to check scrolling left, positive to check scrolling right.
14687      * @return true if this view can be scrolled in the specified direction, false otherwise.
14688      */
canScrollHorizontally(int direction)14689     public boolean canScrollHorizontally(int direction) {
14690         final int offset = computeHorizontalScrollOffset();
14691         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14692         if (range == 0) return false;
14693         if (direction < 0) {
14694             return offset > 0;
14695         } else {
14696             return offset < range - 1;
14697         }
14698     }
14699 
14700     /**
14701      * Check if this view can be scrolled vertically in a certain direction.
14702      *
14703      * @param direction Negative to check scrolling up, positive to check scrolling down.
14704      * @return true if this view can be scrolled in the specified direction, false otherwise.
14705      */
canScrollVertically(int direction)14706     public boolean canScrollVertically(int direction) {
14707         final int offset = computeVerticalScrollOffset();
14708         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14709         if (range == 0) return false;
14710         if (direction < 0) {
14711             return offset > 0;
14712         } else {
14713             return offset < range - 1;
14714         }
14715     }
14716 
getScrollIndicatorBounds(@onNull Rect out)14717     void getScrollIndicatorBounds(@NonNull Rect out) {
14718         out.left = mScrollX;
14719         out.right = mScrollX + mRight - mLeft;
14720         out.top = mScrollY;
14721         out.bottom = mScrollY + mBottom - mTop;
14722     }
14723 
onDrawScrollIndicators(Canvas c)14724     private void onDrawScrollIndicators(Canvas c) {
14725         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14726             // No scroll indicators enabled.
14727             return;
14728         }
14729 
14730         final Drawable dr = mScrollIndicatorDrawable;
14731         if (dr == null) {
14732             // Scroll indicators aren't supported here.
14733             return;
14734         }
14735 
14736         final int h = dr.getIntrinsicHeight();
14737         final int w = dr.getIntrinsicWidth();
14738         final Rect rect = mAttachInfo.mTmpInvalRect;
14739         getScrollIndicatorBounds(rect);
14740 
14741         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14742             final boolean canScrollUp = canScrollVertically(-1);
14743             if (canScrollUp) {
14744                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14745                 dr.draw(c);
14746             }
14747         }
14748 
14749         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14750             final boolean canScrollDown = canScrollVertically(1);
14751             if (canScrollDown) {
14752                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14753                 dr.draw(c);
14754             }
14755         }
14756 
14757         final int leftRtl;
14758         final int rightRtl;
14759         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14760             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14761             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14762         } else {
14763             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14764             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14765         }
14766 
14767         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14768         if ((mPrivateFlags3 & leftMask) != 0) {
14769             final boolean canScrollLeft = canScrollHorizontally(-1);
14770             if (canScrollLeft) {
14771                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14772                 dr.draw(c);
14773             }
14774         }
14775 
14776         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14777         if ((mPrivateFlags3 & rightMask) != 0) {
14778             final boolean canScrollRight = canScrollHorizontally(1);
14779             if (canScrollRight) {
14780                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14781                 dr.draw(c);
14782             }
14783         }
14784     }
14785 
getHorizontalScrollBarBounds(Rect bounds)14786     private void getHorizontalScrollBarBounds(Rect bounds) {
14787         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14788         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14789                 && !isVerticalScrollBarHidden();
14790         final int size = getHorizontalScrollbarHeight();
14791         final int verticalScrollBarGap = drawVerticalScrollBar ?
14792                 getVerticalScrollbarWidth() : 0;
14793         final int width = mRight - mLeft;
14794         final int height = mBottom - mTop;
14795         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14796         bounds.left = mScrollX + (mPaddingLeft & inside);
14797         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14798         bounds.bottom = bounds.top + size;
14799     }
14800 
getVerticalScrollBarBounds(Rect bounds)14801     private void getVerticalScrollBarBounds(Rect bounds) {
14802         if (mRoundScrollbarRenderer == null) {
14803             getStraightVerticalScrollBarBounds(bounds);
14804         } else {
14805             getRoundVerticalScrollBarBounds(bounds);
14806         }
14807     }
14808 
getRoundVerticalScrollBarBounds(Rect bounds)14809     private void getRoundVerticalScrollBarBounds(Rect bounds) {
14810         final int width = mRight - mLeft;
14811         final int height = mBottom - mTop;
14812         // Do not take padding into account as we always want the scrollbars
14813         // to hug the screen for round wearable devices.
14814         bounds.left = mScrollX;
14815         bounds.top = mScrollY;
14816         bounds.right = bounds.left + width;
14817         bounds.bottom = mScrollY + height;
14818     }
14819 
getStraightVerticalScrollBarBounds(Rect bounds)14820     private void getStraightVerticalScrollBarBounds(Rect bounds) {
14821         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14822         final int size = getVerticalScrollbarWidth();
14823         int verticalScrollbarPosition = mVerticalScrollbarPosition;
14824         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14825             verticalScrollbarPosition = isLayoutRtl() ?
14826                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14827         }
14828         final int width = mRight - mLeft;
14829         final int height = mBottom - mTop;
14830         switch (verticalScrollbarPosition) {
14831             default:
14832             case SCROLLBAR_POSITION_RIGHT:
14833                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14834                 break;
14835             case SCROLLBAR_POSITION_LEFT:
14836                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
14837                 break;
14838         }
14839         bounds.top = mScrollY + (mPaddingTop & inside);
14840         bounds.right = bounds.left + size;
14841         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14842     }
14843 
14844     /**
14845      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14846      * scrollbars are painted only if they have been awakened first.</p>
14847      *
14848      * @param canvas the canvas on which to draw the scrollbars
14849      *
14850      * @see #awakenScrollBars(int)
14851      */
onDrawScrollBars(Canvas canvas)14852     protected final void onDrawScrollBars(Canvas canvas) {
14853         // scrollbars are drawn only when the animation is running
14854         final ScrollabilityCache cache = mScrollCache;
14855 
14856         if (cache != null) {
14857 
14858             int state = cache.state;
14859 
14860             if (state == ScrollabilityCache.OFF) {
14861                 return;
14862             }
14863 
14864             boolean invalidate = false;
14865 
14866             if (state == ScrollabilityCache.FADING) {
14867                 // We're fading -- get our fade interpolation
14868                 if (cache.interpolatorValues == null) {
14869                     cache.interpolatorValues = new float[1];
14870                 }
14871 
14872                 float[] values = cache.interpolatorValues;
14873 
14874                 // Stops the animation if we're done
14875                 if (cache.scrollBarInterpolator.timeToValues(values) ==
14876                         Interpolator.Result.FREEZE_END) {
14877                     cache.state = ScrollabilityCache.OFF;
14878                 } else {
14879                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14880                 }
14881 
14882                 // This will make the scroll bars inval themselves after
14883                 // drawing. We only want this when we're fading so that
14884                 // we prevent excessive redraws
14885                 invalidate = true;
14886             } else {
14887                 // We're just on -- but we may have been fading before so
14888                 // reset alpha
14889                 cache.scrollBar.mutate().setAlpha(255);
14890             }
14891 
14892             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14893             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14894                     && !isVerticalScrollBarHidden();
14895 
14896             // Fork out the scroll bar drawing for round wearable devices.
14897             if (mRoundScrollbarRenderer != null) {
14898                 if (drawVerticalScrollBar) {
14899                     final Rect bounds = cache.mScrollBarBounds;
14900                     getVerticalScrollBarBounds(bounds);
14901                     mRoundScrollbarRenderer.drawRoundScrollbars(
14902                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
14903                     if (invalidate) {
14904                         invalidate();
14905                     }
14906                 }
14907                 // Do not draw horizontal scroll bars for round wearable devices.
14908             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14909                 final ScrollBarDrawable scrollBar = cache.scrollBar;
14910 
14911                 if (drawHorizontalScrollBar) {
14912                     scrollBar.setParameters(computeHorizontalScrollRange(),
14913                             computeHorizontalScrollOffset(),
14914                             computeHorizontalScrollExtent(), false);
14915                     final Rect bounds = cache.mScrollBarBounds;
14916                     getHorizontalScrollBarBounds(bounds);
14917                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14918                             bounds.right, bounds.bottom);
14919                     if (invalidate) {
14920                         invalidate(bounds);
14921                     }
14922                 }
14923 
14924                 if (drawVerticalScrollBar) {
14925                     scrollBar.setParameters(computeVerticalScrollRange(),
14926                             computeVerticalScrollOffset(),
14927                             computeVerticalScrollExtent(), true);
14928                     final Rect bounds = cache.mScrollBarBounds;
14929                     getVerticalScrollBarBounds(bounds);
14930                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14931                             bounds.right, bounds.bottom);
14932                     if (invalidate) {
14933                         invalidate(bounds);
14934                     }
14935                 }
14936             }
14937         }
14938     }
14939 
14940     /**
14941      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14942      * FastScroller is visible.
14943      * @return whether to temporarily hide the vertical scrollbar
14944      * @hide
14945      */
isVerticalScrollBarHidden()14946     protected boolean isVerticalScrollBarHidden() {
14947         return false;
14948     }
14949 
14950     /**
14951      * <p>Draw the horizontal scrollbar if
14952      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14953      *
14954      * @param canvas the canvas on which to draw the scrollbar
14955      * @param scrollBar the scrollbar's drawable
14956      *
14957      * @see #isHorizontalScrollBarEnabled()
14958      * @see #computeHorizontalScrollRange()
14959      * @see #computeHorizontalScrollExtent()
14960      * @see #computeHorizontalScrollOffset()
14961      * @see android.widget.ScrollBarDrawable
14962      * @hide
14963      */
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14964     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14965             int l, int t, int r, int b) {
14966         scrollBar.setBounds(l, t, r, b);
14967         scrollBar.draw(canvas);
14968     }
14969 
14970     /**
14971      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14972      * returns true.</p>
14973      *
14974      * @param canvas the canvas on which to draw the scrollbar
14975      * @param scrollBar the scrollbar's drawable
14976      *
14977      * @see #isVerticalScrollBarEnabled()
14978      * @see #computeVerticalScrollRange()
14979      * @see #computeVerticalScrollExtent()
14980      * @see #computeVerticalScrollOffset()
14981      * @see android.widget.ScrollBarDrawable
14982      * @hide
14983      */
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14984     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14985             int l, int t, int r, int b) {
14986         scrollBar.setBounds(l, t, r, b);
14987         scrollBar.draw(canvas);
14988     }
14989 
14990     /**
14991      * Implement this to do your drawing.
14992      *
14993      * @param canvas the canvas on which the background will be drawn
14994      */
onDraw(Canvas canvas)14995     protected void onDraw(Canvas canvas) {
14996     }
14997 
14998     /*
14999      * Caller is responsible for calling requestLayout if necessary.
15000      * (This allows addViewInLayout to not request a new layout.)
15001      */
assignParent(ViewParent parent)15002     void assignParent(ViewParent parent) {
15003         if (mParent == null) {
15004             mParent = parent;
15005         } else if (parent == null) {
15006             mParent = null;
15007         } else {
15008             throw new RuntimeException("view " + this + " being added, but"
15009                     + " it already has a parent");
15010         }
15011     }
15012 
15013     /**
15014      * This is called when the view is attached to a window.  At this point it
15015      * has a Surface and will start drawing.  Note that this function is
15016      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15017      * however it may be called any time before the first onDraw -- including
15018      * before or after {@link #onMeasure(int, int)}.
15019      *
15020      * @see #onDetachedFromWindow()
15021      */
15022     @CallSuper
onAttachedToWindow()15023     protected void onAttachedToWindow() {
15024         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15025             mParent.requestTransparentRegion(this);
15026         }
15027 
15028         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15029 
15030         jumpDrawablesToCurrentState();
15031 
15032         resetSubtreeAccessibilityStateChanged();
15033 
15034         // rebuild, since Outline not maintained while View is detached
15035         rebuildOutline();
15036 
15037         if (isFocused()) {
15038             InputMethodManager imm = InputMethodManager.peekInstance();
15039             if (imm != null) {
15040                 imm.focusIn(this);
15041             }
15042         }
15043     }
15044 
15045     /**
15046      * Resolve all RTL related properties.
15047      *
15048      * @return true if resolution of RTL properties has been done
15049      *
15050      * @hide
15051      */
resolveRtlPropertiesIfNeeded()15052     public boolean resolveRtlPropertiesIfNeeded() {
15053         if (!needRtlPropertiesResolution()) return false;
15054 
15055         // Order is important here: LayoutDirection MUST be resolved first
15056         if (!isLayoutDirectionResolved()) {
15057             resolveLayoutDirection();
15058             resolveLayoutParams();
15059         }
15060         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15061         if (!isTextDirectionResolved()) {
15062             resolveTextDirection();
15063         }
15064         if (!isTextAlignmentResolved()) {
15065             resolveTextAlignment();
15066         }
15067         // Should resolve Drawables before Padding because we need the layout direction of the
15068         // Drawable to correctly resolve Padding.
15069         if (!areDrawablesResolved()) {
15070             resolveDrawables();
15071         }
15072         if (!isPaddingResolved()) {
15073             resolvePadding();
15074         }
15075         onRtlPropertiesChanged(getLayoutDirection());
15076         return true;
15077     }
15078 
15079     /**
15080      * Reset resolution of all RTL related properties.
15081      *
15082      * @hide
15083      */
resetRtlProperties()15084     public void resetRtlProperties() {
15085         resetResolvedLayoutDirection();
15086         resetResolvedTextDirection();
15087         resetResolvedTextAlignment();
15088         resetResolvedPadding();
15089         resetResolvedDrawables();
15090     }
15091 
15092     /**
15093      * @see #onScreenStateChanged(int)
15094      */
dispatchScreenStateChanged(int screenState)15095     void dispatchScreenStateChanged(int screenState) {
15096         onScreenStateChanged(screenState);
15097     }
15098 
15099     /**
15100      * This method is called whenever the state of the screen this view is
15101      * attached to changes. A state change will usually occurs when the screen
15102      * turns on or off (whether it happens automatically or the user does it
15103      * manually.)
15104      *
15105      * @param screenState The new state of the screen. Can be either
15106      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15107      */
onScreenStateChanged(int screenState)15108     public void onScreenStateChanged(int screenState) {
15109     }
15110 
15111     /**
15112      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15113      */
hasRtlSupport()15114     private boolean hasRtlSupport() {
15115         return mContext.getApplicationInfo().hasRtlSupport();
15116     }
15117 
15118     /**
15119      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15120      * RTL not supported)
15121      */
isRtlCompatibilityMode()15122     private boolean isRtlCompatibilityMode() {
15123         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15124         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15125     }
15126 
15127     /**
15128      * @return true if RTL properties need resolution.
15129      *
15130      */
needRtlPropertiesResolution()15131     private boolean needRtlPropertiesResolution() {
15132         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15133     }
15134 
15135     /**
15136      * Called when any RTL property (layout direction or text direction or text alignment) has
15137      * been changed.
15138      *
15139      * Subclasses need to override this method to take care of cached information that depends on the
15140      * resolved layout direction, or to inform child views that inherit their layout direction.
15141      *
15142      * The default implementation does nothing.
15143      *
15144      * @param layoutDirection the direction of the layout
15145      *
15146      * @see #LAYOUT_DIRECTION_LTR
15147      * @see #LAYOUT_DIRECTION_RTL
15148      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)15149     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15150     }
15151 
15152     /**
15153      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15154      * that the parent directionality can and will be resolved before its children.
15155      *
15156      * @return true if resolution has been done, false otherwise.
15157      *
15158      * @hide
15159      */
resolveLayoutDirection()15160     public boolean resolveLayoutDirection() {
15161         // Clear any previous layout direction resolution
15162         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15163 
15164         if (hasRtlSupport()) {
15165             // Set resolved depending on layout direction
15166             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15167                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15168                 case LAYOUT_DIRECTION_INHERIT:
15169                     // We cannot resolve yet. LTR is by default and let the resolution happen again
15170                     // later to get the correct resolved value
15171                     if (!canResolveLayoutDirection()) return false;
15172 
15173                     // Parent has not yet resolved, LTR is still the default
15174                     try {
15175                         if (!mParent.isLayoutDirectionResolved()) return false;
15176 
15177                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15178                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15179                         }
15180                     } catch (AbstractMethodError e) {
15181                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15182                                 " does not fully implement ViewParent", e);
15183                     }
15184                     break;
15185                 case LAYOUT_DIRECTION_RTL:
15186                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15187                     break;
15188                 case LAYOUT_DIRECTION_LOCALE:
15189                     if((LAYOUT_DIRECTION_RTL ==
15190                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15191                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15192                     }
15193                     break;
15194                 default:
15195                     // Nothing to do, LTR by default
15196             }
15197         }
15198 
15199         // Set to resolved
15200         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15201         return true;
15202     }
15203 
15204     /**
15205      * Check if layout direction resolution can be done.
15206      *
15207      * @return true if layout direction resolution can be done otherwise return false.
15208      */
canResolveLayoutDirection()15209     public boolean canResolveLayoutDirection() {
15210         switch (getRawLayoutDirection()) {
15211             case LAYOUT_DIRECTION_INHERIT:
15212                 if (mParent != null) {
15213                     try {
15214                         return mParent.canResolveLayoutDirection();
15215                     } catch (AbstractMethodError e) {
15216                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15217                                 " does not fully implement ViewParent", e);
15218                     }
15219                 }
15220                 return false;
15221 
15222             default:
15223                 return true;
15224         }
15225     }
15226 
15227     /**
15228      * Reset the resolved layout direction. Layout direction will be resolved during a call to
15229      * {@link #onMeasure(int, int)}.
15230      *
15231      * @hide
15232      */
resetResolvedLayoutDirection()15233     public void resetResolvedLayoutDirection() {
15234         // Reset the current resolved bits
15235         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15236     }
15237 
15238     /**
15239      * @return true if the layout direction is inherited.
15240      *
15241      * @hide
15242      */
isLayoutDirectionInherited()15243     public boolean isLayoutDirectionInherited() {
15244         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15245     }
15246 
15247     /**
15248      * @return true if layout direction has been resolved.
15249      */
isLayoutDirectionResolved()15250     public boolean isLayoutDirectionResolved() {
15251         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15252     }
15253 
15254     /**
15255      * Return if padding has been resolved
15256      *
15257      * @hide
15258      */
isPaddingResolved()15259     boolean isPaddingResolved() {
15260         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15261     }
15262 
15263     /**
15264      * Resolves padding depending on layout direction, if applicable, and
15265      * recomputes internal padding values to adjust for scroll bars.
15266      *
15267      * @hide
15268      */
resolvePadding()15269     public void resolvePadding() {
15270         final int resolvedLayoutDirection = getLayoutDirection();
15271 
15272         if (!isRtlCompatibilityMode()) {
15273             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15274             // If start / end padding are defined, they will be resolved (hence overriding) to
15275             // left / right or right / left depending on the resolved layout direction.
15276             // If start / end padding are not defined, use the left / right ones.
15277             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15278                 Rect padding = sThreadLocal.get();
15279                 if (padding == null) {
15280                     padding = new Rect();
15281                     sThreadLocal.set(padding);
15282                 }
15283                 mBackground.getPadding(padding);
15284                 if (!mLeftPaddingDefined) {
15285                     mUserPaddingLeftInitial = padding.left;
15286                 }
15287                 if (!mRightPaddingDefined) {
15288                     mUserPaddingRightInitial = padding.right;
15289                 }
15290             }
15291             switch (resolvedLayoutDirection) {
15292                 case LAYOUT_DIRECTION_RTL:
15293                     if (mUserPaddingStart != UNDEFINED_PADDING) {
15294                         mUserPaddingRight = mUserPaddingStart;
15295                     } else {
15296                         mUserPaddingRight = mUserPaddingRightInitial;
15297                     }
15298                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
15299                         mUserPaddingLeft = mUserPaddingEnd;
15300                     } else {
15301                         mUserPaddingLeft = mUserPaddingLeftInitial;
15302                     }
15303                     break;
15304                 case LAYOUT_DIRECTION_LTR:
15305                 default:
15306                     if (mUserPaddingStart != UNDEFINED_PADDING) {
15307                         mUserPaddingLeft = mUserPaddingStart;
15308                     } else {
15309                         mUserPaddingLeft = mUserPaddingLeftInitial;
15310                     }
15311                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
15312                         mUserPaddingRight = mUserPaddingEnd;
15313                     } else {
15314                         mUserPaddingRight = mUserPaddingRightInitial;
15315                     }
15316             }
15317 
15318             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15319         }
15320 
15321         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15322         onRtlPropertiesChanged(resolvedLayoutDirection);
15323 
15324         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15325     }
15326 
15327     /**
15328      * Reset the resolved layout direction.
15329      *
15330      * @hide
15331      */
resetResolvedPadding()15332     public void resetResolvedPadding() {
15333         resetResolvedPaddingInternal();
15334     }
15335 
15336     /**
15337      * Used when we only want to reset *this* view's padding and not trigger overrides
15338      * in ViewGroup that reset children too.
15339      */
resetResolvedPaddingInternal()15340     void resetResolvedPaddingInternal() {
15341         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15342     }
15343 
15344     /**
15345      * This is called when the view is detached from a window.  At this point it
15346      * no longer has a surface for drawing.
15347      *
15348      * @see #onAttachedToWindow()
15349      */
15350     @CallSuper
onDetachedFromWindow()15351     protected void onDetachedFromWindow() {
15352     }
15353 
15354     /**
15355      * This is a framework-internal mirror of onDetachedFromWindow() that's called
15356      * after onDetachedFromWindow().
15357      *
15358      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15359      * The super method should be called at the end of the overridden method to ensure
15360      * subclasses are destroyed first
15361      *
15362      * @hide
15363      */
15364     @CallSuper
onDetachedFromWindowInternal()15365     protected void onDetachedFromWindowInternal() {
15366         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15367         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15368         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15369 
15370         removeUnsetPressCallback();
15371         removeLongPressCallback();
15372         removePerformClickCallback();
15373         removeSendViewScrolledAccessibilityEventCallback();
15374         stopNestedScroll();
15375 
15376         // Anything that started animating right before detach should already
15377         // be in its final state when re-attached.
15378         jumpDrawablesToCurrentState();
15379 
15380         destroyDrawingCache();
15381 
15382         cleanupDraw();
15383         mCurrentAnimation = null;
15384     }
15385 
cleanupDraw()15386     private void cleanupDraw() {
15387         resetDisplayList();
15388         if (mAttachInfo != null) {
15389             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15390         }
15391     }
15392 
invalidateInheritedLayoutMode(int layoutModeOfRoot)15393     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15394     }
15395 
15396     /**
15397      * @return The number of times this view has been attached to a window
15398      */
getWindowAttachCount()15399     protected int getWindowAttachCount() {
15400         return mWindowAttachCount;
15401     }
15402 
15403     /**
15404      * Retrieve a unique token identifying the window this view is attached to.
15405      * @return Return the window's token for use in
15406      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15407      */
getWindowToken()15408     public IBinder getWindowToken() {
15409         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15410     }
15411 
15412     /**
15413      * Retrieve the {@link WindowId} for the window this view is
15414      * currently attached to.
15415      */
getWindowId()15416     public WindowId getWindowId() {
15417         if (mAttachInfo == null) {
15418             return null;
15419         }
15420         if (mAttachInfo.mWindowId == null) {
15421             try {
15422                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15423                         mAttachInfo.mWindowToken);
15424                 mAttachInfo.mWindowId = new WindowId(
15425                         mAttachInfo.mIWindowId);
15426             } catch (RemoteException e) {
15427             }
15428         }
15429         return mAttachInfo.mWindowId;
15430     }
15431 
15432     /**
15433      * Retrieve a unique token identifying the top-level "real" window of
15434      * the window that this view is attached to.  That is, this is like
15435      * {@link #getWindowToken}, except if the window this view in is a panel
15436      * window (attached to another containing window), then the token of
15437      * the containing window is returned instead.
15438      *
15439      * @return Returns the associated window token, either
15440      * {@link #getWindowToken()} or the containing window's token.
15441      */
getApplicationWindowToken()15442     public IBinder getApplicationWindowToken() {
15443         AttachInfo ai = mAttachInfo;
15444         if (ai != null) {
15445             IBinder appWindowToken = ai.mPanelParentWindowToken;
15446             if (appWindowToken == null) {
15447                 appWindowToken = ai.mWindowToken;
15448             }
15449             return appWindowToken;
15450         }
15451         return null;
15452     }
15453 
15454     /**
15455      * Gets the logical display to which the view's window has been attached.
15456      *
15457      * @return The logical display, or null if the view is not currently attached to a window.
15458      */
getDisplay()15459     public Display getDisplay() {
15460         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15461     }
15462 
15463     /**
15464      * Retrieve private session object this view hierarchy is using to
15465      * communicate with the window manager.
15466      * @return the session object to communicate with the window manager
15467      */
getWindowSession()15468     /*package*/ IWindowSession getWindowSession() {
15469         return mAttachInfo != null ? mAttachInfo.mSession : null;
15470     }
15471 
15472     /**
15473      * Return the visibility value of the least visible component passed.
15474      */
combineVisibility(int vis1, int vis2)15475     int combineVisibility(int vis1, int vis2) {
15476         // This works because VISIBLE < INVISIBLE < GONE.
15477         return Math.max(vis1, vis2);
15478     }
15479 
15480     /**
15481      * @param info the {@link android.view.View.AttachInfo} to associated with
15482      *        this view
15483      */
dispatchAttachedToWindow(AttachInfo info, int visibility)15484     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15485         mAttachInfo = info;
15486         if (mOverlay != null) {
15487             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15488         }
15489         mWindowAttachCount++;
15490         // We will need to evaluate the drawable state at least once.
15491         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15492         if (mFloatingTreeObserver != null) {
15493             info.mTreeObserver.merge(mFloatingTreeObserver);
15494             mFloatingTreeObserver = null;
15495         }
15496 
15497         registerPendingFrameMetricsObservers();
15498 
15499         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15500             mAttachInfo.mScrollContainers.add(this);
15501             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15502         }
15503         // Transfer all pending runnables.
15504         if (mRunQueue != null) {
15505             mRunQueue.executeActions(info.mHandler);
15506             mRunQueue = null;
15507         }
15508         performCollectViewAttributes(mAttachInfo, visibility);
15509         onAttachedToWindow();
15510 
15511         ListenerInfo li = mListenerInfo;
15512         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15513                 li != null ? li.mOnAttachStateChangeListeners : null;
15514         if (listeners != null && listeners.size() > 0) {
15515             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15516             // perform the dispatching. The iterator is a safe guard against listeners that
15517             // could mutate the list by calling the various add/remove methods. This prevents
15518             // the array from being modified while we iterate it.
15519             for (OnAttachStateChangeListener listener : listeners) {
15520                 listener.onViewAttachedToWindow(this);
15521             }
15522         }
15523 
15524         int vis = info.mWindowVisibility;
15525         if (vis != GONE) {
15526             onWindowVisibilityChanged(vis);
15527             if (isShown()) {
15528                 // Calling onVisibilityAggregated directly here since the subtree will also
15529                 // receive dispatchAttachedToWindow and this same call
15530                 onVisibilityAggregated(vis == VISIBLE);
15531             }
15532         }
15533 
15534         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15535         // As all views in the subtree will already receive dispatchAttachedToWindow
15536         // traversing the subtree again here is not desired.
15537         onVisibilityChanged(this, visibility);
15538 
15539         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15540             // If nobody has evaluated the drawable state yet, then do it now.
15541             refreshDrawableState();
15542         }
15543         needGlobalAttributesUpdate(false);
15544     }
15545 
dispatchDetachedFromWindow()15546     void dispatchDetachedFromWindow() {
15547         AttachInfo info = mAttachInfo;
15548         if (info != null) {
15549             int vis = info.mWindowVisibility;
15550             if (vis != GONE) {
15551                 onWindowVisibilityChanged(GONE);
15552                 if (isShown()) {
15553                     // Invoking onVisibilityAggregated directly here since the subtree
15554                     // will also receive detached from window
15555                     onVisibilityAggregated(false);
15556                 }
15557             }
15558         }
15559 
15560         onDetachedFromWindow();
15561         onDetachedFromWindowInternal();
15562 
15563         InputMethodManager imm = InputMethodManager.peekInstance();
15564         if (imm != null) {
15565             imm.onViewDetachedFromWindow(this);
15566         }
15567 
15568         ListenerInfo li = mListenerInfo;
15569         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15570                 li != null ? li.mOnAttachStateChangeListeners : null;
15571         if (listeners != null && listeners.size() > 0) {
15572             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15573             // perform the dispatching. The iterator is a safe guard against listeners that
15574             // could mutate the list by calling the various add/remove methods. This prevents
15575             // the array from being modified while we iterate it.
15576             for (OnAttachStateChangeListener listener : listeners) {
15577                 listener.onViewDetachedFromWindow(this);
15578             }
15579         }
15580 
15581         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15582             mAttachInfo.mScrollContainers.remove(this);
15583             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15584         }
15585 
15586         mAttachInfo = null;
15587         if (mOverlay != null) {
15588             mOverlay.getOverlayView().dispatchDetachedFromWindow();
15589         }
15590     }
15591 
15592     /**
15593      * Cancel any deferred high-level input events that were previously posted to the event queue.
15594      *
15595      * <p>Many views post high-level events such as click handlers to the event queue
15596      * to run deferred in order to preserve a desired user experience - clearing visible
15597      * pressed states before executing, etc. This method will abort any events of this nature
15598      * that are currently in flight.</p>
15599      *
15600      * <p>Custom views that generate their own high-level deferred input events should override
15601      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15602      *
15603      * <p>This will also cancel pending input events for any child views.</p>
15604      *
15605      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15606      * This will not impact newer events posted after this call that may occur as a result of
15607      * lower-level input events still waiting in the queue. If you are trying to prevent
15608      * double-submitted  events for the duration of some sort of asynchronous transaction
15609      * you should also take other steps to protect against unexpected double inputs e.g. calling
15610      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15611      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15612      */
cancelPendingInputEvents()15613     public final void cancelPendingInputEvents() {
15614         dispatchCancelPendingInputEvents();
15615     }
15616 
15617     /**
15618      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15619      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15620      */
dispatchCancelPendingInputEvents()15621     void dispatchCancelPendingInputEvents() {
15622         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15623         onCancelPendingInputEvents();
15624         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15625             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15626                     " did not call through to super.onCancelPendingInputEvents()");
15627         }
15628     }
15629 
15630     /**
15631      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15632      * a parent view.
15633      *
15634      * <p>This method is responsible for removing any pending high-level input events that were
15635      * posted to the event queue to run later. Custom view classes that post their own deferred
15636      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15637      * {@link android.os.Handler} should override this method, call
15638      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15639      * </p>
15640      */
onCancelPendingInputEvents()15641     public void onCancelPendingInputEvents() {
15642         removePerformClickCallback();
15643         cancelLongPress();
15644         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15645     }
15646 
15647     /**
15648      * Store this view hierarchy's frozen state into the given container.
15649      *
15650      * @param container The SparseArray in which to save the view's state.
15651      *
15652      * @see #restoreHierarchyState(android.util.SparseArray)
15653      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15654      * @see #onSaveInstanceState()
15655      */
saveHierarchyState(SparseArray<Parcelable> container)15656     public void saveHierarchyState(SparseArray<Parcelable> container) {
15657         dispatchSaveInstanceState(container);
15658     }
15659 
15660     /**
15661      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15662      * this view and its children. May be overridden to modify how freezing happens to a
15663      * view's children; for example, some views may want to not store state for their children.
15664      *
15665      * @param container The SparseArray in which to save the view's state.
15666      *
15667      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15668      * @see #saveHierarchyState(android.util.SparseArray)
15669      * @see #onSaveInstanceState()
15670      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)15671     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15672         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15673             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15674             Parcelable state = onSaveInstanceState();
15675             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15676                 throw new IllegalStateException(
15677                         "Derived class did not call super.onSaveInstanceState()");
15678             }
15679             if (state != null) {
15680                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15681                 // + ": " + state);
15682                 container.put(mID, state);
15683             }
15684         }
15685     }
15686 
15687     /**
15688      * Hook allowing a view to generate a representation of its internal state
15689      * that can later be used to create a new instance with that same state.
15690      * This state should only contain information that is not persistent or can
15691      * not be reconstructed later. For example, you will never store your
15692      * current position on screen because that will be computed again when a
15693      * new instance of the view is placed in its view hierarchy.
15694      * <p>
15695      * Some examples of things you may store here: the current cursor position
15696      * in a text view (but usually not the text itself since that is stored in a
15697      * content provider or other persistent storage), the currently selected
15698      * item in a list view.
15699      *
15700      * @return Returns a Parcelable object containing the view's current dynamic
15701      *         state, or null if there is nothing interesting to save. The
15702      *         default implementation returns null.
15703      * @see #onRestoreInstanceState(android.os.Parcelable)
15704      * @see #saveHierarchyState(android.util.SparseArray)
15705      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15706      * @see #setSaveEnabled(boolean)
15707      */
15708     @CallSuper
onSaveInstanceState()15709     protected Parcelable onSaveInstanceState() {
15710         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15711         if (mStartActivityRequestWho != null) {
15712             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15713             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15714             return state;
15715         }
15716         return BaseSavedState.EMPTY_STATE;
15717     }
15718 
15719     /**
15720      * Restore this view hierarchy's frozen state from the given container.
15721      *
15722      * @param container The SparseArray which holds previously frozen states.
15723      *
15724      * @see #saveHierarchyState(android.util.SparseArray)
15725      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15726      * @see #onRestoreInstanceState(android.os.Parcelable)
15727      */
restoreHierarchyState(SparseArray<Parcelable> container)15728     public void restoreHierarchyState(SparseArray<Parcelable> container) {
15729         dispatchRestoreInstanceState(container);
15730     }
15731 
15732     /**
15733      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15734      * state for this view and its children. May be overridden to modify how restoring
15735      * happens to a view's children; for example, some views may want to not store state
15736      * for their children.
15737      *
15738      * @param container The SparseArray which holds previously saved state.
15739      *
15740      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15741      * @see #restoreHierarchyState(android.util.SparseArray)
15742      * @see #onRestoreInstanceState(android.os.Parcelable)
15743      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)15744     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15745         if (mID != NO_ID) {
15746             Parcelable state = container.get(mID);
15747             if (state != null) {
15748                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15749                 // + ": " + state);
15750                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15751                 onRestoreInstanceState(state);
15752                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15753                     throw new IllegalStateException(
15754                             "Derived class did not call super.onRestoreInstanceState()");
15755                 }
15756             }
15757         }
15758     }
15759 
15760     /**
15761      * Hook allowing a view to re-apply a representation of its internal state that had previously
15762      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15763      * null state.
15764      *
15765      * @param state The frozen state that had previously been returned by
15766      *        {@link #onSaveInstanceState}.
15767      *
15768      * @see #onSaveInstanceState()
15769      * @see #restoreHierarchyState(android.util.SparseArray)
15770      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15771      */
15772     @CallSuper
onRestoreInstanceState(Parcelable state)15773     protected void onRestoreInstanceState(Parcelable state) {
15774         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15775         if (state != null && !(state instanceof AbsSavedState)) {
15776             throw new IllegalArgumentException("Wrong state class, expecting View State but "
15777                     + "received " + state.getClass().toString() + " instead. This usually happens "
15778                     + "when two views of different type have the same id in the same hierarchy. "
15779                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15780                     + "other views do not use the same id.");
15781         }
15782         if (state != null && state instanceof BaseSavedState) {
15783             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15784         }
15785     }
15786 
15787     /**
15788      * <p>Return the time at which the drawing of the view hierarchy started.</p>
15789      *
15790      * @return the drawing start time in milliseconds
15791      */
getDrawingTime()15792     public long getDrawingTime() {
15793         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15794     }
15795 
15796     /**
15797      * <p>Enables or disables the duplication of the parent's state into this view. When
15798      * duplication is enabled, this view gets its drawable state from its parent rather
15799      * than from its own internal properties.</p>
15800      *
15801      * <p>Note: in the current implementation, setting this property to true after the
15802      * view was added to a ViewGroup might have no effect at all. This property should
15803      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15804      *
15805      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15806      * property is enabled, an exception will be thrown.</p>
15807      *
15808      * <p>Note: if the child view uses and updates additional states which are unknown to the
15809      * parent, these states should not be affected by this method.</p>
15810      *
15811      * @param enabled True to enable duplication of the parent's drawable state, false
15812      *                to disable it.
15813      *
15814      * @see #getDrawableState()
15815      * @see #isDuplicateParentStateEnabled()
15816      */
setDuplicateParentStateEnabled(boolean enabled)15817     public void setDuplicateParentStateEnabled(boolean enabled) {
15818         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15819     }
15820 
15821     /**
15822      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15823      *
15824      * @return True if this view's drawable state is duplicated from the parent,
15825      *         false otherwise
15826      *
15827      * @see #getDrawableState()
15828      * @see #setDuplicateParentStateEnabled(boolean)
15829      */
isDuplicateParentStateEnabled()15830     public boolean isDuplicateParentStateEnabled() {
15831         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15832     }
15833 
15834     /**
15835      * <p>Specifies the type of layer backing this view. The layer can be
15836      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15837      * {@link #LAYER_TYPE_HARDWARE}.</p>
15838      *
15839      * <p>A layer is associated with an optional {@link android.graphics.Paint}
15840      * instance that controls how the layer is composed on screen. The following
15841      * properties of the paint are taken into account when composing the layer:</p>
15842      * <ul>
15843      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15844      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15845      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15846      * </ul>
15847      *
15848      * <p>If this view has an alpha value set to < 1.0 by calling
15849      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15850      * by this view's alpha value.</p>
15851      *
15852      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15853      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15854      * for more information on when and how to use layers.</p>
15855      *
15856      * @param layerType The type of layer to use with this view, must be one of
15857      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15858      *        {@link #LAYER_TYPE_HARDWARE}
15859      * @param paint The paint used to compose the layer. This argument is optional
15860      *        and can be null. It is ignored when the layer type is
15861      *        {@link #LAYER_TYPE_NONE}
15862      *
15863      * @see #getLayerType()
15864      * @see #LAYER_TYPE_NONE
15865      * @see #LAYER_TYPE_SOFTWARE
15866      * @see #LAYER_TYPE_HARDWARE
15867      * @see #setAlpha(float)
15868      *
15869      * @attr ref android.R.styleable#View_layerType
15870      */
setLayerType(int layerType, @Nullable Paint paint)15871     public void setLayerType(int layerType, @Nullable Paint paint) {
15872         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15873             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15874                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15875         }
15876 
15877         boolean typeChanged = mRenderNode.setLayerType(layerType);
15878 
15879         if (!typeChanged) {
15880             setLayerPaint(paint);
15881             return;
15882         }
15883 
15884         if (layerType != LAYER_TYPE_SOFTWARE) {
15885             // Destroy any previous software drawing cache if present
15886             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15887             // drawing cache created in View#draw when drawing to a SW canvas.
15888             destroyDrawingCache();
15889         }
15890 
15891         mLayerType = layerType;
15892         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15893         mRenderNode.setLayerPaint(mLayerPaint);
15894 
15895         // draw() behaves differently if we are on a layer, so we need to
15896         // invalidate() here
15897         invalidateParentCaches();
15898         invalidate(true);
15899     }
15900 
15901     /**
15902      * Updates the {@link Paint} object used with the current layer (used only if the current
15903      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15904      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15905      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15906      * ensure that the view gets redrawn immediately.
15907      *
15908      * <p>A layer is associated with an optional {@link android.graphics.Paint}
15909      * instance that controls how the layer is composed on screen. The following
15910      * properties of the paint are taken into account when composing the layer:</p>
15911      * <ul>
15912      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15913      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15914      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15915      * </ul>
15916      *
15917      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15918      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15919      *
15920      * @param paint The paint used to compose the layer. This argument is optional
15921      *        and can be null. It is ignored when the layer type is
15922      *        {@link #LAYER_TYPE_NONE}
15923      *
15924      * @see #setLayerType(int, android.graphics.Paint)
15925      */
setLayerPaint(@ullable Paint paint)15926     public void setLayerPaint(@Nullable Paint paint) {
15927         int layerType = getLayerType();
15928         if (layerType != LAYER_TYPE_NONE) {
15929             mLayerPaint = paint;
15930             if (layerType == LAYER_TYPE_HARDWARE) {
15931                 if (mRenderNode.setLayerPaint(paint)) {
15932                     invalidateViewProperty(false, false);
15933                 }
15934             } else {
15935                 invalidate();
15936             }
15937         }
15938     }
15939 
15940     /**
15941      * Indicates what type of layer is currently associated with this view. By default
15942      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15943      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15944      * for more information on the different types of layers.
15945      *
15946      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15947      *         {@link #LAYER_TYPE_HARDWARE}
15948      *
15949      * @see #setLayerType(int, android.graphics.Paint)
15950      * @see #buildLayer()
15951      * @see #LAYER_TYPE_NONE
15952      * @see #LAYER_TYPE_SOFTWARE
15953      * @see #LAYER_TYPE_HARDWARE
15954      */
getLayerType()15955     public int getLayerType() {
15956         return mLayerType;
15957     }
15958 
15959     /**
15960      * Forces this view's layer to be created and this view to be rendered
15961      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15962      * invoking this method will have no effect.
15963      *
15964      * This method can for instance be used to render a view into its layer before
15965      * starting an animation. If this view is complex, rendering into the layer
15966      * before starting the animation will avoid skipping frames.
15967      *
15968      * @throws IllegalStateException If this view is not attached to a window
15969      *
15970      * @see #setLayerType(int, android.graphics.Paint)
15971      */
buildLayer()15972     public void buildLayer() {
15973         if (mLayerType == LAYER_TYPE_NONE) return;
15974 
15975         final AttachInfo attachInfo = mAttachInfo;
15976         if (attachInfo == null) {
15977             throw new IllegalStateException("This view must be attached to a window first");
15978         }
15979 
15980         if (getWidth() == 0 || getHeight() == 0) {
15981             return;
15982         }
15983 
15984         switch (mLayerType) {
15985             case LAYER_TYPE_HARDWARE:
15986                 updateDisplayListIfDirty();
15987                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15988                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15989                 }
15990                 break;
15991             case LAYER_TYPE_SOFTWARE:
15992                 buildDrawingCache(true);
15993                 break;
15994         }
15995     }
15996 
15997     /**
15998      * Destroys all hardware rendering resources. This method is invoked
15999      * when the system needs to reclaim resources. Upon execution of this
16000      * method, you should free any OpenGL resources created by the view.
16001      *
16002      * Note: you <strong>must</strong> call
16003      * <code>super.destroyHardwareResources()</code> when overriding
16004      * this method.
16005      *
16006      * @hide
16007      */
16008     @CallSuper
destroyHardwareResources()16009     protected void destroyHardwareResources() {
16010         // Although the Layer will be destroyed by RenderNode, we want to release
16011         // the staging display list, which is also a signal to RenderNode that it's
16012         // safe to free its copy of the display list as it knows that we will
16013         // push an updated DisplayList if we try to draw again
16014         resetDisplayList();
16015     }
16016 
16017     /**
16018      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16019      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16020      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16021      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16022      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16023      * null.</p>
16024      *
16025      * <p>Enabling the drawing cache is similar to
16026      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16027      * acceleration is turned off. When hardware acceleration is turned on, enabling the
16028      * drawing cache has no effect on rendering because the system uses a different mechanism
16029      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16030      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16031      * for information on how to enable software and hardware layers.</p>
16032      *
16033      * <p>This API can be used to manually generate
16034      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16035      * {@link #getDrawingCache()}.</p>
16036      *
16037      * @param enabled true to enable the drawing cache, false otherwise
16038      *
16039      * @see #isDrawingCacheEnabled()
16040      * @see #getDrawingCache()
16041      * @see #buildDrawingCache()
16042      * @see #setLayerType(int, android.graphics.Paint)
16043      */
setDrawingCacheEnabled(boolean enabled)16044     public void setDrawingCacheEnabled(boolean enabled) {
16045         mCachingFailed = false;
16046         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16047     }
16048 
16049     /**
16050      * <p>Indicates whether the drawing cache is enabled for this view.</p>
16051      *
16052      * @return true if the drawing cache is enabled
16053      *
16054      * @see #setDrawingCacheEnabled(boolean)
16055      * @see #getDrawingCache()
16056      */
16057     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()16058     public boolean isDrawingCacheEnabled() {
16059         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16060     }
16061 
16062     /**
16063      * Debugging utility which recursively outputs the dirty state of a view and its
16064      * descendants.
16065      *
16066      * @hide
16067      */
16068     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)16069     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16070         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16071                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16072                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16073                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16074         if (clear) {
16075             mPrivateFlags &= clearMask;
16076         }
16077         if (this instanceof ViewGroup) {
16078             ViewGroup parent = (ViewGroup) this;
16079             final int count = parent.getChildCount();
16080             for (int i = 0; i < count; i++) {
16081                 final View child = parent.getChildAt(i);
16082                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
16083             }
16084         }
16085     }
16086 
16087     /**
16088      * This method is used by ViewGroup to cause its children to restore or recreate their
16089      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16090      * to recreate its own display list, which would happen if it went through the normal
16091      * draw/dispatchDraw mechanisms.
16092      *
16093      * @hide
16094      */
dispatchGetDisplayList()16095     protected void dispatchGetDisplayList() {}
16096 
16097     /**
16098      * A view that is not attached or hardware accelerated cannot create a display list.
16099      * This method checks these conditions and returns the appropriate result.
16100      *
16101      * @return true if view has the ability to create a display list, false otherwise.
16102      *
16103      * @hide
16104      */
canHaveDisplayList()16105     public boolean canHaveDisplayList() {
16106         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
16107     }
16108 
16109     /**
16110      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16111      * @hide
16112      */
16113     @NonNull
updateDisplayListIfDirty()16114     public RenderNode updateDisplayListIfDirty() {
16115         final RenderNode renderNode = mRenderNode;
16116         if (!canHaveDisplayList()) {
16117             // can't populate RenderNode, don't try
16118             return renderNode;
16119         }
16120 
16121         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16122                 || !renderNode.isValid()
16123                 || (mRecreateDisplayList)) {
16124             // Don't need to recreate the display list, just need to tell our
16125             // children to restore/recreate theirs
16126             if (renderNode.isValid()
16127                     && !mRecreateDisplayList) {
16128                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16129                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16130                 dispatchGetDisplayList();
16131 
16132                 return renderNode; // no work needed
16133             }
16134 
16135             // If we got here, we're recreating it. Mark it as such to ensure that
16136             // we copy in child display lists into ours in drawChild()
16137             mRecreateDisplayList = true;
16138 
16139             int width = mRight - mLeft;
16140             int height = mBottom - mTop;
16141             int layerType = getLayerType();
16142 
16143             final DisplayListCanvas canvas = renderNode.start(width, height);
16144             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16145 
16146             try {
16147                 if (layerType == LAYER_TYPE_SOFTWARE) {
16148                     buildDrawingCache(true);
16149                     Bitmap cache = getDrawingCache(true);
16150                     if (cache != null) {
16151                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16152                     }
16153                 } else {
16154                     computeScroll();
16155 
16156                     canvas.translate(-mScrollX, -mScrollY);
16157                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16158                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16159 
16160                     // Fast path for layouts with no backgrounds
16161                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16162                         dispatchDraw(canvas);
16163                         if (mOverlay != null && !mOverlay.isEmpty()) {
16164                             mOverlay.getOverlayView().draw(canvas);
16165                         }
16166                     } else {
16167                         draw(canvas);
16168                     }
16169                 }
16170             } finally {
16171                 renderNode.end(canvas);
16172                 setDisplayListProperties(renderNode);
16173             }
16174         } else {
16175             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16176             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16177         }
16178         return renderNode;
16179     }
16180 
resetDisplayList()16181     private void resetDisplayList() {
16182         if (mRenderNode.isValid()) {
16183             mRenderNode.discardDisplayList();
16184         }
16185 
16186         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16187             mBackgroundRenderNode.discardDisplayList();
16188         }
16189     }
16190 
16191     /**
16192      * Called when the passed RenderNode is removed from the draw tree
16193      * @hide
16194      */
onRenderNodeDetached(RenderNode renderNode)16195     public void onRenderNodeDetached(RenderNode renderNode) {
16196     }
16197 
16198     /**
16199      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16200      *
16201      * @return A non-scaled bitmap representing this view or null if cache is disabled.
16202      *
16203      * @see #getDrawingCache(boolean)
16204      */
getDrawingCache()16205     public Bitmap getDrawingCache() {
16206         return getDrawingCache(false);
16207     }
16208 
16209     /**
16210      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16211      * is null when caching is disabled. If caching is enabled and the cache is not ready,
16212      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16213      * draw from the cache when the cache is enabled. To benefit from the cache, you must
16214      * request the drawing cache by calling this method and draw it on screen if the
16215      * returned bitmap is not null.</p>
16216      *
16217      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16218      * this method will create a bitmap of the same size as this view. Because this bitmap
16219      * will be drawn scaled by the parent ViewGroup, the result on screen might show
16220      * scaling artifacts. To avoid such artifacts, you should call this method by setting
16221      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16222      * size than the view. This implies that your application must be able to handle this
16223      * size.</p>
16224      *
16225      * @param autoScale Indicates whether the generated bitmap should be scaled based on
16226      *        the current density of the screen when the application is in compatibility
16227      *        mode.
16228      *
16229      * @return A bitmap representing this view or null if cache is disabled.
16230      *
16231      * @see #setDrawingCacheEnabled(boolean)
16232      * @see #isDrawingCacheEnabled()
16233      * @see #buildDrawingCache(boolean)
16234      * @see #destroyDrawingCache()
16235      */
getDrawingCache(boolean autoScale)16236     public Bitmap getDrawingCache(boolean autoScale) {
16237         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16238             return null;
16239         }
16240         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16241             buildDrawingCache(autoScale);
16242         }
16243         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16244     }
16245 
16246     /**
16247      * <p>Frees the resources used by the drawing cache. If you call
16248      * {@link #buildDrawingCache()} manually without calling
16249      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16250      * should cleanup the cache with this method afterwards.</p>
16251      *
16252      * @see #setDrawingCacheEnabled(boolean)
16253      * @see #buildDrawingCache()
16254      * @see #getDrawingCache()
16255      */
destroyDrawingCache()16256     public void destroyDrawingCache() {
16257         if (mDrawingCache != null) {
16258             mDrawingCache.recycle();
16259             mDrawingCache = null;
16260         }
16261         if (mUnscaledDrawingCache != null) {
16262             mUnscaledDrawingCache.recycle();
16263             mUnscaledDrawingCache = null;
16264         }
16265     }
16266 
16267     /**
16268      * Setting a solid background color for the drawing cache's bitmaps will improve
16269      * performance and memory usage. Note, though that this should only be used if this
16270      * view will always be drawn on top of a solid color.
16271      *
16272      * @param color The background color to use for the drawing cache's bitmap
16273      *
16274      * @see #setDrawingCacheEnabled(boolean)
16275      * @see #buildDrawingCache()
16276      * @see #getDrawingCache()
16277      */
setDrawingCacheBackgroundColor(@olorInt int color)16278     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16279         if (color != mDrawingCacheBackgroundColor) {
16280             mDrawingCacheBackgroundColor = color;
16281             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16282         }
16283     }
16284 
16285     /**
16286      * @see #setDrawingCacheBackgroundColor(int)
16287      *
16288      * @return The background color to used for the drawing cache's bitmap
16289      */
16290     @ColorInt
getDrawingCacheBackgroundColor()16291     public int getDrawingCacheBackgroundColor() {
16292         return mDrawingCacheBackgroundColor;
16293     }
16294 
16295     /**
16296      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16297      *
16298      * @see #buildDrawingCache(boolean)
16299      */
buildDrawingCache()16300     public void buildDrawingCache() {
16301         buildDrawingCache(false);
16302     }
16303 
16304     /**
16305      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16306      *
16307      * <p>If you call {@link #buildDrawingCache()} manually without calling
16308      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16309      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16310      *
16311      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16312      * this method will create a bitmap of the same size as this view. Because this bitmap
16313      * will be drawn scaled by the parent ViewGroup, the result on screen might show
16314      * scaling artifacts. To avoid such artifacts, you should call this method by setting
16315      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16316      * size than the view. This implies that your application must be able to handle this
16317      * size.</p>
16318      *
16319      * <p>You should avoid calling this method when hardware acceleration is enabled. If
16320      * you do not need the drawing cache bitmap, calling this method will increase memory
16321      * usage and cause the view to be rendered in software once, thus negatively impacting
16322      * performance.</p>
16323      *
16324      * @see #getDrawingCache()
16325      * @see #destroyDrawingCache()
16326      */
buildDrawingCache(boolean autoScale)16327     public void buildDrawingCache(boolean autoScale) {
16328         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16329                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
16330             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16331                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16332                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16333             }
16334             try {
16335                 buildDrawingCacheImpl(autoScale);
16336             } finally {
16337                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16338             }
16339         }
16340     }
16341 
16342     /**
16343      * private, internal implementation of buildDrawingCache, used to enable tracing
16344      */
buildDrawingCacheImpl(boolean autoScale)16345     private void buildDrawingCacheImpl(boolean autoScale) {
16346         mCachingFailed = false;
16347 
16348         int width = mRight - mLeft;
16349         int height = mBottom - mTop;
16350 
16351         final AttachInfo attachInfo = mAttachInfo;
16352         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16353 
16354         if (autoScale && scalingRequired) {
16355             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16356             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16357         }
16358 
16359         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16360         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16361         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16362 
16363         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16364         final long drawingCacheSize =
16365                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16366         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16367             if (width > 0 && height > 0) {
16368                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16369                         + " too large to fit into a software layer (or drawing cache), needs "
16370                         + projectedBitmapSize + " bytes, only "
16371                         + drawingCacheSize + " available");
16372             }
16373             destroyDrawingCache();
16374             mCachingFailed = true;
16375             return;
16376         }
16377 
16378         boolean clear = true;
16379         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16380 
16381         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16382             Bitmap.Config quality;
16383             if (!opaque) {
16384                 // Never pick ARGB_4444 because it looks awful
16385                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16386                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16387                     case DRAWING_CACHE_QUALITY_AUTO:
16388                     case DRAWING_CACHE_QUALITY_LOW:
16389                     case DRAWING_CACHE_QUALITY_HIGH:
16390                     default:
16391                         quality = Bitmap.Config.ARGB_8888;
16392                         break;
16393                 }
16394             } else {
16395                 // Optimization for translucent windows
16396                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16397                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16398             }
16399 
16400             // Try to cleanup memory
16401             if (bitmap != null) bitmap.recycle();
16402 
16403             try {
16404                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16405                         width, height, quality);
16406                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16407                 if (autoScale) {
16408                     mDrawingCache = bitmap;
16409                 } else {
16410                     mUnscaledDrawingCache = bitmap;
16411                 }
16412                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16413             } catch (OutOfMemoryError e) {
16414                 // If there is not enough memory to create the bitmap cache, just
16415                 // ignore the issue as bitmap caches are not required to draw the
16416                 // view hierarchy
16417                 if (autoScale) {
16418                     mDrawingCache = null;
16419                 } else {
16420                     mUnscaledDrawingCache = null;
16421                 }
16422                 mCachingFailed = true;
16423                 return;
16424             }
16425 
16426             clear = drawingCacheBackgroundColor != 0;
16427         }
16428 
16429         Canvas canvas;
16430         if (attachInfo != null) {
16431             canvas = attachInfo.mCanvas;
16432             if (canvas == null) {
16433                 canvas = new Canvas();
16434             }
16435             canvas.setBitmap(bitmap);
16436             // Temporarily clobber the cached Canvas in case one of our children
16437             // is also using a drawing cache. Without this, the children would
16438             // steal the canvas by attaching their own bitmap to it and bad, bad
16439             // thing would happen (invisible views, corrupted drawings, etc.)
16440             attachInfo.mCanvas = null;
16441         } else {
16442             // This case should hopefully never or seldom happen
16443             canvas = new Canvas(bitmap);
16444         }
16445 
16446         if (clear) {
16447             bitmap.eraseColor(drawingCacheBackgroundColor);
16448         }
16449 
16450         computeScroll();
16451         final int restoreCount = canvas.save();
16452 
16453         if (autoScale && scalingRequired) {
16454             final float scale = attachInfo.mApplicationScale;
16455             canvas.scale(scale, scale);
16456         }
16457 
16458         canvas.translate(-mScrollX, -mScrollY);
16459 
16460         mPrivateFlags |= PFLAG_DRAWN;
16461         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16462                 mLayerType != LAYER_TYPE_NONE) {
16463             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16464         }
16465 
16466         // Fast path for layouts with no backgrounds
16467         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16468             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16469             dispatchDraw(canvas);
16470             if (mOverlay != null && !mOverlay.isEmpty()) {
16471                 mOverlay.getOverlayView().draw(canvas);
16472             }
16473         } else {
16474             draw(canvas);
16475         }
16476 
16477         canvas.restoreToCount(restoreCount);
16478         canvas.setBitmap(null);
16479 
16480         if (attachInfo != null) {
16481             // Restore the cached Canvas for our siblings
16482             attachInfo.mCanvas = canvas;
16483         }
16484     }
16485 
16486     /**
16487      * Create a snapshot of the view into a bitmap.  We should probably make
16488      * some form of this public, but should think about the API.
16489      *
16490      * @hide
16491      */
createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren)16492     public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16493         int width = mRight - mLeft;
16494         int height = mBottom - mTop;
16495 
16496         final AttachInfo attachInfo = mAttachInfo;
16497         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16498         width = (int) ((width * scale) + 0.5f);
16499         height = (int) ((height * scale) + 0.5f);
16500 
16501         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16502                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
16503         if (bitmap == null) {
16504             throw new OutOfMemoryError();
16505         }
16506 
16507         Resources resources = getResources();
16508         if (resources != null) {
16509             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16510         }
16511 
16512         Canvas canvas;
16513         if (attachInfo != null) {
16514             canvas = attachInfo.mCanvas;
16515             if (canvas == null) {
16516                 canvas = new Canvas();
16517             }
16518             canvas.setBitmap(bitmap);
16519             // Temporarily clobber the cached Canvas in case one of our children
16520             // is also using a drawing cache. Without this, the children would
16521             // steal the canvas by attaching their own bitmap to it and bad, bad
16522             // things would happen (invisible views, corrupted drawings, etc.)
16523             attachInfo.mCanvas = null;
16524         } else {
16525             // This case should hopefully never or seldom happen
16526             canvas = new Canvas(bitmap);
16527         }
16528 
16529         if ((backgroundColor & 0xff000000) != 0) {
16530             bitmap.eraseColor(backgroundColor);
16531         }
16532 
16533         computeScroll();
16534         final int restoreCount = canvas.save();
16535         canvas.scale(scale, scale);
16536         canvas.translate(-mScrollX, -mScrollY);
16537 
16538         // Temporarily remove the dirty mask
16539         int flags = mPrivateFlags;
16540         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16541 
16542         // Fast path for layouts with no backgrounds
16543         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16544             dispatchDraw(canvas);
16545             if (mOverlay != null && !mOverlay.isEmpty()) {
16546                 mOverlay.getOverlayView().draw(canvas);
16547             }
16548         } else {
16549             draw(canvas);
16550         }
16551 
16552         mPrivateFlags = flags;
16553 
16554         canvas.restoreToCount(restoreCount);
16555         canvas.setBitmap(null);
16556 
16557         if (attachInfo != null) {
16558             // Restore the cached Canvas for our siblings
16559             attachInfo.mCanvas = canvas;
16560         }
16561 
16562         return bitmap;
16563     }
16564 
16565     /**
16566      * Indicates whether this View is currently in edit mode. A View is usually
16567      * in edit mode when displayed within a developer tool. For instance, if
16568      * this View is being drawn by a visual user interface builder, this method
16569      * should return true.
16570      *
16571      * Subclasses should check the return value of this method to provide
16572      * different behaviors if their normal behavior might interfere with the
16573      * host environment. For instance: the class spawns a thread in its
16574      * constructor, the drawing code relies on device-specific features, etc.
16575      *
16576      * This method is usually checked in the drawing code of custom widgets.
16577      *
16578      * @return True if this View is in edit mode, false otherwise.
16579      */
isInEditMode()16580     public boolean isInEditMode() {
16581         return false;
16582     }
16583 
16584     /**
16585      * If the View draws content inside its padding and enables fading edges,
16586      * it needs to support padding offsets. Padding offsets are added to the
16587      * fading edges to extend the length of the fade so that it covers pixels
16588      * drawn inside the padding.
16589      *
16590      * Subclasses of this class should override this method if they need
16591      * to draw content inside the padding.
16592      *
16593      * @return True if padding offset must be applied, false otherwise.
16594      *
16595      * @see #getLeftPaddingOffset()
16596      * @see #getRightPaddingOffset()
16597      * @see #getTopPaddingOffset()
16598      * @see #getBottomPaddingOffset()
16599      *
16600      * @since CURRENT
16601      */
isPaddingOffsetRequired()16602     protected boolean isPaddingOffsetRequired() {
16603         return false;
16604     }
16605 
16606     /**
16607      * Amount by which to extend the left fading region. Called only when
16608      * {@link #isPaddingOffsetRequired()} returns true.
16609      *
16610      * @return The left padding offset in pixels.
16611      *
16612      * @see #isPaddingOffsetRequired()
16613      *
16614      * @since CURRENT
16615      */
getLeftPaddingOffset()16616     protected int getLeftPaddingOffset() {
16617         return 0;
16618     }
16619 
16620     /**
16621      * Amount by which to extend the right fading region. Called only when
16622      * {@link #isPaddingOffsetRequired()} returns true.
16623      *
16624      * @return The right padding offset in pixels.
16625      *
16626      * @see #isPaddingOffsetRequired()
16627      *
16628      * @since CURRENT
16629      */
getRightPaddingOffset()16630     protected int getRightPaddingOffset() {
16631         return 0;
16632     }
16633 
16634     /**
16635      * Amount by which to extend the top fading region. Called only when
16636      * {@link #isPaddingOffsetRequired()} returns true.
16637      *
16638      * @return The top padding offset in pixels.
16639      *
16640      * @see #isPaddingOffsetRequired()
16641      *
16642      * @since CURRENT
16643      */
getTopPaddingOffset()16644     protected int getTopPaddingOffset() {
16645         return 0;
16646     }
16647 
16648     /**
16649      * Amount by which to extend the bottom fading region. Called only when
16650      * {@link #isPaddingOffsetRequired()} returns true.
16651      *
16652      * @return The bottom padding offset in pixels.
16653      *
16654      * @see #isPaddingOffsetRequired()
16655      *
16656      * @since CURRENT
16657      */
getBottomPaddingOffset()16658     protected int getBottomPaddingOffset() {
16659         return 0;
16660     }
16661 
16662     /**
16663      * @hide
16664      * @param offsetRequired
16665      */
getFadeTop(boolean offsetRequired)16666     protected int getFadeTop(boolean offsetRequired) {
16667         int top = mPaddingTop;
16668         if (offsetRequired) top += getTopPaddingOffset();
16669         return top;
16670     }
16671 
16672     /**
16673      * @hide
16674      * @param offsetRequired
16675      */
getFadeHeight(boolean offsetRequired)16676     protected int getFadeHeight(boolean offsetRequired) {
16677         int padding = mPaddingTop;
16678         if (offsetRequired) padding += getTopPaddingOffset();
16679         return mBottom - mTop - mPaddingBottom - padding;
16680     }
16681 
16682     /**
16683      * <p>Indicates whether this view is attached to a hardware accelerated
16684      * window or not.</p>
16685      *
16686      * <p>Even if this method returns true, it does not mean that every call
16687      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16688      * accelerated {@link android.graphics.Canvas}. For instance, if this view
16689      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16690      * window is hardware accelerated,
16691      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16692      * return false, and this method will return true.</p>
16693      *
16694      * @return True if the view is attached to a window and the window is
16695      *         hardware accelerated; false in any other case.
16696      */
16697     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()16698     public boolean isHardwareAccelerated() {
16699         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16700     }
16701 
16702     /**
16703      * Sets a rectangular area on this view to which the view will be clipped
16704      * when it is drawn. Setting the value to null will remove the clip bounds
16705      * and the view will draw normally, using its full bounds.
16706      *
16707      * @param clipBounds The rectangular area, in the local coordinates of
16708      * this view, to which future drawing operations will be clipped.
16709      */
setClipBounds(Rect clipBounds)16710     public void setClipBounds(Rect clipBounds) {
16711         if (clipBounds == mClipBounds
16712                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16713             return;
16714         }
16715         if (clipBounds != null) {
16716             if (mClipBounds == null) {
16717                 mClipBounds = new Rect(clipBounds);
16718             } else {
16719                 mClipBounds.set(clipBounds);
16720             }
16721         } else {
16722             mClipBounds = null;
16723         }
16724         mRenderNode.setClipBounds(mClipBounds);
16725         invalidateViewProperty(false, false);
16726     }
16727 
16728     /**
16729      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16730      *
16731      * @return A copy of the current clip bounds if clip bounds are set,
16732      * otherwise null.
16733      */
getClipBounds()16734     public Rect getClipBounds() {
16735         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16736     }
16737 
16738 
16739     /**
16740      * Populates an output rectangle with the clip bounds of the view,
16741      * returning {@code true} if successful or {@code false} if the view's
16742      * clip bounds are {@code null}.
16743      *
16744      * @param outRect rectangle in which to place the clip bounds of the view
16745      * @return {@code true} if successful or {@code false} if the view's
16746      *         clip bounds are {@code null}
16747      */
getClipBounds(Rect outRect)16748     public boolean getClipBounds(Rect outRect) {
16749         if (mClipBounds != null) {
16750             outRect.set(mClipBounds);
16751             return true;
16752         }
16753         return false;
16754     }
16755 
16756     /**
16757      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16758      * case of an active Animation being run on the view.
16759      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)16760     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16761             Animation a, boolean scalingRequired) {
16762         Transformation invalidationTransform;
16763         final int flags = parent.mGroupFlags;
16764         final boolean initialized = a.isInitialized();
16765         if (!initialized) {
16766             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16767             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16768             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16769             onAnimationStart();
16770         }
16771 
16772         final Transformation t = parent.getChildTransformation();
16773         boolean more = a.getTransformation(drawingTime, t, 1f);
16774         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16775             if (parent.mInvalidationTransformation == null) {
16776                 parent.mInvalidationTransformation = new Transformation();
16777             }
16778             invalidationTransform = parent.mInvalidationTransformation;
16779             a.getTransformation(drawingTime, invalidationTransform, 1f);
16780         } else {
16781             invalidationTransform = t;
16782         }
16783 
16784         if (more) {
16785             if (!a.willChangeBounds()) {
16786                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16787                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16788                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16789                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16790                     // The child need to draw an animation, potentially offscreen, so
16791                     // make sure we do not cancel invalidate requests
16792                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16793                     parent.invalidate(mLeft, mTop, mRight, mBottom);
16794                 }
16795             } else {
16796                 if (parent.mInvalidateRegion == null) {
16797                     parent.mInvalidateRegion = new RectF();
16798                 }
16799                 final RectF region = parent.mInvalidateRegion;
16800                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16801                         invalidationTransform);
16802 
16803                 // The child need to draw an animation, potentially offscreen, so
16804                 // make sure we do not cancel invalidate requests
16805                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16806 
16807                 final int left = mLeft + (int) region.left;
16808                 final int top = mTop + (int) region.top;
16809                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
16810                         top + (int) (region.height() + .5f));
16811             }
16812         }
16813         return more;
16814     }
16815 
16816     /**
16817      * This method is called by getDisplayList() when a display list is recorded for a View.
16818      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16819      */
setDisplayListProperties(RenderNode renderNode)16820     void setDisplayListProperties(RenderNode renderNode) {
16821         if (renderNode != null) {
16822             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16823             renderNode.setClipToBounds(mParent instanceof ViewGroup
16824                     && ((ViewGroup) mParent).getClipChildren());
16825 
16826             float alpha = 1;
16827             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16828                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16829                 ViewGroup parentVG = (ViewGroup) mParent;
16830                 final Transformation t = parentVG.getChildTransformation();
16831                 if (parentVG.getChildStaticTransformation(this, t)) {
16832                     final int transformType = t.getTransformationType();
16833                     if (transformType != Transformation.TYPE_IDENTITY) {
16834                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16835                             alpha = t.getAlpha();
16836                         }
16837                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16838                             renderNode.setStaticMatrix(t.getMatrix());
16839                         }
16840                     }
16841                 }
16842             }
16843             if (mTransformationInfo != null) {
16844                 alpha *= getFinalAlpha();
16845                 if (alpha < 1) {
16846                     final int multipliedAlpha = (int) (255 * alpha);
16847                     if (onSetAlpha(multipliedAlpha)) {
16848                         alpha = 1;
16849                     }
16850                 }
16851                 renderNode.setAlpha(alpha);
16852             } else if (alpha < 1) {
16853                 renderNode.setAlpha(alpha);
16854             }
16855         }
16856     }
16857 
16858     /**
16859      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16860      *
16861      * This is where the View specializes rendering behavior based on layer type,
16862      * and hardware acceleration.
16863      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)16864     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16865         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16866         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16867          *
16868          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16869          * HW accelerated, it can't handle drawing RenderNodes.
16870          */
16871         boolean drawingWithRenderNode = mAttachInfo != null
16872                 && mAttachInfo.mHardwareAccelerated
16873                 && hardwareAcceleratedCanvas;
16874 
16875         boolean more = false;
16876         final boolean childHasIdentityMatrix = hasIdentityMatrix();
16877         final int parentFlags = parent.mGroupFlags;
16878 
16879         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16880             parent.getChildTransformation().clear();
16881             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16882         }
16883 
16884         Transformation transformToApply = null;
16885         boolean concatMatrix = false;
16886         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16887         final Animation a = getAnimation();
16888         if (a != null) {
16889             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16890             concatMatrix = a.willChangeTransformationMatrix();
16891             if (concatMatrix) {
16892                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16893             }
16894             transformToApply = parent.getChildTransformation();
16895         } else {
16896             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16897                 // No longer animating: clear out old animation matrix
16898                 mRenderNode.setAnimationMatrix(null);
16899                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16900             }
16901             if (!drawingWithRenderNode
16902                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16903                 final Transformation t = parent.getChildTransformation();
16904                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16905                 if (hasTransform) {
16906                     final int transformType = t.getTransformationType();
16907                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16908                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16909                 }
16910             }
16911         }
16912 
16913         concatMatrix |= !childHasIdentityMatrix;
16914 
16915         // Sets the flag as early as possible to allow draw() implementations
16916         // to call invalidate() successfully when doing animations
16917         mPrivateFlags |= PFLAG_DRAWN;
16918 
16919         if (!concatMatrix &&
16920                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16921                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16922                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16923                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16924             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16925             return more;
16926         }
16927         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16928 
16929         if (hardwareAcceleratedCanvas) {
16930             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16931             // retain the flag's value temporarily in the mRecreateDisplayList flag
16932             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16933             mPrivateFlags &= ~PFLAG_INVALIDATED;
16934         }
16935 
16936         RenderNode renderNode = null;
16937         Bitmap cache = null;
16938         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16939         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16940              if (layerType != LAYER_TYPE_NONE) {
16941                  // If not drawing with RenderNode, treat HW layers as SW
16942                  layerType = LAYER_TYPE_SOFTWARE;
16943                  buildDrawingCache(true);
16944             }
16945             cache = getDrawingCache(true);
16946         }
16947 
16948         if (drawingWithRenderNode) {
16949             // Delay getting the display list until animation-driven alpha values are
16950             // set up and possibly passed on to the view
16951             renderNode = updateDisplayListIfDirty();
16952             if (!renderNode.isValid()) {
16953                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
16954                 // to getDisplayList(), the display list will be marked invalid and we should not
16955                 // try to use it again.
16956                 renderNode = null;
16957                 drawingWithRenderNode = false;
16958             }
16959         }
16960 
16961         int sx = 0;
16962         int sy = 0;
16963         if (!drawingWithRenderNode) {
16964             computeScroll();
16965             sx = mScrollX;
16966             sy = mScrollY;
16967         }
16968 
16969         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16970         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16971 
16972         int restoreTo = -1;
16973         if (!drawingWithRenderNode || transformToApply != null) {
16974             restoreTo = canvas.save();
16975         }
16976         if (offsetForScroll) {
16977             canvas.translate(mLeft - sx, mTop - sy);
16978         } else {
16979             if (!drawingWithRenderNode) {
16980                 canvas.translate(mLeft, mTop);
16981             }
16982             if (scalingRequired) {
16983                 if (drawingWithRenderNode) {
16984                     // TODO: Might not need this if we put everything inside the DL
16985                     restoreTo = canvas.save();
16986                 }
16987                 // mAttachInfo cannot be null, otherwise scalingRequired == false
16988                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
16989                 canvas.scale(scale, scale);
16990             }
16991         }
16992 
16993         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16994         if (transformToApply != null
16995                 || alpha < 1
16996                 || !hasIdentityMatrix()
16997                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16998             if (transformToApply != null || !childHasIdentityMatrix) {
16999                 int transX = 0;
17000                 int transY = 0;
17001 
17002                 if (offsetForScroll) {
17003                     transX = -sx;
17004                     transY = -sy;
17005                 }
17006 
17007                 if (transformToApply != null) {
17008                     if (concatMatrix) {
17009                         if (drawingWithRenderNode) {
17010                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
17011                         } else {
17012                             // Undo the scroll translation, apply the transformation matrix,
17013                             // then redo the scroll translate to get the correct result.
17014                             canvas.translate(-transX, -transY);
17015                             canvas.concat(transformToApply.getMatrix());
17016                             canvas.translate(transX, transY);
17017                         }
17018                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17019                     }
17020 
17021                     float transformAlpha = transformToApply.getAlpha();
17022                     if (transformAlpha < 1) {
17023                         alpha *= transformAlpha;
17024                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17025                     }
17026                 }
17027 
17028                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17029                     canvas.translate(-transX, -transY);
17030                     canvas.concat(getMatrix());
17031                     canvas.translate(transX, transY);
17032                 }
17033             }
17034 
17035             // Deal with alpha if it is or used to be <1
17036             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17037                 if (alpha < 1) {
17038                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17039                 } else {
17040                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17041                 }
17042                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17043                 if (!drawingWithDrawingCache) {
17044                     final int multipliedAlpha = (int) (255 * alpha);
17045                     if (!onSetAlpha(multipliedAlpha)) {
17046                         if (drawingWithRenderNode) {
17047                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17048                         } else if (layerType == LAYER_TYPE_NONE) {
17049                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17050                                     multipliedAlpha);
17051                         }
17052                     } else {
17053                         // Alpha is handled by the child directly, clobber the layer's alpha
17054                         mPrivateFlags |= PFLAG_ALPHA_SET;
17055                     }
17056                 }
17057             }
17058         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17059             onSetAlpha(255);
17060             mPrivateFlags &= ~PFLAG_ALPHA_SET;
17061         }
17062 
17063         if (!drawingWithRenderNode) {
17064             // apply clips directly, since RenderNode won't do it for this draw
17065             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17066                 if (offsetForScroll) {
17067                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17068                 } else {
17069                     if (!scalingRequired || cache == null) {
17070                         canvas.clipRect(0, 0, getWidth(), getHeight());
17071                     } else {
17072                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17073                     }
17074                 }
17075             }
17076 
17077             if (mClipBounds != null) {
17078                 // clip bounds ignore scroll
17079                 canvas.clipRect(mClipBounds);
17080             }
17081         }
17082 
17083         if (!drawingWithDrawingCache) {
17084             if (drawingWithRenderNode) {
17085                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17086                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17087             } else {
17088                 // Fast path for layouts with no backgrounds
17089                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17090                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17091                     dispatchDraw(canvas);
17092                 } else {
17093                     draw(canvas);
17094                 }
17095             }
17096         } else if (cache != null) {
17097             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17098             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17099                 // no layer paint, use temporary paint to draw bitmap
17100                 Paint cachePaint = parent.mCachePaint;
17101                 if (cachePaint == null) {
17102                     cachePaint = new Paint();
17103                     cachePaint.setDither(false);
17104                     parent.mCachePaint = cachePaint;
17105                 }
17106                 cachePaint.setAlpha((int) (alpha * 255));
17107                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17108             } else {
17109                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
17110                 int layerPaintAlpha = mLayerPaint.getAlpha();
17111                 if (alpha < 1) {
17112                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17113                 }
17114                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17115                 if (alpha < 1) {
17116                     mLayerPaint.setAlpha(layerPaintAlpha);
17117                 }
17118             }
17119         }
17120 
17121         if (restoreTo >= 0) {
17122             canvas.restoreToCount(restoreTo);
17123         }
17124 
17125         if (a != null && !more) {
17126             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17127                 onSetAlpha(255);
17128             }
17129             parent.finishAnimatingView(this, a);
17130         }
17131 
17132         if (more && hardwareAcceleratedCanvas) {
17133             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17134                 // alpha animations should cause the child to recreate its display list
17135                 invalidate(true);
17136             }
17137         }
17138 
17139         mRecreateDisplayList = false;
17140 
17141         return more;
17142     }
17143 
17144     /**
17145      * Manually render this view (and all of its children) to the given Canvas.
17146      * The view must have already done a full layout before this function is
17147      * called.  When implementing a view, implement
17148      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17149      * If you do need to override this method, call the superclass version.
17150      *
17151      * @param canvas The Canvas to which the View is rendered.
17152      */
17153     @CallSuper
draw(Canvas canvas)17154     public void draw(Canvas canvas) {
17155         final int privateFlags = mPrivateFlags;
17156         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17157                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17158         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17159 
17160         /*
17161          * Draw traversal performs several drawing steps which must be executed
17162          * in the appropriate order:
17163          *
17164          *      1. Draw the background
17165          *      2. If necessary, save the canvas' layers to prepare for fading
17166          *      3. Draw view's content
17167          *      4. Draw children
17168          *      5. If necessary, draw the fading edges and restore layers
17169          *      6. Draw decorations (scrollbars for instance)
17170          */
17171 
17172         // Step 1, draw the background, if needed
17173         int saveCount;
17174 
17175         if (!dirtyOpaque) {
17176             drawBackground(canvas);
17177         }
17178 
17179         // skip step 2 & 5 if possible (common case)
17180         final int viewFlags = mViewFlags;
17181         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17182         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17183         if (!verticalEdges && !horizontalEdges) {
17184             // Step 3, draw the content
17185             if (!dirtyOpaque) onDraw(canvas);
17186 
17187             // Step 4, draw the children
17188             dispatchDraw(canvas);
17189 
17190             // Overlay is part of the content and draws beneath Foreground
17191             if (mOverlay != null && !mOverlay.isEmpty()) {
17192                 mOverlay.getOverlayView().dispatchDraw(canvas);
17193             }
17194 
17195             // Step 6, draw decorations (foreground, scrollbars)
17196             onDrawForeground(canvas);
17197 
17198             // we're done...
17199             return;
17200         }
17201 
17202         /*
17203          * Here we do the full fledged routine...
17204          * (this is an uncommon case where speed matters less,
17205          * this is why we repeat some of the tests that have been
17206          * done above)
17207          */
17208 
17209         boolean drawTop = false;
17210         boolean drawBottom = false;
17211         boolean drawLeft = false;
17212         boolean drawRight = false;
17213 
17214         float topFadeStrength = 0.0f;
17215         float bottomFadeStrength = 0.0f;
17216         float leftFadeStrength = 0.0f;
17217         float rightFadeStrength = 0.0f;
17218 
17219         // Step 2, save the canvas' layers
17220         int paddingLeft = mPaddingLeft;
17221 
17222         final boolean offsetRequired = isPaddingOffsetRequired();
17223         if (offsetRequired) {
17224             paddingLeft += getLeftPaddingOffset();
17225         }
17226 
17227         int left = mScrollX + paddingLeft;
17228         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17229         int top = mScrollY + getFadeTop(offsetRequired);
17230         int bottom = top + getFadeHeight(offsetRequired);
17231 
17232         if (offsetRequired) {
17233             right += getRightPaddingOffset();
17234             bottom += getBottomPaddingOffset();
17235         }
17236 
17237         final ScrollabilityCache scrollabilityCache = mScrollCache;
17238         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17239         int length = (int) fadeHeight;
17240 
17241         // clip the fade length if top and bottom fades overlap
17242         // overlapping fades produce odd-looking artifacts
17243         if (verticalEdges && (top + length > bottom - length)) {
17244             length = (bottom - top) / 2;
17245         }
17246 
17247         // also clip horizontal fades if necessary
17248         if (horizontalEdges && (left + length > right - length)) {
17249             length = (right - left) / 2;
17250         }
17251 
17252         if (verticalEdges) {
17253             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17254             drawTop = topFadeStrength * fadeHeight > 1.0f;
17255             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17256             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17257         }
17258 
17259         if (horizontalEdges) {
17260             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17261             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17262             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17263             drawRight = rightFadeStrength * fadeHeight > 1.0f;
17264         }
17265 
17266         saveCount = canvas.getSaveCount();
17267 
17268         int solidColor = getSolidColor();
17269         if (solidColor == 0) {
17270             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17271 
17272             if (drawTop) {
17273                 canvas.saveLayer(left, top, right, top + length, null, flags);
17274             }
17275 
17276             if (drawBottom) {
17277                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17278             }
17279 
17280             if (drawLeft) {
17281                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
17282             }
17283 
17284             if (drawRight) {
17285                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
17286             }
17287         } else {
17288             scrollabilityCache.setFadeColor(solidColor);
17289         }
17290 
17291         // Step 3, draw the content
17292         if (!dirtyOpaque) onDraw(canvas);
17293 
17294         // Step 4, draw the children
17295         dispatchDraw(canvas);
17296 
17297         // Step 5, draw the fade effect and restore layers
17298         final Paint p = scrollabilityCache.paint;
17299         final Matrix matrix = scrollabilityCache.matrix;
17300         final Shader fade = scrollabilityCache.shader;
17301 
17302         if (drawTop) {
17303             matrix.setScale(1, fadeHeight * topFadeStrength);
17304             matrix.postTranslate(left, top);
17305             fade.setLocalMatrix(matrix);
17306             p.setShader(fade);
17307             canvas.drawRect(left, top, right, top + length, p);
17308         }
17309 
17310         if (drawBottom) {
17311             matrix.setScale(1, fadeHeight * bottomFadeStrength);
17312             matrix.postRotate(180);
17313             matrix.postTranslate(left, bottom);
17314             fade.setLocalMatrix(matrix);
17315             p.setShader(fade);
17316             canvas.drawRect(left, bottom - length, right, bottom, p);
17317         }
17318 
17319         if (drawLeft) {
17320             matrix.setScale(1, fadeHeight * leftFadeStrength);
17321             matrix.postRotate(-90);
17322             matrix.postTranslate(left, top);
17323             fade.setLocalMatrix(matrix);
17324             p.setShader(fade);
17325             canvas.drawRect(left, top, left + length, bottom, p);
17326         }
17327 
17328         if (drawRight) {
17329             matrix.setScale(1, fadeHeight * rightFadeStrength);
17330             matrix.postRotate(90);
17331             matrix.postTranslate(right, top);
17332             fade.setLocalMatrix(matrix);
17333             p.setShader(fade);
17334             canvas.drawRect(right - length, top, right, bottom, p);
17335         }
17336 
17337         canvas.restoreToCount(saveCount);
17338 
17339         // Overlay is part of the content and draws beneath Foreground
17340         if (mOverlay != null && !mOverlay.isEmpty()) {
17341             mOverlay.getOverlayView().dispatchDraw(canvas);
17342         }
17343 
17344         // Step 6, draw decorations (foreground, scrollbars)
17345         onDrawForeground(canvas);
17346     }
17347 
17348     /**
17349      * Draws the background onto the specified canvas.
17350      *
17351      * @param canvas Canvas on which to draw the background
17352      */
drawBackground(Canvas canvas)17353     private void drawBackground(Canvas canvas) {
17354         final Drawable background = mBackground;
17355         if (background == null) {
17356             return;
17357         }
17358 
17359         setBackgroundBounds();
17360 
17361         // Attempt to use a display list if requested.
17362         if (canvas.isHardwareAccelerated() && mAttachInfo != null
17363                 && mAttachInfo.mHardwareRenderer != null) {
17364             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17365 
17366             final RenderNode renderNode = mBackgroundRenderNode;
17367             if (renderNode != null && renderNode.isValid()) {
17368                 setBackgroundRenderNodeProperties(renderNode);
17369                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17370                 return;
17371             }
17372         }
17373 
17374         final int scrollX = mScrollX;
17375         final int scrollY = mScrollY;
17376         if ((scrollX | scrollY) == 0) {
17377             background.draw(canvas);
17378         } else {
17379             canvas.translate(scrollX, scrollY);
17380             background.draw(canvas);
17381             canvas.translate(-scrollX, -scrollY);
17382         }
17383     }
17384 
17385     /**
17386      * Sets the correct background bounds and rebuilds the outline, if needed.
17387      * <p/>
17388      * This is called by LayoutLib.
17389      */
setBackgroundBounds()17390     void setBackgroundBounds() {
17391         if (mBackgroundSizeChanged && mBackground != null) {
17392             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17393             mBackgroundSizeChanged = false;
17394             rebuildOutline();
17395         }
17396     }
17397 
setBackgroundRenderNodeProperties(RenderNode renderNode)17398     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17399         renderNode.setTranslationX(mScrollX);
17400         renderNode.setTranslationY(mScrollY);
17401     }
17402 
17403     /**
17404      * Creates a new display list or updates the existing display list for the
17405      * specified Drawable.
17406      *
17407      * @param drawable Drawable for which to create a display list
17408      * @param renderNode Existing RenderNode, or {@code null}
17409      * @return A valid display list for the specified drawable
17410      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)17411     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17412         if (renderNode == null) {
17413             renderNode = RenderNode.create(drawable.getClass().getName(), this);
17414         }
17415 
17416         final Rect bounds = drawable.getBounds();
17417         final int width = bounds.width();
17418         final int height = bounds.height();
17419         final DisplayListCanvas canvas = renderNode.start(width, height);
17420 
17421         // Reverse left/top translation done by drawable canvas, which will
17422         // instead be applied by rendernode's LTRB bounds below. This way, the
17423         // drawable's bounds match with its rendernode bounds and its content
17424         // will lie within those bounds in the rendernode tree.
17425         canvas.translate(-bounds.left, -bounds.top);
17426 
17427         try {
17428             drawable.draw(canvas);
17429         } finally {
17430             renderNode.end(canvas);
17431         }
17432 
17433         // Set up drawable properties that are view-independent.
17434         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17435         renderNode.setProjectBackwards(drawable.isProjected());
17436         renderNode.setProjectionReceiver(true);
17437         renderNode.setClipToBounds(false);
17438         return renderNode;
17439     }
17440 
17441     /**
17442      * Returns the overlay for this view, creating it if it does not yet exist.
17443      * Adding drawables to the overlay will cause them to be displayed whenever
17444      * the view itself is redrawn. Objects in the overlay should be actively
17445      * managed: remove them when they should not be displayed anymore. The
17446      * overlay will always have the same size as its host view.
17447      *
17448      * <p>Note: Overlays do not currently work correctly with {@link
17449      * SurfaceView} or {@link TextureView}; contents in overlays for these
17450      * types of views may not display correctly.</p>
17451      *
17452      * @return The ViewOverlay object for this view.
17453      * @see ViewOverlay
17454      */
getOverlay()17455     public ViewOverlay getOverlay() {
17456         if (mOverlay == null) {
17457             mOverlay = new ViewOverlay(mContext, this);
17458         }
17459         return mOverlay;
17460     }
17461 
17462     /**
17463      * Override this if your view is known to always be drawn on top of a solid color background,
17464      * and needs to draw fading edges. Returning a non-zero color enables the view system to
17465      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17466      * should be set to 0xFF.
17467      *
17468      * @see #setVerticalFadingEdgeEnabled(boolean)
17469      * @see #setHorizontalFadingEdgeEnabled(boolean)
17470      *
17471      * @return The known solid color background for this view, or 0 if the color may vary
17472      */
17473     @ViewDebug.ExportedProperty(category = "drawing")
17474     @ColorInt
getSolidColor()17475     public int getSolidColor() {
17476         return 0;
17477     }
17478 
17479     /**
17480      * Build a human readable string representation of the specified view flags.
17481      *
17482      * @param flags the view flags to convert to a string
17483      * @return a String representing the supplied flags
17484      */
printFlags(int flags)17485     private static String printFlags(int flags) {
17486         String output = "";
17487         int numFlags = 0;
17488         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17489             output += "TAKES_FOCUS";
17490             numFlags++;
17491         }
17492 
17493         switch (flags & VISIBILITY_MASK) {
17494         case INVISIBLE:
17495             if (numFlags > 0) {
17496                 output += " ";
17497             }
17498             output += "INVISIBLE";
17499             // USELESS HERE numFlags++;
17500             break;
17501         case GONE:
17502             if (numFlags > 0) {
17503                 output += " ";
17504             }
17505             output += "GONE";
17506             // USELESS HERE numFlags++;
17507             break;
17508         default:
17509             break;
17510         }
17511         return output;
17512     }
17513 
17514     /**
17515      * Build a human readable string representation of the specified private
17516      * view flags.
17517      *
17518      * @param privateFlags the private view flags to convert to a string
17519      * @return a String representing the supplied flags
17520      */
printPrivateFlags(int privateFlags)17521     private static String printPrivateFlags(int privateFlags) {
17522         String output = "";
17523         int numFlags = 0;
17524 
17525         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17526             output += "WANTS_FOCUS";
17527             numFlags++;
17528         }
17529 
17530         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17531             if (numFlags > 0) {
17532                 output += " ";
17533             }
17534             output += "FOCUSED";
17535             numFlags++;
17536         }
17537 
17538         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17539             if (numFlags > 0) {
17540                 output += " ";
17541             }
17542             output += "SELECTED";
17543             numFlags++;
17544         }
17545 
17546         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17547             if (numFlags > 0) {
17548                 output += " ";
17549             }
17550             output += "IS_ROOT_NAMESPACE";
17551             numFlags++;
17552         }
17553 
17554         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17555             if (numFlags > 0) {
17556                 output += " ";
17557             }
17558             output += "HAS_BOUNDS";
17559             numFlags++;
17560         }
17561 
17562         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17563             if (numFlags > 0) {
17564                 output += " ";
17565             }
17566             output += "DRAWN";
17567             // USELESS HERE numFlags++;
17568         }
17569         return output;
17570     }
17571 
17572     /**
17573      * <p>Indicates whether or not this view's layout will be requested during
17574      * the next hierarchy layout pass.</p>
17575      *
17576      * @return true if the layout will be forced during next layout pass
17577      */
isLayoutRequested()17578     public boolean isLayoutRequested() {
17579         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17580     }
17581 
17582     /**
17583      * Return true if o is a ViewGroup that is laying out using optical bounds.
17584      * @hide
17585      */
isLayoutModeOptical(Object o)17586     public static boolean isLayoutModeOptical(Object o) {
17587         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17588     }
17589 
setOpticalFrame(int left, int top, int right, int bottom)17590     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17591         Insets parentInsets = mParent instanceof View ?
17592                 ((View) mParent).getOpticalInsets() : Insets.NONE;
17593         Insets childInsets = getOpticalInsets();
17594         return setFrame(
17595                 left   + parentInsets.left - childInsets.left,
17596                 top    + parentInsets.top  - childInsets.top,
17597                 right  + parentInsets.left + childInsets.right,
17598                 bottom + parentInsets.top  + childInsets.bottom);
17599     }
17600 
17601     /**
17602      * Assign a size and position to a view and all of its
17603      * descendants
17604      *
17605      * <p>This is the second phase of the layout mechanism.
17606      * (The first is measuring). In this phase, each parent calls
17607      * layout on all of its children to position them.
17608      * This is typically done using the child measurements
17609      * that were stored in the measure pass().</p>
17610      *
17611      * <p>Derived classes should not override this method.
17612      * Derived classes with children should override
17613      * onLayout. In that method, they should
17614      * call layout on each of their children.</p>
17615      *
17616      * @param l Left position, relative to parent
17617      * @param t Top position, relative to parent
17618      * @param r Right position, relative to parent
17619      * @param b Bottom position, relative to parent
17620      */
17621     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)17622     public void layout(int l, int t, int r, int b) {
17623         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17624             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17625             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17626         }
17627 
17628         int oldL = mLeft;
17629         int oldT = mTop;
17630         int oldB = mBottom;
17631         int oldR = mRight;
17632 
17633         boolean changed = isLayoutModeOptical(mParent) ?
17634                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17635 
17636         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17637             onLayout(changed, l, t, r, b);
17638 
17639             if (shouldDrawRoundScrollbar()) {
17640                 if(mRoundScrollbarRenderer == null) {
17641                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
17642                 }
17643             } else {
17644                 mRoundScrollbarRenderer = null;
17645             }
17646 
17647             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17648 
17649             ListenerInfo li = mListenerInfo;
17650             if (li != null && li.mOnLayoutChangeListeners != null) {
17651                 ArrayList<OnLayoutChangeListener> listenersCopy =
17652                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17653                 int numListeners = listenersCopy.size();
17654                 for (int i = 0; i < numListeners; ++i) {
17655                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17656                 }
17657             }
17658         }
17659 
17660         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17661         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17662     }
17663 
17664     /**
17665      * Called from layout when this view should
17666      * assign a size and position to each of its children.
17667      *
17668      * Derived classes with children should override
17669      * this method and call layout on each of
17670      * their children.
17671      * @param changed This is a new size or position for this view
17672      * @param left Left position, relative to parent
17673      * @param top Top position, relative to parent
17674      * @param right Right position, relative to parent
17675      * @param bottom Bottom position, relative to parent
17676      */
onLayout(boolean changed, int left, int top, int right, int bottom)17677     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17678     }
17679 
17680     /**
17681      * Assign a size and position to this view.
17682      *
17683      * This is called from layout.
17684      *
17685      * @param left Left position, relative to parent
17686      * @param top Top position, relative to parent
17687      * @param right Right position, relative to parent
17688      * @param bottom Bottom position, relative to parent
17689      * @return true if the new size and position are different than the
17690      *         previous ones
17691      * {@hide}
17692      */
setFrame(int left, int top, int right, int bottom)17693     protected boolean setFrame(int left, int top, int right, int bottom) {
17694         boolean changed = false;
17695 
17696         if (DBG) {
17697             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17698                     + right + "," + bottom + ")");
17699         }
17700 
17701         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17702             changed = true;
17703 
17704             // Remember our drawn bit
17705             int drawn = mPrivateFlags & PFLAG_DRAWN;
17706 
17707             int oldWidth = mRight - mLeft;
17708             int oldHeight = mBottom - mTop;
17709             int newWidth = right - left;
17710             int newHeight = bottom - top;
17711             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17712 
17713             // Invalidate our old position
17714             invalidate(sizeChanged);
17715 
17716             mLeft = left;
17717             mTop = top;
17718             mRight = right;
17719             mBottom = bottom;
17720             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17721 
17722             mPrivateFlags |= PFLAG_HAS_BOUNDS;
17723 
17724 
17725             if (sizeChanged) {
17726                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17727             }
17728 
17729             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17730                 // If we are visible, force the DRAWN bit to on so that
17731                 // this invalidate will go through (at least to our parent).
17732                 // This is because someone may have invalidated this view
17733                 // before this call to setFrame came in, thereby clearing
17734                 // the DRAWN bit.
17735                 mPrivateFlags |= PFLAG_DRAWN;
17736                 invalidate(sizeChanged);
17737                 // parent display list may need to be recreated based on a change in the bounds
17738                 // of any child
17739                 invalidateParentCaches();
17740             }
17741 
17742             // Reset drawn bit to original value (invalidate turns it off)
17743             mPrivateFlags |= drawn;
17744 
17745             mBackgroundSizeChanged = true;
17746             if (mForegroundInfo != null) {
17747                 mForegroundInfo.mBoundsChanged = true;
17748             }
17749 
17750             notifySubtreeAccessibilityStateChangedIfNeeded();
17751         }
17752         return changed;
17753     }
17754 
17755     /**
17756      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17757      * @hide
17758      */
setLeftTopRightBottom(int left, int top, int right, int bottom)17759     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17760         setFrame(left, top, right, bottom);
17761     }
17762 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)17763     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17764         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17765         if (mOverlay != null) {
17766             mOverlay.getOverlayView().setRight(newWidth);
17767             mOverlay.getOverlayView().setBottom(newHeight);
17768         }
17769         rebuildOutline();
17770     }
17771 
17772     /**
17773      * Finalize inflating a view from XML.  This is called as the last phase
17774      * of inflation, after all child views have been added.
17775      *
17776      * <p>Even if the subclass overrides onFinishInflate, they should always be
17777      * sure to call the super method, so that we get called.
17778      */
17779     @CallSuper
onFinishInflate()17780     protected void onFinishInflate() {
17781     }
17782 
17783     /**
17784      * Returns the resources associated with this view.
17785      *
17786      * @return Resources object.
17787      */
getResources()17788     public Resources getResources() {
17789         return mResources;
17790     }
17791 
17792     /**
17793      * Invalidates the specified Drawable.
17794      *
17795      * @param drawable the drawable to invalidate
17796      */
17797     @Override
invalidateDrawable(@onNull Drawable drawable)17798     public void invalidateDrawable(@NonNull Drawable drawable) {
17799         if (verifyDrawable(drawable)) {
17800             final Rect dirty = drawable.getDirtyBounds();
17801             final int scrollX = mScrollX;
17802             final int scrollY = mScrollY;
17803 
17804             invalidate(dirty.left + scrollX, dirty.top + scrollY,
17805                     dirty.right + scrollX, dirty.bottom + scrollY);
17806             rebuildOutline();
17807         }
17808     }
17809 
17810     /**
17811      * Schedules an action on a drawable to occur at a specified time.
17812      *
17813      * @param who the recipient of the action
17814      * @param what the action to run on the drawable
17815      * @param when the time at which the action must occur. Uses the
17816      *        {@link SystemClock#uptimeMillis} timebase.
17817      */
17818     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)17819     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17820         if (verifyDrawable(who) && what != null) {
17821             final long delay = when - SystemClock.uptimeMillis();
17822             if (mAttachInfo != null) {
17823                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17824                         Choreographer.CALLBACK_ANIMATION, what, who,
17825                         Choreographer.subtractFrameDelay(delay));
17826             } else {
17827                 // Postpone the runnable until we know
17828                 // on which thread it needs to run.
17829                 getRunQueue().postDelayed(what, delay);
17830             }
17831         }
17832     }
17833 
17834     /**
17835      * Cancels a scheduled action on a drawable.
17836      *
17837      * @param who the recipient of the action
17838      * @param what the action to cancel
17839      */
17840     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)17841     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17842         if (verifyDrawable(who) && what != null) {
17843             if (mAttachInfo != null) {
17844                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17845                         Choreographer.CALLBACK_ANIMATION, what, who);
17846             }
17847             getRunQueue().removeCallbacks(what);
17848         }
17849     }
17850 
17851     /**
17852      * Unschedule any events associated with the given Drawable.  This can be
17853      * used when selecting a new Drawable into a view, so that the previous
17854      * one is completely unscheduled.
17855      *
17856      * @param who The Drawable to unschedule.
17857      *
17858      * @see #drawableStateChanged
17859      */
unscheduleDrawable(Drawable who)17860     public void unscheduleDrawable(Drawable who) {
17861         if (mAttachInfo != null && who != null) {
17862             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17863                     Choreographer.CALLBACK_ANIMATION, null, who);
17864         }
17865     }
17866 
17867     /**
17868      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17869      * that the View directionality can and will be resolved before its Drawables.
17870      *
17871      * Will call {@link View#onResolveDrawables} when resolution is done.
17872      *
17873      * @hide
17874      */
resolveDrawables()17875     protected void resolveDrawables() {
17876         // Drawables resolution may need to happen before resolving the layout direction (which is
17877         // done only during the measure() call).
17878         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17879         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17880         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17881         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17882         // direction to be resolved as its resolved value will be the same as its raw value.
17883         if (!isLayoutDirectionResolved() &&
17884                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17885             return;
17886         }
17887 
17888         final int layoutDirection = isLayoutDirectionResolved() ?
17889                 getLayoutDirection() : getRawLayoutDirection();
17890 
17891         if (mBackground != null) {
17892             mBackground.setLayoutDirection(layoutDirection);
17893         }
17894         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17895             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17896         }
17897         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17898         onResolveDrawables(layoutDirection);
17899     }
17900 
areDrawablesResolved()17901     boolean areDrawablesResolved() {
17902         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17903     }
17904 
17905     /**
17906      * Called when layout direction has been resolved.
17907      *
17908      * The default implementation does nothing.
17909      *
17910      * @param layoutDirection The resolved layout direction.
17911      *
17912      * @see #LAYOUT_DIRECTION_LTR
17913      * @see #LAYOUT_DIRECTION_RTL
17914      *
17915      * @hide
17916      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)17917     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17918     }
17919 
17920     /**
17921      * @hide
17922      */
resetResolvedDrawables()17923     protected void resetResolvedDrawables() {
17924         resetResolvedDrawablesInternal();
17925     }
17926 
resetResolvedDrawablesInternal()17927     void resetResolvedDrawablesInternal() {
17928         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17929     }
17930 
17931     /**
17932      * If your view subclass is displaying its own Drawable objects, it should
17933      * override this function and return true for any Drawable it is
17934      * displaying.  This allows animations for those drawables to be
17935      * scheduled.
17936      *
17937      * <p>Be sure to call through to the super class when overriding this
17938      * function.
17939      *
17940      * @param who The Drawable to verify.  Return true if it is one you are
17941      *            displaying, else return the result of calling through to the
17942      *            super class.
17943      *
17944      * @return boolean If true than the Drawable is being displayed in the
17945      *         view; else false and it is not allowed to animate.
17946      *
17947      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17948      * @see #drawableStateChanged()
17949      */
17950     @CallSuper
verifyDrawable(@onNull Drawable who)17951     protected boolean verifyDrawable(@NonNull Drawable who) {
17952         // Avoid verifying the scroll bar drawable so that we don't end up in
17953         // an invalidation loop. This effectively prevents the scroll bar
17954         // drawable from triggering invalidations and scheduling runnables.
17955         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17956     }
17957 
17958     /**
17959      * This function is called whenever the state of the view changes in such
17960      * a way that it impacts the state of drawables being shown.
17961      * <p>
17962      * If the View has a StateListAnimator, it will also be called to run necessary state
17963      * change animations.
17964      * <p>
17965      * Be sure to call through to the superclass when overriding this function.
17966      *
17967      * @see Drawable#setState(int[])
17968      */
17969     @CallSuper
drawableStateChanged()17970     protected void drawableStateChanged() {
17971         final int[] state = getDrawableState();
17972         boolean changed = false;
17973 
17974         final Drawable bg = mBackground;
17975         if (bg != null && bg.isStateful()) {
17976             changed |= bg.setState(state);
17977         }
17978 
17979         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17980         if (fg != null && fg.isStateful()) {
17981             changed |= fg.setState(state);
17982         }
17983 
17984         if (mScrollCache != null) {
17985             final Drawable scrollBar = mScrollCache.scrollBar;
17986             if (scrollBar != null && scrollBar.isStateful()) {
17987                 changed |= scrollBar.setState(state)
17988                         && mScrollCache.state != ScrollabilityCache.OFF;
17989             }
17990         }
17991 
17992         if (mStateListAnimator != null) {
17993             mStateListAnimator.setState(state);
17994         }
17995 
17996         if (changed) {
17997             invalidate();
17998         }
17999     }
18000 
18001     /**
18002      * This function is called whenever the view hotspot changes and needs to
18003      * be propagated to drawables or child views managed by the view.
18004      * <p>
18005      * Dispatching to child views is handled by
18006      * {@link #dispatchDrawableHotspotChanged(float, float)}.
18007      * <p>
18008      * Be sure to call through to the superclass when overriding this function.
18009      *
18010      * @param x hotspot x coordinate
18011      * @param y hotspot y coordinate
18012      */
18013     @CallSuper
drawableHotspotChanged(float x, float y)18014     public void drawableHotspotChanged(float x, float y) {
18015         if (mBackground != null) {
18016             mBackground.setHotspot(x, y);
18017         }
18018         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18019             mForegroundInfo.mDrawable.setHotspot(x, y);
18020         }
18021 
18022         dispatchDrawableHotspotChanged(x, y);
18023     }
18024 
18025     /**
18026      * Dispatches drawableHotspotChanged to all of this View's children.
18027      *
18028      * @param x hotspot x coordinate
18029      * @param y hotspot y coordinate
18030      * @see #drawableHotspotChanged(float, float)
18031      */
dispatchDrawableHotspotChanged(float x, float y)18032     public void dispatchDrawableHotspotChanged(float x, float y) {
18033     }
18034 
18035     /**
18036      * Call this to force a view to update its drawable state. This will cause
18037      * drawableStateChanged to be called on this view. Views that are interested
18038      * in the new state should call getDrawableState.
18039      *
18040      * @see #drawableStateChanged
18041      * @see #getDrawableState
18042      */
refreshDrawableState()18043     public void refreshDrawableState() {
18044         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18045         drawableStateChanged();
18046 
18047         ViewParent parent = mParent;
18048         if (parent != null) {
18049             parent.childDrawableStateChanged(this);
18050         }
18051     }
18052 
18053     /**
18054      * Return an array of resource IDs of the drawable states representing the
18055      * current state of the view.
18056      *
18057      * @return The current drawable state
18058      *
18059      * @see Drawable#setState(int[])
18060      * @see #drawableStateChanged()
18061      * @see #onCreateDrawableState(int)
18062      */
getDrawableState()18063     public final int[] getDrawableState() {
18064         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18065             return mDrawableState;
18066         } else {
18067             mDrawableState = onCreateDrawableState(0);
18068             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18069             return mDrawableState;
18070         }
18071     }
18072 
18073     /**
18074      * Generate the new {@link android.graphics.drawable.Drawable} state for
18075      * this view. This is called by the view
18076      * system when the cached Drawable state is determined to be invalid.  To
18077      * retrieve the current state, you should use {@link #getDrawableState}.
18078      *
18079      * @param extraSpace if non-zero, this is the number of extra entries you
18080      * would like in the returned array in which you can place your own
18081      * states.
18082      *
18083      * @return Returns an array holding the current {@link Drawable} state of
18084      * the view.
18085      *
18086      * @see #mergeDrawableStates(int[], int[])
18087      */
onCreateDrawableState(int extraSpace)18088     protected int[] onCreateDrawableState(int extraSpace) {
18089         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18090                 mParent instanceof View) {
18091             return ((View) mParent).onCreateDrawableState(extraSpace);
18092         }
18093 
18094         int[] drawableState;
18095 
18096         int privateFlags = mPrivateFlags;
18097 
18098         int viewStateIndex = 0;
18099         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18100         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18101         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18102         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18103         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18104         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18105         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18106                 ThreadedRenderer.isAvailable()) {
18107             // This is set if HW acceleration is requested, even if the current
18108             // process doesn't allow it.  This is just to allow app preview
18109             // windows to better match their app.
18110             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18111         }
18112         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18113 
18114         final int privateFlags2 = mPrivateFlags2;
18115         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18116             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18117         }
18118         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18119             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18120         }
18121 
18122         drawableState = StateSet.get(viewStateIndex);
18123 
18124         //noinspection ConstantIfStatement
18125         if (false) {
18126             Log.i("View", "drawableStateIndex=" + viewStateIndex);
18127             Log.i("View", toString()
18128                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18129                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18130                     + " fo=" + hasFocus()
18131                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18132                     + " wf=" + hasWindowFocus()
18133                     + ": " + Arrays.toString(drawableState));
18134         }
18135 
18136         if (extraSpace == 0) {
18137             return drawableState;
18138         }
18139 
18140         final int[] fullState;
18141         if (drawableState != null) {
18142             fullState = new int[drawableState.length + extraSpace];
18143             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18144         } else {
18145             fullState = new int[extraSpace];
18146         }
18147 
18148         return fullState;
18149     }
18150 
18151     /**
18152      * Merge your own state values in <var>additionalState</var> into the base
18153      * state values <var>baseState</var> that were returned by
18154      * {@link #onCreateDrawableState(int)}.
18155      *
18156      * @param baseState The base state values returned by
18157      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18158      * own additional state values.
18159      *
18160      * @param additionalState The additional state values you would like
18161      * added to <var>baseState</var>; this array is not modified.
18162      *
18163      * @return As a convenience, the <var>baseState</var> array you originally
18164      * passed into the function is returned.
18165      *
18166      * @see #onCreateDrawableState(int)
18167      */
mergeDrawableStates(int[] baseState, int[] additionalState)18168     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18169         final int N = baseState.length;
18170         int i = N - 1;
18171         while (i >= 0 && baseState[i] == 0) {
18172             i--;
18173         }
18174         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18175         return baseState;
18176     }
18177 
18178     /**
18179      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18180      * on all Drawable objects associated with this view.
18181      * <p>
18182      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18183      * attached to this view.
18184      */
18185     @CallSuper
jumpDrawablesToCurrentState()18186     public void jumpDrawablesToCurrentState() {
18187         if (mBackground != null) {
18188             mBackground.jumpToCurrentState();
18189         }
18190         if (mStateListAnimator != null) {
18191             mStateListAnimator.jumpToCurrentState();
18192         }
18193         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18194             mForegroundInfo.mDrawable.jumpToCurrentState();
18195         }
18196     }
18197 
18198     /**
18199      * Sets the background color for this view.
18200      * @param color the color of the background
18201      */
18202     @RemotableViewMethod
setBackgroundColor(@olorInt int color)18203     public void setBackgroundColor(@ColorInt int color) {
18204         if (mBackground instanceof ColorDrawable) {
18205             ((ColorDrawable) mBackground.mutate()).setColor(color);
18206             computeOpaqueFlags();
18207             mBackgroundResource = 0;
18208         } else {
18209             setBackground(new ColorDrawable(color));
18210         }
18211     }
18212 
18213     /**
18214      * Set the background to a given resource. The resource should refer to
18215      * a Drawable object or 0 to remove the background.
18216      * @param resid The identifier of the resource.
18217      *
18218      * @attr ref android.R.styleable#View_background
18219      */
18220     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)18221     public void setBackgroundResource(@DrawableRes int resid) {
18222         if (resid != 0 && resid == mBackgroundResource) {
18223             return;
18224         }
18225 
18226         Drawable d = null;
18227         if (resid != 0) {
18228             d = mContext.getDrawable(resid);
18229         }
18230         setBackground(d);
18231 
18232         mBackgroundResource = resid;
18233     }
18234 
18235     /**
18236      * Set the background to a given Drawable, or remove the background. If the
18237      * background has padding, this View's padding is set to the background's
18238      * padding. However, when a background is removed, this View's padding isn't
18239      * touched. If setting the padding is desired, please use
18240      * {@link #setPadding(int, int, int, int)}.
18241      *
18242      * @param background The Drawable to use as the background, or null to remove the
18243      *        background
18244      */
setBackground(Drawable background)18245     public void setBackground(Drawable background) {
18246         //noinspection deprecation
18247         setBackgroundDrawable(background);
18248     }
18249 
18250     /**
18251      * @deprecated use {@link #setBackground(Drawable)} instead
18252      */
18253     @Deprecated
setBackgroundDrawable(Drawable background)18254     public void setBackgroundDrawable(Drawable background) {
18255         computeOpaqueFlags();
18256 
18257         if (background == mBackground) {
18258             return;
18259         }
18260 
18261         boolean requestLayout = false;
18262 
18263         mBackgroundResource = 0;
18264 
18265         /*
18266          * Regardless of whether we're setting a new background or not, we want
18267          * to clear the previous drawable. setVisible first while we still have the callback set.
18268          */
18269         if (mBackground != null) {
18270             if (isAttachedToWindow()) {
18271                 mBackground.setVisible(false, false);
18272             }
18273             mBackground.setCallback(null);
18274             unscheduleDrawable(mBackground);
18275         }
18276 
18277         if (background != null) {
18278             Rect padding = sThreadLocal.get();
18279             if (padding == null) {
18280                 padding = new Rect();
18281                 sThreadLocal.set(padding);
18282             }
18283             resetResolvedDrawablesInternal();
18284             background.setLayoutDirection(getLayoutDirection());
18285             if (background.getPadding(padding)) {
18286                 resetResolvedPaddingInternal();
18287                 switch (background.getLayoutDirection()) {
18288                     case LAYOUT_DIRECTION_RTL:
18289                         mUserPaddingLeftInitial = padding.right;
18290                         mUserPaddingRightInitial = padding.left;
18291                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18292                         break;
18293                     case LAYOUT_DIRECTION_LTR:
18294                     default:
18295                         mUserPaddingLeftInitial = padding.left;
18296                         mUserPaddingRightInitial = padding.right;
18297                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18298                 }
18299                 mLeftPaddingDefined = false;
18300                 mRightPaddingDefined = false;
18301             }
18302 
18303             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18304             // if it has a different minimum size, we should layout again
18305             if (mBackground == null
18306                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
18307                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18308                 requestLayout = true;
18309             }
18310 
18311             // Set mBackground before we set this as the callback and start making other
18312             // background drawable state change calls. In particular, the setVisible call below
18313             // can result in drawables attempting to start animations or otherwise invalidate,
18314             // which requires the view set as the callback (us) to recognize the drawable as
18315             // belonging to it as per verifyDrawable.
18316             mBackground = background;
18317             if (background.isStateful()) {
18318                 background.setState(getDrawableState());
18319             }
18320             if (isAttachedToWindow()) {
18321                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18322             }
18323 
18324             applyBackgroundTint();
18325 
18326             // Set callback last, since the view may still be initializing.
18327             background.setCallback(this);
18328 
18329             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18330                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18331                 requestLayout = true;
18332             }
18333         } else {
18334             /* Remove the background */
18335             mBackground = null;
18336             if ((mViewFlags & WILL_NOT_DRAW) != 0
18337                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18338                 mPrivateFlags |= PFLAG_SKIP_DRAW;
18339             }
18340 
18341             /*
18342              * When the background is set, we try to apply its padding to this
18343              * View. When the background is removed, we don't touch this View's
18344              * padding. This is noted in the Javadocs. Hence, we don't need to
18345              * requestLayout(), the invalidate() below is sufficient.
18346              */
18347 
18348             // The old background's minimum size could have affected this
18349             // View's layout, so let's requestLayout
18350             requestLayout = true;
18351         }
18352 
18353         computeOpaqueFlags();
18354 
18355         if (requestLayout) {
18356             requestLayout();
18357         }
18358 
18359         mBackgroundSizeChanged = true;
18360         invalidate(true);
18361         invalidateOutline();
18362     }
18363 
18364     /**
18365      * Gets the background drawable
18366      *
18367      * @return The drawable used as the background for this view, if any.
18368      *
18369      * @see #setBackground(Drawable)
18370      *
18371      * @attr ref android.R.styleable#View_background
18372      */
getBackground()18373     public Drawable getBackground() {
18374         return mBackground;
18375     }
18376 
18377     /**
18378      * Applies a tint to the background drawable. Does not modify the current tint
18379      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18380      * <p>
18381      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18382      * mutate the drawable and apply the specified tint and tint mode using
18383      * {@link Drawable#setTintList(ColorStateList)}.
18384      *
18385      * @param tint the tint to apply, may be {@code null} to clear tint
18386      *
18387      * @attr ref android.R.styleable#View_backgroundTint
18388      * @see #getBackgroundTintList()
18389      * @see Drawable#setTintList(ColorStateList)
18390      */
setBackgroundTintList(@ullable ColorStateList tint)18391     public void setBackgroundTintList(@Nullable ColorStateList tint) {
18392         if (mBackgroundTint == null) {
18393             mBackgroundTint = new TintInfo();
18394         }
18395         mBackgroundTint.mTintList = tint;
18396         mBackgroundTint.mHasTintList = true;
18397 
18398         applyBackgroundTint();
18399     }
18400 
18401     /**
18402      * Return the tint applied to the background drawable, if specified.
18403      *
18404      * @return the tint applied to the background drawable
18405      * @attr ref android.R.styleable#View_backgroundTint
18406      * @see #setBackgroundTintList(ColorStateList)
18407      */
18408     @Nullable
getBackgroundTintList()18409     public ColorStateList getBackgroundTintList() {
18410         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18411     }
18412 
18413     /**
18414      * Specifies the blending mode used to apply the tint specified by
18415      * {@link #setBackgroundTintList(ColorStateList)}} to the background
18416      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18417      *
18418      * @param tintMode the blending mode used to apply the tint, may be
18419      *                 {@code null} to clear tint
18420      * @attr ref android.R.styleable#View_backgroundTintMode
18421      * @see #getBackgroundTintMode()
18422      * @see Drawable#setTintMode(PorterDuff.Mode)
18423      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)18424     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18425         if (mBackgroundTint == null) {
18426             mBackgroundTint = new TintInfo();
18427         }
18428         mBackgroundTint.mTintMode = tintMode;
18429         mBackgroundTint.mHasTintMode = true;
18430 
18431         applyBackgroundTint();
18432     }
18433 
18434     /**
18435      * Return the blending mode used to apply the tint to the background
18436      * drawable, if specified.
18437      *
18438      * @return the blending mode used to apply the tint to the background
18439      *         drawable
18440      * @attr ref android.R.styleable#View_backgroundTintMode
18441      * @see #setBackgroundTintMode(PorterDuff.Mode)
18442      */
18443     @Nullable
getBackgroundTintMode()18444     public PorterDuff.Mode getBackgroundTintMode() {
18445         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18446     }
18447 
applyBackgroundTint()18448     private void applyBackgroundTint() {
18449         if (mBackground != null && mBackgroundTint != null) {
18450             final TintInfo tintInfo = mBackgroundTint;
18451             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18452                 mBackground = mBackground.mutate();
18453 
18454                 if (tintInfo.mHasTintList) {
18455                     mBackground.setTintList(tintInfo.mTintList);
18456                 }
18457 
18458                 if (tintInfo.mHasTintMode) {
18459                     mBackground.setTintMode(tintInfo.mTintMode);
18460                 }
18461 
18462                 // The drawable (or one of its children) may not have been
18463                 // stateful before applying the tint, so let's try again.
18464                 if (mBackground.isStateful()) {
18465                     mBackground.setState(getDrawableState());
18466                 }
18467             }
18468         }
18469     }
18470 
18471     /**
18472      * Returns the drawable used as the foreground of this View. The
18473      * foreground drawable, if non-null, is always drawn on top of the view's content.
18474      *
18475      * @return a Drawable or null if no foreground was set
18476      *
18477      * @see #onDrawForeground(Canvas)
18478      */
getForeground()18479     public Drawable getForeground() {
18480         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18481     }
18482 
18483     /**
18484      * Supply a Drawable that is to be rendered on top of all of the content in the view.
18485      *
18486      * @param foreground the Drawable to be drawn on top of the children
18487      *
18488      * @attr ref android.R.styleable#View_foreground
18489      */
setForeground(Drawable foreground)18490     public void setForeground(Drawable foreground) {
18491         if (mForegroundInfo == null) {
18492             if (foreground == null) {
18493                 // Nothing to do.
18494                 return;
18495             }
18496             mForegroundInfo = new ForegroundInfo();
18497         }
18498 
18499         if (foreground == mForegroundInfo.mDrawable) {
18500             // Nothing to do
18501             return;
18502         }
18503 
18504         if (mForegroundInfo.mDrawable != null) {
18505             if (isAttachedToWindow()) {
18506                 mForegroundInfo.mDrawable.setVisible(false, false);
18507             }
18508             mForegroundInfo.mDrawable.setCallback(null);
18509             unscheduleDrawable(mForegroundInfo.mDrawable);
18510         }
18511 
18512         mForegroundInfo.mDrawable = foreground;
18513         mForegroundInfo.mBoundsChanged = true;
18514         if (foreground != null) {
18515             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18516                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18517             }
18518             foreground.setLayoutDirection(getLayoutDirection());
18519             if (foreground.isStateful()) {
18520                 foreground.setState(getDrawableState());
18521             }
18522             applyForegroundTint();
18523             if (isAttachedToWindow()) {
18524                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18525             }
18526             // Set callback last, since the view may still be initializing.
18527             foreground.setCallback(this);
18528         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18529             mPrivateFlags |= PFLAG_SKIP_DRAW;
18530         }
18531         requestLayout();
18532         invalidate();
18533     }
18534 
18535     /**
18536      * Magic bit used to support features of framework-internal window decor implementation details.
18537      * This used to live exclusively in FrameLayout.
18538      *
18539      * @return true if the foreground should draw inside the padding region or false
18540      *         if it should draw inset by the view's padding
18541      * @hide internal use only; only used by FrameLayout and internal screen layouts.
18542      */
isForegroundInsidePadding()18543     public boolean isForegroundInsidePadding() {
18544         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18545     }
18546 
18547     /**
18548      * Describes how the foreground is positioned.
18549      *
18550      * @return foreground gravity.
18551      *
18552      * @see #setForegroundGravity(int)
18553      *
18554      * @attr ref android.R.styleable#View_foregroundGravity
18555      */
getForegroundGravity()18556     public int getForegroundGravity() {
18557         return mForegroundInfo != null ? mForegroundInfo.mGravity
18558                 : Gravity.START | Gravity.TOP;
18559     }
18560 
18561     /**
18562      * Describes how the foreground is positioned. Defaults to START and TOP.
18563      *
18564      * @param gravity see {@link android.view.Gravity}
18565      *
18566      * @see #getForegroundGravity()
18567      *
18568      * @attr ref android.R.styleable#View_foregroundGravity
18569      */
setForegroundGravity(int gravity)18570     public void setForegroundGravity(int gravity) {
18571         if (mForegroundInfo == null) {
18572             mForegroundInfo = new ForegroundInfo();
18573         }
18574 
18575         if (mForegroundInfo.mGravity != gravity) {
18576             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18577                 gravity |= Gravity.START;
18578             }
18579 
18580             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18581                 gravity |= Gravity.TOP;
18582             }
18583 
18584             mForegroundInfo.mGravity = gravity;
18585             requestLayout();
18586         }
18587     }
18588 
18589     /**
18590      * Applies a tint to the foreground drawable. Does not modify the current tint
18591      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18592      * <p>
18593      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18594      * mutate the drawable and apply the specified tint and tint mode using
18595      * {@link Drawable#setTintList(ColorStateList)}.
18596      *
18597      * @param tint the tint to apply, may be {@code null} to clear tint
18598      *
18599      * @attr ref android.R.styleable#View_foregroundTint
18600      * @see #getForegroundTintList()
18601      * @see Drawable#setTintList(ColorStateList)
18602      */
setForegroundTintList(@ullable ColorStateList tint)18603     public void setForegroundTintList(@Nullable ColorStateList tint) {
18604         if (mForegroundInfo == null) {
18605             mForegroundInfo = new ForegroundInfo();
18606         }
18607         if (mForegroundInfo.mTintInfo == null) {
18608             mForegroundInfo.mTintInfo = new TintInfo();
18609         }
18610         mForegroundInfo.mTintInfo.mTintList = tint;
18611         mForegroundInfo.mTintInfo.mHasTintList = true;
18612 
18613         applyForegroundTint();
18614     }
18615 
18616     /**
18617      * Return the tint applied to the foreground drawable, if specified.
18618      *
18619      * @return the tint applied to the foreground drawable
18620      * @attr ref android.R.styleable#View_foregroundTint
18621      * @see #setForegroundTintList(ColorStateList)
18622      */
18623     @Nullable
getForegroundTintList()18624     public ColorStateList getForegroundTintList() {
18625         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18626                 ? mForegroundInfo.mTintInfo.mTintList : null;
18627     }
18628 
18629     /**
18630      * Specifies the blending mode used to apply the tint specified by
18631      * {@link #setForegroundTintList(ColorStateList)}} to the background
18632      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18633      *
18634      * @param tintMode the blending mode used to apply the tint, may be
18635      *                 {@code null} to clear tint
18636      * @attr ref android.R.styleable#View_foregroundTintMode
18637      * @see #getForegroundTintMode()
18638      * @see Drawable#setTintMode(PorterDuff.Mode)
18639      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)18640     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18641         if (mForegroundInfo == null) {
18642             mForegroundInfo = new ForegroundInfo();
18643         }
18644         if (mForegroundInfo.mTintInfo == null) {
18645             mForegroundInfo.mTintInfo = new TintInfo();
18646         }
18647         mForegroundInfo.mTintInfo.mTintMode = tintMode;
18648         mForegroundInfo.mTintInfo.mHasTintMode = true;
18649 
18650         applyForegroundTint();
18651     }
18652 
18653     /**
18654      * Return the blending mode used to apply the tint to the foreground
18655      * drawable, if specified.
18656      *
18657      * @return the blending mode used to apply the tint to the foreground
18658      *         drawable
18659      * @attr ref android.R.styleable#View_foregroundTintMode
18660      * @see #setForegroundTintMode(PorterDuff.Mode)
18661      */
18662     @Nullable
getForegroundTintMode()18663     public PorterDuff.Mode getForegroundTintMode() {
18664         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18665                 ? mForegroundInfo.mTintInfo.mTintMode : null;
18666     }
18667 
applyForegroundTint()18668     private void applyForegroundTint() {
18669         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18670                 && mForegroundInfo.mTintInfo != null) {
18671             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18672             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18673                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18674 
18675                 if (tintInfo.mHasTintList) {
18676                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18677                 }
18678 
18679                 if (tintInfo.mHasTintMode) {
18680                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18681                 }
18682 
18683                 // The drawable (or one of its children) may not have been
18684                 // stateful before applying the tint, so let's try again.
18685                 if (mForegroundInfo.mDrawable.isStateful()) {
18686                     mForegroundInfo.mDrawable.setState(getDrawableState());
18687                 }
18688             }
18689         }
18690     }
18691 
18692     /**
18693      * Draw any foreground content for this view.
18694      *
18695      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18696      * drawable or other view-specific decorations. The foreground is drawn on top of the
18697      * primary view content.</p>
18698      *
18699      * @param canvas canvas to draw into
18700      */
onDrawForeground(Canvas canvas)18701     public void onDrawForeground(Canvas canvas) {
18702         onDrawScrollIndicators(canvas);
18703         onDrawScrollBars(canvas);
18704 
18705         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18706         if (foreground != null) {
18707             if (mForegroundInfo.mBoundsChanged) {
18708                 mForegroundInfo.mBoundsChanged = false;
18709                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
18710                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18711 
18712                 if (mForegroundInfo.mInsidePadding) {
18713                     selfBounds.set(0, 0, getWidth(), getHeight());
18714                 } else {
18715                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
18716                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18717                 }
18718 
18719                 final int ld = getLayoutDirection();
18720                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18721                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18722                 foreground.setBounds(overlayBounds);
18723             }
18724 
18725             foreground.draw(canvas);
18726         }
18727     }
18728 
18729     /**
18730      * Sets the padding. The view may add on the space required to display
18731      * the scrollbars, depending on the style and visibility of the scrollbars.
18732      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18733      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18734      * from the values set in this call.
18735      *
18736      * @attr ref android.R.styleable#View_padding
18737      * @attr ref android.R.styleable#View_paddingBottom
18738      * @attr ref android.R.styleable#View_paddingLeft
18739      * @attr ref android.R.styleable#View_paddingRight
18740      * @attr ref android.R.styleable#View_paddingTop
18741      * @param left the left padding in pixels
18742      * @param top the top padding in pixels
18743      * @param right the right padding in pixels
18744      * @param bottom the bottom padding in pixels
18745      */
setPadding(int left, int top, int right, int bottom)18746     public void setPadding(int left, int top, int right, int bottom) {
18747         resetResolvedPaddingInternal();
18748 
18749         mUserPaddingStart = UNDEFINED_PADDING;
18750         mUserPaddingEnd = UNDEFINED_PADDING;
18751 
18752         mUserPaddingLeftInitial = left;
18753         mUserPaddingRightInitial = right;
18754 
18755         mLeftPaddingDefined = true;
18756         mRightPaddingDefined = true;
18757 
18758         internalSetPadding(left, top, right, bottom);
18759     }
18760 
18761     /**
18762      * @hide
18763      */
internalSetPadding(int left, int top, int right, int bottom)18764     protected void internalSetPadding(int left, int top, int right, int bottom) {
18765         mUserPaddingLeft = left;
18766         mUserPaddingRight = right;
18767         mUserPaddingBottom = bottom;
18768 
18769         final int viewFlags = mViewFlags;
18770         boolean changed = false;
18771 
18772         // Common case is there are no scroll bars.
18773         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18774             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18775                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18776                         ? 0 : getVerticalScrollbarWidth();
18777                 switch (mVerticalScrollbarPosition) {
18778                     case SCROLLBAR_POSITION_DEFAULT:
18779                         if (isLayoutRtl()) {
18780                             left += offset;
18781                         } else {
18782                             right += offset;
18783                         }
18784                         break;
18785                     case SCROLLBAR_POSITION_RIGHT:
18786                         right += offset;
18787                         break;
18788                     case SCROLLBAR_POSITION_LEFT:
18789                         left += offset;
18790                         break;
18791                 }
18792             }
18793             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18794                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18795                         ? 0 : getHorizontalScrollbarHeight();
18796             }
18797         }
18798 
18799         if (mPaddingLeft != left) {
18800             changed = true;
18801             mPaddingLeft = left;
18802         }
18803         if (mPaddingTop != top) {
18804             changed = true;
18805             mPaddingTop = top;
18806         }
18807         if (mPaddingRight != right) {
18808             changed = true;
18809             mPaddingRight = right;
18810         }
18811         if (mPaddingBottom != bottom) {
18812             changed = true;
18813             mPaddingBottom = bottom;
18814         }
18815 
18816         if (changed) {
18817             requestLayout();
18818             invalidateOutline();
18819         }
18820     }
18821 
18822     /**
18823      * Sets the relative padding. The view may add on the space required to display
18824      * the scrollbars, depending on the style and visibility of the scrollbars.
18825      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18826      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18827      * from the values set in this call.
18828      *
18829      * @attr ref android.R.styleable#View_padding
18830      * @attr ref android.R.styleable#View_paddingBottom
18831      * @attr ref android.R.styleable#View_paddingStart
18832      * @attr ref android.R.styleable#View_paddingEnd
18833      * @attr ref android.R.styleable#View_paddingTop
18834      * @param start the start padding in pixels
18835      * @param top the top padding in pixels
18836      * @param end the end padding in pixels
18837      * @param bottom the bottom padding in pixels
18838      */
setPaddingRelative(int start, int top, int end, int bottom)18839     public void setPaddingRelative(int start, int top, int end, int bottom) {
18840         resetResolvedPaddingInternal();
18841 
18842         mUserPaddingStart = start;
18843         mUserPaddingEnd = end;
18844         mLeftPaddingDefined = true;
18845         mRightPaddingDefined = true;
18846 
18847         switch(getLayoutDirection()) {
18848             case LAYOUT_DIRECTION_RTL:
18849                 mUserPaddingLeftInitial = end;
18850                 mUserPaddingRightInitial = start;
18851                 internalSetPadding(end, top, start, bottom);
18852                 break;
18853             case LAYOUT_DIRECTION_LTR:
18854             default:
18855                 mUserPaddingLeftInitial = start;
18856                 mUserPaddingRightInitial = end;
18857                 internalSetPadding(start, top, end, bottom);
18858         }
18859     }
18860 
18861     /**
18862      * Returns the top padding of this view.
18863      *
18864      * @return the top padding in pixels
18865      */
getPaddingTop()18866     public int getPaddingTop() {
18867         return mPaddingTop;
18868     }
18869 
18870     /**
18871      * Returns the bottom padding of this view. If there are inset and enabled
18872      * scrollbars, this value may include the space required to display the
18873      * scrollbars as well.
18874      *
18875      * @return the bottom padding in pixels
18876      */
getPaddingBottom()18877     public int getPaddingBottom() {
18878         return mPaddingBottom;
18879     }
18880 
18881     /**
18882      * Returns the left padding of this view. If there are inset and enabled
18883      * scrollbars, this value may include the space required to display the
18884      * scrollbars as well.
18885      *
18886      * @return the left padding in pixels
18887      */
getPaddingLeft()18888     public int getPaddingLeft() {
18889         if (!isPaddingResolved()) {
18890             resolvePadding();
18891         }
18892         return mPaddingLeft;
18893     }
18894 
18895     /**
18896      * Returns the start padding of this view depending on its resolved layout direction.
18897      * If there are inset and enabled scrollbars, this value may include the space
18898      * required to display the scrollbars as well.
18899      *
18900      * @return the start padding in pixels
18901      */
getPaddingStart()18902     public int getPaddingStart() {
18903         if (!isPaddingResolved()) {
18904             resolvePadding();
18905         }
18906         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18907                 mPaddingRight : mPaddingLeft;
18908     }
18909 
18910     /**
18911      * Returns the right padding of this view. If there are inset and enabled
18912      * scrollbars, this value may include the space required to display the
18913      * scrollbars as well.
18914      *
18915      * @return the right padding in pixels
18916      */
getPaddingRight()18917     public int getPaddingRight() {
18918         if (!isPaddingResolved()) {
18919             resolvePadding();
18920         }
18921         return mPaddingRight;
18922     }
18923 
18924     /**
18925      * Returns the end padding of this view depending on its resolved layout direction.
18926      * If there are inset and enabled scrollbars, this value may include the space
18927      * required to display the scrollbars as well.
18928      *
18929      * @return the end padding in pixels
18930      */
getPaddingEnd()18931     public int getPaddingEnd() {
18932         if (!isPaddingResolved()) {
18933             resolvePadding();
18934         }
18935         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18936                 mPaddingLeft : mPaddingRight;
18937     }
18938 
18939     /**
18940      * Return if the padding has been set through relative values
18941      * {@link #setPaddingRelative(int, int, int, int)} or through
18942      * @attr ref android.R.styleable#View_paddingStart or
18943      * @attr ref android.R.styleable#View_paddingEnd
18944      *
18945      * @return true if the padding is relative or false if it is not.
18946      */
isPaddingRelative()18947     public boolean isPaddingRelative() {
18948         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18949     }
18950 
computeOpticalInsets()18951     Insets computeOpticalInsets() {
18952         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18953     }
18954 
18955     /**
18956      * @hide
18957      */
resetPaddingToInitialValues()18958     public void resetPaddingToInitialValues() {
18959         if (isRtlCompatibilityMode()) {
18960             mPaddingLeft = mUserPaddingLeftInitial;
18961             mPaddingRight = mUserPaddingRightInitial;
18962             return;
18963         }
18964         if (isLayoutRtl()) {
18965             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18966             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18967         } else {
18968             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18969             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18970         }
18971     }
18972 
18973     /**
18974      * @hide
18975      */
getOpticalInsets()18976     public Insets getOpticalInsets() {
18977         if (mLayoutInsets == null) {
18978             mLayoutInsets = computeOpticalInsets();
18979         }
18980         return mLayoutInsets;
18981     }
18982 
18983     /**
18984      * Set this view's optical insets.
18985      *
18986      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18987      * property. Views that compute their own optical insets should call it as part of measurement.
18988      * This method does not request layout. If you are setting optical insets outside of
18989      * measure/layout itself you will want to call requestLayout() yourself.
18990      * </p>
18991      * @hide
18992      */
setOpticalInsets(Insets insets)18993     public void setOpticalInsets(Insets insets) {
18994         mLayoutInsets = insets;
18995     }
18996 
18997     /**
18998      * Changes the selection state of this view. A view can be selected or not.
18999      * Note that selection is not the same as focus. Views are typically
19000      * selected in the context of an AdapterView like ListView or GridView;
19001      * the selected view is the view that is highlighted.
19002      *
19003      * @param selected true if the view must be selected, false otherwise
19004      */
setSelected(boolean selected)19005     public void setSelected(boolean selected) {
19006         //noinspection DoubleNegation
19007         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19008             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19009             if (!selected) resetPressedState();
19010             invalidate(true);
19011             refreshDrawableState();
19012             dispatchSetSelected(selected);
19013             if (selected) {
19014                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19015             } else {
19016                 notifyViewAccessibilityStateChangedIfNeeded(
19017                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19018             }
19019         }
19020     }
19021 
19022     /**
19023      * Dispatch setSelected to all of this View's children.
19024      *
19025      * @see #setSelected(boolean)
19026      *
19027      * @param selected The new selected state
19028      */
dispatchSetSelected(boolean selected)19029     protected void dispatchSetSelected(boolean selected) {
19030     }
19031 
19032     /**
19033      * Indicates the selection state of this view.
19034      *
19035      * @return true if the view is selected, false otherwise
19036      */
19037     @ViewDebug.ExportedProperty
isSelected()19038     public boolean isSelected() {
19039         return (mPrivateFlags & PFLAG_SELECTED) != 0;
19040     }
19041 
19042     /**
19043      * Changes the activated state of this view. A view can be activated or not.
19044      * Note that activation is not the same as selection.  Selection is
19045      * a transient property, representing the view (hierarchy) the user is
19046      * currently interacting with.  Activation is a longer-term state that the
19047      * user can move views in and out of.  For example, in a list view with
19048      * single or multiple selection enabled, the views in the current selection
19049      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19050      * here.)  The activated state is propagated down to children of the view it
19051      * is set on.
19052      *
19053      * @param activated true if the view must be activated, false otherwise
19054      */
setActivated(boolean activated)19055     public void setActivated(boolean activated) {
19056         //noinspection DoubleNegation
19057         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19058             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19059             invalidate(true);
19060             refreshDrawableState();
19061             dispatchSetActivated(activated);
19062         }
19063     }
19064 
19065     /**
19066      * Dispatch setActivated to all of this View's children.
19067      *
19068      * @see #setActivated(boolean)
19069      *
19070      * @param activated The new activated state
19071      */
dispatchSetActivated(boolean activated)19072     protected void dispatchSetActivated(boolean activated) {
19073     }
19074 
19075     /**
19076      * Indicates the activation state of this view.
19077      *
19078      * @return true if the view is activated, false otherwise
19079      */
19080     @ViewDebug.ExportedProperty
isActivated()19081     public boolean isActivated() {
19082         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19083     }
19084 
19085     /**
19086      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19087      * observer can be used to get notifications when global events, like
19088      * layout, happen.
19089      *
19090      * The returned ViewTreeObserver observer is not guaranteed to remain
19091      * valid for the lifetime of this View. If the caller of this method keeps
19092      * a long-lived reference to ViewTreeObserver, it should always check for
19093      * the return value of {@link ViewTreeObserver#isAlive()}.
19094      *
19095      * @return The ViewTreeObserver for this view's hierarchy.
19096      */
getViewTreeObserver()19097     public ViewTreeObserver getViewTreeObserver() {
19098         if (mAttachInfo != null) {
19099             return mAttachInfo.mTreeObserver;
19100         }
19101         if (mFloatingTreeObserver == null) {
19102             mFloatingTreeObserver = new ViewTreeObserver();
19103         }
19104         return mFloatingTreeObserver;
19105     }
19106 
19107     /**
19108      * <p>Finds the topmost view in the current view hierarchy.</p>
19109      *
19110      * @return the topmost view containing this view
19111      */
getRootView()19112     public View getRootView() {
19113         if (mAttachInfo != null) {
19114             final View v = mAttachInfo.mRootView;
19115             if (v != null) {
19116                 return v;
19117             }
19118         }
19119 
19120         View parent = this;
19121 
19122         while (parent.mParent != null && parent.mParent instanceof View) {
19123             parent = (View) parent.mParent;
19124         }
19125 
19126         return parent;
19127     }
19128 
19129     /**
19130      * Transforms a motion event from view-local coordinates to on-screen
19131      * coordinates.
19132      *
19133      * @param ev the view-local motion event
19134      * @return false if the transformation could not be applied
19135      * @hide
19136      */
toGlobalMotionEvent(MotionEvent ev)19137     public boolean toGlobalMotionEvent(MotionEvent ev) {
19138         final AttachInfo info = mAttachInfo;
19139         if (info == null) {
19140             return false;
19141         }
19142 
19143         final Matrix m = info.mTmpMatrix;
19144         m.set(Matrix.IDENTITY_MATRIX);
19145         transformMatrixToGlobal(m);
19146         ev.transform(m);
19147         return true;
19148     }
19149 
19150     /**
19151      * Transforms a motion event from on-screen coordinates to view-local
19152      * coordinates.
19153      *
19154      * @param ev the on-screen motion event
19155      * @return false if the transformation could not be applied
19156      * @hide
19157      */
toLocalMotionEvent(MotionEvent ev)19158     public boolean toLocalMotionEvent(MotionEvent ev) {
19159         final AttachInfo info = mAttachInfo;
19160         if (info == null) {
19161             return false;
19162         }
19163 
19164         final Matrix m = info.mTmpMatrix;
19165         m.set(Matrix.IDENTITY_MATRIX);
19166         transformMatrixToLocal(m);
19167         ev.transform(m);
19168         return true;
19169     }
19170 
19171     /**
19172      * Modifies the input matrix such that it maps view-local coordinates to
19173      * on-screen coordinates.
19174      *
19175      * @param m input matrix to modify
19176      * @hide
19177      */
transformMatrixToGlobal(Matrix m)19178     public void transformMatrixToGlobal(Matrix m) {
19179         final ViewParent parent = mParent;
19180         if (parent instanceof View) {
19181             final View vp = (View) parent;
19182             vp.transformMatrixToGlobal(m);
19183             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19184         } else if (parent instanceof ViewRootImpl) {
19185             final ViewRootImpl vr = (ViewRootImpl) parent;
19186             vr.transformMatrixToGlobal(m);
19187             m.preTranslate(0, -vr.mCurScrollY);
19188         }
19189 
19190         m.preTranslate(mLeft, mTop);
19191 
19192         if (!hasIdentityMatrix()) {
19193             m.preConcat(getMatrix());
19194         }
19195     }
19196 
19197     /**
19198      * Modifies the input matrix such that it maps on-screen coordinates to
19199      * view-local coordinates.
19200      *
19201      * @param m input matrix to modify
19202      * @hide
19203      */
transformMatrixToLocal(Matrix m)19204     public void transformMatrixToLocal(Matrix m) {
19205         final ViewParent parent = mParent;
19206         if (parent instanceof View) {
19207             final View vp = (View) parent;
19208             vp.transformMatrixToLocal(m);
19209             m.postTranslate(vp.mScrollX, vp.mScrollY);
19210         } else if (parent instanceof ViewRootImpl) {
19211             final ViewRootImpl vr = (ViewRootImpl) parent;
19212             vr.transformMatrixToLocal(m);
19213             m.postTranslate(0, vr.mCurScrollY);
19214         }
19215 
19216         m.postTranslate(-mLeft, -mTop);
19217 
19218         if (!hasIdentityMatrix()) {
19219             m.postConcat(getInverseMatrix());
19220         }
19221     }
19222 
19223     /**
19224      * @hide
19225      */
19226     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19227             @ViewDebug.IntToString(from = 0, to = "x"),
19228             @ViewDebug.IntToString(from = 1, to = "y")
19229     })
getLocationOnScreen()19230     public int[] getLocationOnScreen() {
19231         int[] location = new int[2];
19232         getLocationOnScreen(location);
19233         return location;
19234     }
19235 
19236     /**
19237      * <p>Computes the coordinates of this view on the screen. The argument
19238      * must be an array of two integers. After the method returns, the array
19239      * contains the x and y location in that order.</p>
19240      *
19241      * @param outLocation an array of two integers in which to hold the coordinates
19242      */
getLocationOnScreen(@ize2) int[] outLocation)19243     public void getLocationOnScreen(@Size(2) int[] outLocation) {
19244         getLocationInWindow(outLocation);
19245 
19246         final AttachInfo info = mAttachInfo;
19247         if (info != null) {
19248             outLocation[0] += info.mWindowLeft;
19249             outLocation[1] += info.mWindowTop;
19250         }
19251     }
19252 
19253     /**
19254      * <p>Computes the coordinates of this view in its window. The argument
19255      * must be an array of two integers. After the method returns, the array
19256      * contains the x and y location in that order.</p>
19257      *
19258      * @param outLocation an array of two integers in which to hold the coordinates
19259      */
getLocationInWindow(@ize2) int[] outLocation)19260     public void getLocationInWindow(@Size(2) int[] outLocation) {
19261         if (outLocation == null || outLocation.length < 2) {
19262             throw new IllegalArgumentException("outLocation must be an array of two integers");
19263         }
19264 
19265         outLocation[0] = 0;
19266         outLocation[1] = 0;
19267 
19268         transformFromViewToWindowSpace(outLocation);
19269     }
19270 
19271     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)19272     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19273         if (inOutLocation == null || inOutLocation.length < 2) {
19274             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19275         }
19276 
19277         if (mAttachInfo == null) {
19278             // When the view is not attached to a window, this method does not make sense
19279             inOutLocation[0] = inOutLocation[1] = 0;
19280             return;
19281         }
19282 
19283         float position[] = mAttachInfo.mTmpTransformLocation;
19284         position[0] = inOutLocation[0];
19285         position[1] = inOutLocation[1];
19286 
19287         if (!hasIdentityMatrix()) {
19288             getMatrix().mapPoints(position);
19289         }
19290 
19291         position[0] += mLeft;
19292         position[1] += mTop;
19293 
19294         ViewParent viewParent = mParent;
19295         while (viewParent instanceof View) {
19296             final View view = (View) viewParent;
19297 
19298             position[0] -= view.mScrollX;
19299             position[1] -= view.mScrollY;
19300 
19301             if (!view.hasIdentityMatrix()) {
19302                 view.getMatrix().mapPoints(position);
19303             }
19304 
19305             position[0] += view.mLeft;
19306             position[1] += view.mTop;
19307 
19308             viewParent = view.mParent;
19309          }
19310 
19311         if (viewParent instanceof ViewRootImpl) {
19312             // *cough*
19313             final ViewRootImpl vr = (ViewRootImpl) viewParent;
19314             position[1] -= vr.mCurScrollY;
19315         }
19316 
19317         inOutLocation[0] = Math.round(position[0]);
19318         inOutLocation[1] = Math.round(position[1]);
19319     }
19320 
19321     /**
19322      * {@hide}
19323      * @param id the id of the view to be found
19324      * @return the view of the specified id, null if cannot be found
19325      */
findViewTraversal(@dRes int id)19326     protected View findViewTraversal(@IdRes int id) {
19327         if (id == mID) {
19328             return this;
19329         }
19330         return null;
19331     }
19332 
19333     /**
19334      * {@hide}
19335      * @param tag the tag of the view to be found
19336      * @return the view of specified tag, null if cannot be found
19337      */
findViewWithTagTraversal(Object tag)19338     protected View findViewWithTagTraversal(Object tag) {
19339         if (tag != null && tag.equals(mTag)) {
19340             return this;
19341         }
19342         return null;
19343     }
19344 
19345     /**
19346      * {@hide}
19347      * @param predicate The predicate to evaluate.
19348      * @param childToSkip If not null, ignores this child during the recursive traversal.
19349      * @return The first view that matches the predicate or null.
19350      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)19351     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19352         if (predicate.apply(this)) {
19353             return this;
19354         }
19355         return null;
19356     }
19357 
19358     /**
19359      * Look for a child view with the given id.  If this view has the given
19360      * id, return this view.
19361      *
19362      * @param id The id to search for.
19363      * @return The view that has the given id in the hierarchy or null
19364      */
19365     @Nullable
findViewById(@dRes int id)19366     public final View findViewById(@IdRes int id) {
19367         if (id < 0) {
19368             return null;
19369         }
19370         return findViewTraversal(id);
19371     }
19372 
19373     /**
19374      * Finds a view by its unuque and stable accessibility id.
19375      *
19376      * @param accessibilityId The searched accessibility id.
19377      * @return The found view.
19378      */
findViewByAccessibilityId(int accessibilityId)19379     final View findViewByAccessibilityId(int accessibilityId) {
19380         if (accessibilityId < 0) {
19381             return null;
19382         }
19383         View view = findViewByAccessibilityIdTraversal(accessibilityId);
19384         if (view != null) {
19385             return view.includeForAccessibility() ? view : null;
19386         }
19387         return null;
19388     }
19389 
19390     /**
19391      * Performs the traversal to find a view by its unuque and stable accessibility id.
19392      *
19393      * <strong>Note:</strong>This method does not stop at the root namespace
19394      * boundary since the user can touch the screen at an arbitrary location
19395      * potentially crossing the root namespace bounday which will send an
19396      * accessibility event to accessibility services and they should be able
19397      * to obtain the event source. Also accessibility ids are guaranteed to be
19398      * unique in the window.
19399      *
19400      * @param accessibilityId The accessibility id.
19401      * @return The found view.
19402      *
19403      * @hide
19404      */
findViewByAccessibilityIdTraversal(int accessibilityId)19405     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19406         if (getAccessibilityViewId() == accessibilityId) {
19407             return this;
19408         }
19409         return null;
19410     }
19411 
19412     /**
19413      * Look for a child view with the given tag.  If this view has the given
19414      * tag, return this view.
19415      *
19416      * @param tag The tag to search for, using "tag.equals(getTag())".
19417      * @return The View that has the given tag in the hierarchy or null
19418      */
findViewWithTag(Object tag)19419     public final View findViewWithTag(Object tag) {
19420         if (tag == null) {
19421             return null;
19422         }
19423         return findViewWithTagTraversal(tag);
19424     }
19425 
19426     /**
19427      * {@hide}
19428      * Look for a child view that matches the specified predicate.
19429      * If this view matches the predicate, return this view.
19430      *
19431      * @param predicate The predicate to evaluate.
19432      * @return The first view that matches the predicate or null.
19433      */
findViewByPredicate(Predicate<View> predicate)19434     public final View findViewByPredicate(Predicate<View> predicate) {
19435         return findViewByPredicateTraversal(predicate, null);
19436     }
19437 
19438     /**
19439      * {@hide}
19440      * Look for a child view that matches the specified predicate,
19441      * starting with the specified view and its descendents and then
19442      * recusively searching the ancestors and siblings of that view
19443      * until this view is reached.
19444      *
19445      * This method is useful in cases where the predicate does not match
19446      * a single unique view (perhaps multiple views use the same id)
19447      * and we are trying to find the view that is "closest" in scope to the
19448      * starting view.
19449      *
19450      * @param start The view to start from.
19451      * @param predicate The predicate to evaluate.
19452      * @return The first view that matches the predicate or null.
19453      */
findViewByPredicateInsideOut(View start, Predicate<View> predicate)19454     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19455         View childToSkip = null;
19456         for (;;) {
19457             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19458             if (view != null || start == this) {
19459                 return view;
19460             }
19461 
19462             ViewParent parent = start.getParent();
19463             if (parent == null || !(parent instanceof View)) {
19464                 return null;
19465             }
19466 
19467             childToSkip = start;
19468             start = (View) parent;
19469         }
19470     }
19471 
19472     /**
19473      * Sets the identifier for this view. The identifier does not have to be
19474      * unique in this view's hierarchy. The identifier should be a positive
19475      * number.
19476      *
19477      * @see #NO_ID
19478      * @see #getId()
19479      * @see #findViewById(int)
19480      *
19481      * @param id a number used to identify the view
19482      *
19483      * @attr ref android.R.styleable#View_id
19484      */
setId(@dRes int id)19485     public void setId(@IdRes int id) {
19486         mID = id;
19487         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19488             mID = generateViewId();
19489         }
19490     }
19491 
19492     /**
19493      * {@hide}
19494      *
19495      * @param isRoot true if the view belongs to the root namespace, false
19496      *        otherwise
19497      */
setIsRootNamespace(boolean isRoot)19498     public void setIsRootNamespace(boolean isRoot) {
19499         if (isRoot) {
19500             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19501         } else {
19502             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19503         }
19504     }
19505 
19506     /**
19507      * {@hide}
19508      *
19509      * @return true if the view belongs to the root namespace, false otherwise
19510      */
isRootNamespace()19511     public boolean isRootNamespace() {
19512         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19513     }
19514 
19515     /**
19516      * Returns this view's identifier.
19517      *
19518      * @return a positive integer used to identify the view or {@link #NO_ID}
19519      *         if the view has no ID
19520      *
19521      * @see #setId(int)
19522      * @see #findViewById(int)
19523      * @attr ref android.R.styleable#View_id
19524      */
19525     @IdRes
19526     @ViewDebug.CapturedViewProperty
getId()19527     public int getId() {
19528         return mID;
19529     }
19530 
19531     /**
19532      * Returns this view's tag.
19533      *
19534      * @return the Object stored in this view as a tag, or {@code null} if not
19535      *         set
19536      *
19537      * @see #setTag(Object)
19538      * @see #getTag(int)
19539      */
19540     @ViewDebug.ExportedProperty
getTag()19541     public Object getTag() {
19542         return mTag;
19543     }
19544 
19545     /**
19546      * Sets the tag associated with this view. A tag can be used to mark
19547      * a view in its hierarchy and does not have to be unique within the
19548      * hierarchy. Tags can also be used to store data within a view without
19549      * resorting to another data structure.
19550      *
19551      * @param tag an Object to tag the view with
19552      *
19553      * @see #getTag()
19554      * @see #setTag(int, Object)
19555      */
setTag(final Object tag)19556     public void setTag(final Object tag) {
19557         mTag = tag;
19558     }
19559 
19560     /**
19561      * Returns the tag associated with this view and the specified key.
19562      *
19563      * @param key The key identifying the tag
19564      *
19565      * @return the Object stored in this view as a tag, or {@code null} if not
19566      *         set
19567      *
19568      * @see #setTag(int, Object)
19569      * @see #getTag()
19570      */
getTag(int key)19571     public Object getTag(int key) {
19572         if (mKeyedTags != null) return mKeyedTags.get(key);
19573         return null;
19574     }
19575 
19576     /**
19577      * Sets a tag associated with this view and a key. A tag can be used
19578      * to mark a view in its hierarchy and does not have to be unique within
19579      * the hierarchy. Tags can also be used to store data within a view
19580      * without resorting to another data structure.
19581      *
19582      * The specified key should be an id declared in the resources of the
19583      * application to ensure it is unique (see the <a
19584      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19585      * Keys identified as belonging to
19586      * the Android framework or not associated with any package will cause
19587      * an {@link IllegalArgumentException} to be thrown.
19588      *
19589      * @param key The key identifying the tag
19590      * @param tag An Object to tag the view with
19591      *
19592      * @throws IllegalArgumentException If they specified key is not valid
19593      *
19594      * @see #setTag(Object)
19595      * @see #getTag(int)
19596      */
setTag(int key, final Object tag)19597     public void setTag(int key, final Object tag) {
19598         // If the package id is 0x00 or 0x01, it's either an undefined package
19599         // or a framework id
19600         if ((key >>> 24) < 2) {
19601             throw new IllegalArgumentException("The key must be an application-specific "
19602                     + "resource id.");
19603         }
19604 
19605         setKeyedTag(key, tag);
19606     }
19607 
19608     /**
19609      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19610      * framework id.
19611      *
19612      * @hide
19613      */
setTagInternal(int key, Object tag)19614     public void setTagInternal(int key, Object tag) {
19615         if ((key >>> 24) != 0x1) {
19616             throw new IllegalArgumentException("The key must be a framework-specific "
19617                     + "resource id.");
19618         }
19619 
19620         setKeyedTag(key, tag);
19621     }
19622 
setKeyedTag(int key, Object tag)19623     private void setKeyedTag(int key, Object tag) {
19624         if (mKeyedTags == null) {
19625             mKeyedTags = new SparseArray<Object>(2);
19626         }
19627 
19628         mKeyedTags.put(key, tag);
19629     }
19630 
19631     /**
19632      * Prints information about this view in the log output, with the tag
19633      * {@link #VIEW_LOG_TAG}.
19634      *
19635      * @hide
19636      */
debug()19637     public void debug() {
19638         debug(0);
19639     }
19640 
19641     /**
19642      * Prints information about this view in the log output, with the tag
19643      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19644      * indentation defined by the <code>depth</code>.
19645      *
19646      * @param depth the indentation level
19647      *
19648      * @hide
19649      */
debug(int depth)19650     protected void debug(int depth) {
19651         String output = debugIndent(depth - 1);
19652 
19653         output += "+ " + this;
19654         int id = getId();
19655         if (id != -1) {
19656             output += " (id=" + id + ")";
19657         }
19658         Object tag = getTag();
19659         if (tag != null) {
19660             output += " (tag=" + tag + ")";
19661         }
19662         Log.d(VIEW_LOG_TAG, output);
19663 
19664         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19665             output = debugIndent(depth) + " FOCUSED";
19666             Log.d(VIEW_LOG_TAG, output);
19667         }
19668 
19669         output = debugIndent(depth);
19670         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19671                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19672                 + "} ";
19673         Log.d(VIEW_LOG_TAG, output);
19674 
19675         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19676                 || mPaddingBottom != 0) {
19677             output = debugIndent(depth);
19678             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19679                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19680             Log.d(VIEW_LOG_TAG, output);
19681         }
19682 
19683         output = debugIndent(depth);
19684         output += "mMeasureWidth=" + mMeasuredWidth +
19685                 " mMeasureHeight=" + mMeasuredHeight;
19686         Log.d(VIEW_LOG_TAG, output);
19687 
19688         output = debugIndent(depth);
19689         if (mLayoutParams == null) {
19690             output += "BAD! no layout params";
19691         } else {
19692             output = mLayoutParams.debug(output);
19693         }
19694         Log.d(VIEW_LOG_TAG, output);
19695 
19696         output = debugIndent(depth);
19697         output += "flags={";
19698         output += View.printFlags(mViewFlags);
19699         output += "}";
19700         Log.d(VIEW_LOG_TAG, output);
19701 
19702         output = debugIndent(depth);
19703         output += "privateFlags={";
19704         output += View.printPrivateFlags(mPrivateFlags);
19705         output += "}";
19706         Log.d(VIEW_LOG_TAG, output);
19707     }
19708 
19709     /**
19710      * Creates a string of whitespaces used for indentation.
19711      *
19712      * @param depth the indentation level
19713      * @return a String containing (depth * 2 + 3) * 2 white spaces
19714      *
19715      * @hide
19716      */
debugIndent(int depth)19717     protected static String debugIndent(int depth) {
19718         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19719         for (int i = 0; i < (depth * 2) + 3; i++) {
19720             spaces.append(' ').append(' ');
19721         }
19722         return spaces.toString();
19723     }
19724 
19725     /**
19726      * <p>Return the offset of the widget's text baseline from the widget's top
19727      * boundary. If this widget does not support baseline alignment, this
19728      * method returns -1. </p>
19729      *
19730      * @return the offset of the baseline within the widget's bounds or -1
19731      *         if baseline alignment is not supported
19732      */
19733     @ViewDebug.ExportedProperty(category = "layout")
getBaseline()19734     public int getBaseline() {
19735         return -1;
19736     }
19737 
19738     /**
19739      * Returns whether the view hierarchy is currently undergoing a layout pass. This
19740      * information is useful to avoid situations such as calling {@link #requestLayout()} during
19741      * a layout pass.
19742      *
19743      * @return whether the view hierarchy is currently undergoing a layout pass
19744      */
isInLayout()19745     public boolean isInLayout() {
19746         ViewRootImpl viewRoot = getViewRootImpl();
19747         return (viewRoot != null && viewRoot.isInLayout());
19748     }
19749 
19750     /**
19751      * Call this when something has changed which has invalidated the
19752      * layout of this view. This will schedule a layout pass of the view
19753      * tree. This should not be called while the view hierarchy is currently in a layout
19754      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19755      * end of the current layout pass (and then layout will run again) or after the current
19756      * frame is drawn and the next layout occurs.
19757      *
19758      * <p>Subclasses which override this method should call the superclass method to
19759      * handle possible request-during-layout errors correctly.</p>
19760      */
19761     @CallSuper
requestLayout()19762     public void requestLayout() {
19763         if (mMeasureCache != null) mMeasureCache.clear();
19764 
19765         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19766             // Only trigger request-during-layout logic if this is the view requesting it,
19767             // not the views in its parent hierarchy
19768             ViewRootImpl viewRoot = getViewRootImpl();
19769             if (viewRoot != null && viewRoot.isInLayout()) {
19770                 if (!viewRoot.requestLayoutDuringLayout(this)) {
19771                     return;
19772                 }
19773             }
19774             mAttachInfo.mViewRequestingLayout = this;
19775         }
19776 
19777         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19778         mPrivateFlags |= PFLAG_INVALIDATED;
19779 
19780         if (mParent != null && !mParent.isLayoutRequested()) {
19781             mParent.requestLayout();
19782         }
19783         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19784             mAttachInfo.mViewRequestingLayout = null;
19785         }
19786     }
19787 
19788     /**
19789      * Forces this view to be laid out during the next layout pass.
19790      * This method does not call requestLayout() or forceLayout()
19791      * on the parent.
19792      */
forceLayout()19793     public void forceLayout() {
19794         if (mMeasureCache != null) mMeasureCache.clear();
19795 
19796         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19797         mPrivateFlags |= PFLAG_INVALIDATED;
19798     }
19799 
19800     /**
19801      * <p>
19802      * This is called to find out how big a view should be. The parent
19803      * supplies constraint information in the width and height parameters.
19804      * </p>
19805      *
19806      * <p>
19807      * The actual measurement work of a view is performed in
19808      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19809      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19810      * </p>
19811      *
19812      *
19813      * @param widthMeasureSpec Horizontal space requirements as imposed by the
19814      *        parent
19815      * @param heightMeasureSpec Vertical space requirements as imposed by the
19816      *        parent
19817      *
19818      * @see #onMeasure(int, int)
19819      */
measure(int widthMeasureSpec, int heightMeasureSpec)19820     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19821         boolean optical = isLayoutModeOptical(this);
19822         if (optical != isLayoutModeOptical(mParent)) {
19823             Insets insets = getOpticalInsets();
19824             int oWidth  = insets.left + insets.right;
19825             int oHeight = insets.top  + insets.bottom;
19826             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19827             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19828         }
19829 
19830         // Suppress sign extension for the low bytes
19831         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19832         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19833 
19834         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19835 
19836         // Optimize layout by avoiding an extra EXACTLY pass when the view is
19837         // already measured as the correct size. In API 23 and below, this
19838         // extra pass is required to make LinearLayout re-distribute weight.
19839         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19840                 || heightMeasureSpec != mOldHeightMeasureSpec;
19841         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19842                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19843         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19844                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19845         final boolean needsLayout = specChanged
19846                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19847 
19848         if (forceLayout || needsLayout) {
19849             // first clears the measured dimension flag
19850             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19851 
19852             resolveRtlPropertiesIfNeeded();
19853 
19854             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19855             if (cacheIndex < 0 || sIgnoreMeasureCache) {
19856                 // measure ourselves, this should set the measured dimension flag back
19857                 onMeasure(widthMeasureSpec, heightMeasureSpec);
19858                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19859             } else {
19860                 long value = mMeasureCache.valueAt(cacheIndex);
19861                 // Casting a long to int drops the high 32 bits, no mask needed
19862                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19863                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19864             }
19865 
19866             // flag not set, setMeasuredDimension() was not invoked, we raise
19867             // an exception to warn the developer
19868             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19869                 throw new IllegalStateException("View with id " + getId() + ": "
19870                         + getClass().getName() + "#onMeasure() did not set the"
19871                         + " measured dimension by calling"
19872                         + " setMeasuredDimension()");
19873             }
19874 
19875             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19876         }
19877 
19878         mOldWidthMeasureSpec = widthMeasureSpec;
19879         mOldHeightMeasureSpec = heightMeasureSpec;
19880 
19881         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19882                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19883     }
19884 
19885     /**
19886      * <p>
19887      * Measure the view and its content to determine the measured width and the
19888      * measured height. This method is invoked by {@link #measure(int, int)} and
19889      * should be overridden by subclasses to provide accurate and efficient
19890      * measurement of their contents.
19891      * </p>
19892      *
19893      * <p>
19894      * <strong>CONTRACT:</strong> When overriding this method, you
19895      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19896      * measured width and height of this view. Failure to do so will trigger an
19897      * <code>IllegalStateException</code>, thrown by
19898      * {@link #measure(int, int)}. Calling the superclass'
19899      * {@link #onMeasure(int, int)} is a valid use.
19900      * </p>
19901      *
19902      * <p>
19903      * The base class implementation of measure defaults to the background size,
19904      * unless a larger size is allowed by the MeasureSpec. Subclasses should
19905      * override {@link #onMeasure(int, int)} to provide better measurements of
19906      * their content.
19907      * </p>
19908      *
19909      * <p>
19910      * If this method is overridden, it is the subclass's responsibility to make
19911      * sure the measured height and width are at least the view's minimum height
19912      * and width ({@link #getSuggestedMinimumHeight()} and
19913      * {@link #getSuggestedMinimumWidth()}).
19914      * </p>
19915      *
19916      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19917      *                         The requirements are encoded with
19918      *                         {@link android.view.View.MeasureSpec}.
19919      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19920      *                         The requirements are encoded with
19921      *                         {@link android.view.View.MeasureSpec}.
19922      *
19923      * @see #getMeasuredWidth()
19924      * @see #getMeasuredHeight()
19925      * @see #setMeasuredDimension(int, int)
19926      * @see #getSuggestedMinimumHeight()
19927      * @see #getSuggestedMinimumWidth()
19928      * @see android.view.View.MeasureSpec#getMode(int)
19929      * @see android.view.View.MeasureSpec#getSize(int)
19930      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)19931     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19932         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19933                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19934     }
19935 
19936     /**
19937      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19938      * measured width and measured height. Failing to do so will trigger an
19939      * exception at measurement time.</p>
19940      *
19941      * @param measuredWidth The measured width of this view.  May be a complex
19942      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19943      * {@link #MEASURED_STATE_TOO_SMALL}.
19944      * @param measuredHeight The measured height of this view.  May be a complex
19945      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19946      * {@link #MEASURED_STATE_TOO_SMALL}.
19947      */
setMeasuredDimension(int measuredWidth, int measuredHeight)19948     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19949         boolean optical = isLayoutModeOptical(this);
19950         if (optical != isLayoutModeOptical(mParent)) {
19951             Insets insets = getOpticalInsets();
19952             int opticalWidth  = insets.left + insets.right;
19953             int opticalHeight = insets.top  + insets.bottom;
19954 
19955             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19956             measuredHeight += optical ? opticalHeight : -opticalHeight;
19957         }
19958         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19959     }
19960 
19961     /**
19962      * Sets the measured dimension without extra processing for things like optical bounds.
19963      * Useful for reapplying consistent values that have already been cooked with adjustments
19964      * for optical bounds, etc. such as those from the measurement cache.
19965      *
19966      * @param measuredWidth The measured width of this view.  May be a complex
19967      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19968      * {@link #MEASURED_STATE_TOO_SMALL}.
19969      * @param measuredHeight The measured height of this view.  May be a complex
19970      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19971      * {@link #MEASURED_STATE_TOO_SMALL}.
19972      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)19973     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19974         mMeasuredWidth = measuredWidth;
19975         mMeasuredHeight = measuredHeight;
19976 
19977         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19978     }
19979 
19980     /**
19981      * Merge two states as returned by {@link #getMeasuredState()}.
19982      * @param curState The current state as returned from a view or the result
19983      * of combining multiple views.
19984      * @param newState The new view state to combine.
19985      * @return Returns a new integer reflecting the combination of the two
19986      * states.
19987      */
combineMeasuredStates(int curState, int newState)19988     public static int combineMeasuredStates(int curState, int newState) {
19989         return curState | newState;
19990     }
19991 
19992     /**
19993      * Version of {@link #resolveSizeAndState(int, int, int)}
19994      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19995      */
resolveSize(int size, int measureSpec)19996     public static int resolveSize(int size, int measureSpec) {
19997         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19998     }
19999 
20000     /**
20001      * Utility to reconcile a desired size and state, with constraints imposed
20002      * by a MeasureSpec. Will take the desired size, unless a different size
20003      * is imposed by the constraints. The returned value is a compound integer,
20004      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20005      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20006      * resulting size is smaller than the size the view wants to be.
20007      *
20008      * @param size How big the view wants to be.
20009      * @param measureSpec Constraints imposed by the parent.
20010      * @param childMeasuredState Size information bit mask for the view's
20011      *                           children.
20012      * @return Size information bit mask as defined by
20013      *         {@link #MEASURED_SIZE_MASK} and
20014      *         {@link #MEASURED_STATE_TOO_SMALL}.
20015      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)20016     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20017         final int specMode = MeasureSpec.getMode(measureSpec);
20018         final int specSize = MeasureSpec.getSize(measureSpec);
20019         final int result;
20020         switch (specMode) {
20021             case MeasureSpec.AT_MOST:
20022                 if (specSize < size) {
20023                     result = specSize | MEASURED_STATE_TOO_SMALL;
20024                 } else {
20025                     result = size;
20026                 }
20027                 break;
20028             case MeasureSpec.EXACTLY:
20029                 result = specSize;
20030                 break;
20031             case MeasureSpec.UNSPECIFIED:
20032             default:
20033                 result = size;
20034         }
20035         return result | (childMeasuredState & MEASURED_STATE_MASK);
20036     }
20037 
20038     /**
20039      * Utility to return a default size. Uses the supplied size if the
20040      * MeasureSpec imposed no constraints. Will get larger if allowed
20041      * by the MeasureSpec.
20042      *
20043      * @param size Default size for this view
20044      * @param measureSpec Constraints imposed by the parent
20045      * @return The size this view should be.
20046      */
getDefaultSize(int size, int measureSpec)20047     public static int getDefaultSize(int size, int measureSpec) {
20048         int result = size;
20049         int specMode = MeasureSpec.getMode(measureSpec);
20050         int specSize = MeasureSpec.getSize(measureSpec);
20051 
20052         switch (specMode) {
20053         case MeasureSpec.UNSPECIFIED:
20054             result = size;
20055             break;
20056         case MeasureSpec.AT_MOST:
20057         case MeasureSpec.EXACTLY:
20058             result = specSize;
20059             break;
20060         }
20061         return result;
20062     }
20063 
20064     /**
20065      * Returns the suggested minimum height that the view should use. This
20066      * returns the maximum of the view's minimum height
20067      * and the background's minimum height
20068      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20069      * <p>
20070      * When being used in {@link #onMeasure(int, int)}, the caller should still
20071      * ensure the returned height is within the requirements of the parent.
20072      *
20073      * @return The suggested minimum height of the view.
20074      */
getSuggestedMinimumHeight()20075     protected int getSuggestedMinimumHeight() {
20076         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20077 
20078     }
20079 
20080     /**
20081      * Returns the suggested minimum width that the view should use. This
20082      * returns the maximum of the view's minimum width
20083      * and the background's minimum width
20084      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20085      * <p>
20086      * When being used in {@link #onMeasure(int, int)}, the caller should still
20087      * ensure the returned width is within the requirements of the parent.
20088      *
20089      * @return The suggested minimum width of the view.
20090      */
getSuggestedMinimumWidth()20091     protected int getSuggestedMinimumWidth() {
20092         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20093     }
20094 
20095     /**
20096      * Returns the minimum height of the view.
20097      *
20098      * @return the minimum height the view will try to be.
20099      *
20100      * @see #setMinimumHeight(int)
20101      *
20102      * @attr ref android.R.styleable#View_minHeight
20103      */
getMinimumHeight()20104     public int getMinimumHeight() {
20105         return mMinHeight;
20106     }
20107 
20108     /**
20109      * Sets the minimum height of the view. It is not guaranteed the view will
20110      * be able to achieve this minimum height (for example, if its parent layout
20111      * constrains it with less available height).
20112      *
20113      * @param minHeight The minimum height the view will try to be.
20114      *
20115      * @see #getMinimumHeight()
20116      *
20117      * @attr ref android.R.styleable#View_minHeight
20118      */
20119     @RemotableViewMethod
setMinimumHeight(int minHeight)20120     public void setMinimumHeight(int minHeight) {
20121         mMinHeight = minHeight;
20122         requestLayout();
20123     }
20124 
20125     /**
20126      * Returns the minimum width of the view.
20127      *
20128      * @return the minimum width the view will try to be.
20129      *
20130      * @see #setMinimumWidth(int)
20131      *
20132      * @attr ref android.R.styleable#View_minWidth
20133      */
getMinimumWidth()20134     public int getMinimumWidth() {
20135         return mMinWidth;
20136     }
20137 
20138     /**
20139      * Sets the minimum width of the view. It is not guaranteed the view will
20140      * be able to achieve this minimum width (for example, if its parent layout
20141      * constrains it with less available width).
20142      *
20143      * @param minWidth The minimum width the view will try to be.
20144      *
20145      * @see #getMinimumWidth()
20146      *
20147      * @attr ref android.R.styleable#View_minWidth
20148      */
setMinimumWidth(int minWidth)20149     public void setMinimumWidth(int minWidth) {
20150         mMinWidth = minWidth;
20151         requestLayout();
20152 
20153     }
20154 
20155     /**
20156      * Get the animation currently associated with this view.
20157      *
20158      * @return The animation that is currently playing or
20159      *         scheduled to play for this view.
20160      */
getAnimation()20161     public Animation getAnimation() {
20162         return mCurrentAnimation;
20163     }
20164 
20165     /**
20166      * Start the specified animation now.
20167      *
20168      * @param animation the animation to start now
20169      */
startAnimation(Animation animation)20170     public void startAnimation(Animation animation) {
20171         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20172         setAnimation(animation);
20173         invalidateParentCaches();
20174         invalidate(true);
20175     }
20176 
20177     /**
20178      * Cancels any animations for this view.
20179      */
clearAnimation()20180     public void clearAnimation() {
20181         if (mCurrentAnimation != null) {
20182             mCurrentAnimation.detach();
20183         }
20184         mCurrentAnimation = null;
20185         invalidateParentIfNeeded();
20186     }
20187 
20188     /**
20189      * Sets the next animation to play for this view.
20190      * If you want the animation to play immediately, use
20191      * {@link #startAnimation(android.view.animation.Animation)} instead.
20192      * This method provides allows fine-grained
20193      * control over the start time and invalidation, but you
20194      * must make sure that 1) the animation has a start time set, and
20195      * 2) the view's parent (which controls animations on its children)
20196      * will be invalidated when the animation is supposed to
20197      * start.
20198      *
20199      * @param animation The next animation, or null.
20200      */
setAnimation(Animation animation)20201     public void setAnimation(Animation animation) {
20202         mCurrentAnimation = animation;
20203 
20204         if (animation != null) {
20205             // If the screen is off assume the animation start time is now instead of
20206             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20207             // would cause the animation to start when the screen turns back on
20208             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20209                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20210                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20211             }
20212             animation.reset();
20213         }
20214     }
20215 
20216     /**
20217      * Invoked by a parent ViewGroup to notify the start of the animation
20218      * currently associated with this view. If you override this method,
20219      * always call super.onAnimationStart();
20220      *
20221      * @see #setAnimation(android.view.animation.Animation)
20222      * @see #getAnimation()
20223      */
20224     @CallSuper
onAnimationStart()20225     protected void onAnimationStart() {
20226         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20227     }
20228 
20229     /**
20230      * Invoked by a parent ViewGroup to notify the end of the animation
20231      * currently associated with this view. If you override this method,
20232      * always call super.onAnimationEnd();
20233      *
20234      * @see #setAnimation(android.view.animation.Animation)
20235      * @see #getAnimation()
20236      */
20237     @CallSuper
onAnimationEnd()20238     protected void onAnimationEnd() {
20239         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20240     }
20241 
20242     /**
20243      * Invoked if there is a Transform that involves alpha. Subclass that can
20244      * draw themselves with the specified alpha should return true, and then
20245      * respect that alpha when their onDraw() is called. If this returns false
20246      * then the view may be redirected to draw into an offscreen buffer to
20247      * fulfill the request, which will look fine, but may be slower than if the
20248      * subclass handles it internally. The default implementation returns false.
20249      *
20250      * @param alpha The alpha (0..255) to apply to the view's drawing
20251      * @return true if the view can draw with the specified alpha.
20252      */
onSetAlpha(int alpha)20253     protected boolean onSetAlpha(int alpha) {
20254         return false;
20255     }
20256 
20257     /**
20258      * This is used by the RootView to perform an optimization when
20259      * the view hierarchy contains one or several SurfaceView.
20260      * SurfaceView is always considered transparent, but its children are not,
20261      * therefore all View objects remove themselves from the global transparent
20262      * region (passed as a parameter to this function).
20263      *
20264      * @param region The transparent region for this ViewAncestor (window).
20265      *
20266      * @return Returns true if the effective visibility of the view at this
20267      * point is opaque, regardless of the transparent region; returns false
20268      * if it is possible for underlying windows to be seen behind the view.
20269      *
20270      * {@hide}
20271      */
gatherTransparentRegion(Region region)20272     public boolean gatherTransparentRegion(Region region) {
20273         final AttachInfo attachInfo = mAttachInfo;
20274         if (region != null && attachInfo != null) {
20275             final int pflags = mPrivateFlags;
20276             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20277                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20278                 // remove it from the transparent region.
20279                 final int[] location = attachInfo.mTransparentLocation;
20280                 getLocationInWindow(location);
20281                 // When a view has Z value, then it will be better to leave some area below the view
20282                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
20283                 // the bottom part needs more offset than the left, top and right parts due to the
20284                 // spot light effects.
20285                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
20286                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
20287                         location[0] + mRight - mLeft + shadowOffset,
20288                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
20289             } else {
20290                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20291                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20292                     // the background drawable's non-transparent parts from this transparent region.
20293                     applyDrawableToTransparentRegion(mBackground, region);
20294                 }
20295                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20296                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20297                     // Similarly, we remove the foreground drawable's non-transparent parts.
20298                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20299                 }
20300             }
20301         }
20302         return true;
20303     }
20304 
20305     /**
20306      * Play a sound effect for this view.
20307      *
20308      * <p>The framework will play sound effects for some built in actions, such as
20309      * clicking, but you may wish to play these effects in your widget,
20310      * for instance, for internal navigation.
20311      *
20312      * <p>The sound effect will only be played if sound effects are enabled by the user, and
20313      * {@link #isSoundEffectsEnabled()} is true.
20314      *
20315      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20316      */
playSoundEffect(int soundConstant)20317     public void playSoundEffect(int soundConstant) {
20318         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20319             return;
20320         }
20321         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20322     }
20323 
20324     /**
20325      * BZZZTT!!1!
20326      *
20327      * <p>Provide haptic feedback to the user for this view.
20328      *
20329      * <p>The framework will provide haptic feedback for some built in actions,
20330      * such as long presses, but you may wish to provide feedback for your
20331      * own widget.
20332      *
20333      * <p>The feedback will only be performed if
20334      * {@link #isHapticFeedbackEnabled()} is true.
20335      *
20336      * @param feedbackConstant One of the constants defined in
20337      * {@link HapticFeedbackConstants}
20338      */
performHapticFeedback(int feedbackConstant)20339     public boolean performHapticFeedback(int feedbackConstant) {
20340         return performHapticFeedback(feedbackConstant, 0);
20341     }
20342 
20343     /**
20344      * BZZZTT!!1!
20345      *
20346      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20347      *
20348      * @param feedbackConstant One of the constants defined in
20349      * {@link HapticFeedbackConstants}
20350      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20351      */
performHapticFeedback(int feedbackConstant, int flags)20352     public boolean performHapticFeedback(int feedbackConstant, int flags) {
20353         if (mAttachInfo == null) {
20354             return false;
20355         }
20356         //noinspection SimplifiableIfStatement
20357         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20358                 && !isHapticFeedbackEnabled()) {
20359             return false;
20360         }
20361         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20362                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20363     }
20364 
20365     /**
20366      * Request that the visibility of the status bar or other screen/window
20367      * decorations be changed.
20368      *
20369      * <p>This method is used to put the over device UI into temporary modes
20370      * where the user's attention is focused more on the application content,
20371      * by dimming or hiding surrounding system affordances.  This is typically
20372      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20373      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20374      * to be placed behind the action bar (and with these flags other system
20375      * affordances) so that smooth transitions between hiding and showing them
20376      * can be done.
20377      *
20378      * <p>Two representative examples of the use of system UI visibility is
20379      * implementing a content browsing application (like a magazine reader)
20380      * and a video playing application.
20381      *
20382      * <p>The first code shows a typical implementation of a View in a content
20383      * browsing application.  In this implementation, the application goes
20384      * into a content-oriented mode by hiding the status bar and action bar,
20385      * and putting the navigation elements into lights out mode.  The user can
20386      * then interact with content while in this mode.  Such an application should
20387      * provide an easy way for the user to toggle out of the mode (such as to
20388      * check information in the status bar or access notifications).  In the
20389      * implementation here, this is done simply by tapping on the content.
20390      *
20391      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20392      *      content}
20393      *
20394      * <p>This second code sample shows a typical implementation of a View
20395      * in a video playing application.  In this situation, while the video is
20396      * playing the application would like to go into a complete full-screen mode,
20397      * to use as much of the display as possible for the video.  When in this state
20398      * the user can not interact with the application; the system intercepts
20399      * touching on the screen to pop the UI out of full screen mode.  See
20400      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20401      *
20402      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20403      *      content}
20404      *
20405      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20406      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20407      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20408      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20409      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20410      */
setSystemUiVisibility(int visibility)20411     public void setSystemUiVisibility(int visibility) {
20412         if (visibility != mSystemUiVisibility) {
20413             mSystemUiVisibility = visibility;
20414             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20415                 mParent.recomputeViewAttributes(this);
20416             }
20417         }
20418     }
20419 
20420     /**
20421      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20422      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20423      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20424      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20425      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20426      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20427      */
getSystemUiVisibility()20428     public int getSystemUiVisibility() {
20429         return mSystemUiVisibility;
20430     }
20431 
20432     /**
20433      * Returns the current system UI visibility that is currently set for
20434      * the entire window.  This is the combination of the
20435      * {@link #setSystemUiVisibility(int)} values supplied by all of the
20436      * views in the window.
20437      */
getWindowSystemUiVisibility()20438     public int getWindowSystemUiVisibility() {
20439         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20440     }
20441 
20442     /**
20443      * Override to find out when the window's requested system UI visibility
20444      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20445      * This is different from the callbacks received through
20446      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20447      * in that this is only telling you about the local request of the window,
20448      * not the actual values applied by the system.
20449      */
onWindowSystemUiVisibilityChanged(int visible)20450     public void onWindowSystemUiVisibilityChanged(int visible) {
20451     }
20452 
20453     /**
20454      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20455      * the view hierarchy.
20456      */
dispatchWindowSystemUiVisiblityChanged(int visible)20457     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20458         onWindowSystemUiVisibilityChanged(visible);
20459     }
20460 
20461     /**
20462      * Set a listener to receive callbacks when the visibility of the system bar changes.
20463      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20464      */
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)20465     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20466         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20467         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20468             mParent.recomputeViewAttributes(this);
20469         }
20470     }
20471 
20472     /**
20473      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20474      * the view hierarchy.
20475      */
dispatchSystemUiVisibilityChanged(int visibility)20476     public void dispatchSystemUiVisibilityChanged(int visibility) {
20477         ListenerInfo li = mListenerInfo;
20478         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20479             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20480                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20481         }
20482     }
20483 
updateLocalSystemUiVisibility(int localValue, int localChanges)20484     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20485         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20486         if (val != mSystemUiVisibility) {
20487             setSystemUiVisibility(val);
20488             return true;
20489         }
20490         return false;
20491     }
20492 
20493     /** @hide */
setDisabledSystemUiVisibility(int flags)20494     public void setDisabledSystemUiVisibility(int flags) {
20495         if (mAttachInfo != null) {
20496             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20497                 mAttachInfo.mDisabledSystemUiVisibility = flags;
20498                 if (mParent != null) {
20499                     mParent.recomputeViewAttributes(this);
20500                 }
20501             }
20502         }
20503     }
20504 
20505     /**
20506      * Creates an image that the system displays during the drag and drop
20507      * operation. This is called a &quot;drag shadow&quot;. The default implementation
20508      * for a DragShadowBuilder based on a View returns an image that has exactly the same
20509      * appearance as the given View. The default also positions the center of the drag shadow
20510      * directly under the touch point. If no View is provided (the constructor with no parameters
20511      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20512      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20513      * default is an invisible drag shadow.
20514      * <p>
20515      * You are not required to use the View you provide to the constructor as the basis of the
20516      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20517      * anything you want as the drag shadow.
20518      * </p>
20519      * <p>
20520      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20521      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20522      *  size and position of the drag shadow. It uses this data to construct a
20523      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20524      *  so that your application can draw the shadow image in the Canvas.
20525      * </p>
20526      *
20527      * <div class="special reference">
20528      * <h3>Developer Guides</h3>
20529      * <p>For a guide to implementing drag and drop features, read the
20530      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20531      * </div>
20532      */
20533     public static class DragShadowBuilder {
20534         private final WeakReference<View> mView;
20535 
20536         /**
20537          * Constructs a shadow image builder based on a View. By default, the resulting drag
20538          * shadow will have the same appearance and dimensions as the View, with the touch point
20539          * over the center of the View.
20540          * @param view A View. Any View in scope can be used.
20541          */
DragShadowBuilder(View view)20542         public DragShadowBuilder(View view) {
20543             mView = new WeakReference<View>(view);
20544         }
20545 
20546         /**
20547          * Construct a shadow builder object with no associated View.  This
20548          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20549          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20550          * to supply the drag shadow's dimensions and appearance without
20551          * reference to any View object. If they are not overridden, then the result is an
20552          * invisible drag shadow.
20553          */
DragShadowBuilder()20554         public DragShadowBuilder() {
20555             mView = new WeakReference<View>(null);
20556         }
20557 
20558         /**
20559          * Returns the View object that had been passed to the
20560          * {@link #View.DragShadowBuilder(View)}
20561          * constructor.  If that View parameter was {@code null} or if the
20562          * {@link #View.DragShadowBuilder()}
20563          * constructor was used to instantiate the builder object, this method will return
20564          * null.
20565          *
20566          * @return The View object associate with this builder object.
20567          */
20568         @SuppressWarnings({"JavadocReference"})
getView()20569         final public View getView() {
20570             return mView.get();
20571         }
20572 
20573         /**
20574          * Provides the metrics for the shadow image. These include the dimensions of
20575          * the shadow image, and the point within that shadow that should
20576          * be centered under the touch location while dragging.
20577          * <p>
20578          * The default implementation sets the dimensions of the shadow to be the
20579          * same as the dimensions of the View itself and centers the shadow under
20580          * the touch point.
20581          * </p>
20582          *
20583          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20584          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20585          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20586          * image.
20587          *
20588          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20589          * shadow image that should be underneath the touch point during the drag and drop
20590          * operation. Your application must set {@link android.graphics.Point#x} to the
20591          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20592          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)20593         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20594             final View view = mView.get();
20595             if (view != null) {
20596                 outShadowSize.set(view.getWidth(), view.getHeight());
20597                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20598             } else {
20599                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20600             }
20601         }
20602 
20603         /**
20604          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20605          * based on the dimensions it received from the
20606          * {@link #onProvideShadowMetrics(Point, Point)} callback.
20607          *
20608          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20609          */
onDrawShadow(Canvas canvas)20610         public void onDrawShadow(Canvas canvas) {
20611             final View view = mView.get();
20612             if (view != null) {
20613                 view.draw(canvas);
20614             } else {
20615                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20616             }
20617         }
20618     }
20619 
20620     /**
20621      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20622      * startDragAndDrop()} for newer platform versions.
20623      */
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20624     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20625                                    Object myLocalState, int flags) {
20626         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20627     }
20628 
20629     /**
20630      * Starts a drag and drop operation. When your application calls this method, it passes a
20631      * {@link android.view.View.DragShadowBuilder} object to the system. The
20632      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20633      * to get metrics for the drag shadow, and then calls the object's
20634      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20635      * <p>
20636      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
20637      *  drag events to all the View objects in your application that are currently visible. It does
20638      *  this either by calling the View object's drag listener (an implementation of
20639      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20640      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20641      *  Both are passed a {@link android.view.DragEvent} object that has a
20642      *  {@link android.view.DragEvent#getAction()} value of
20643      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20644      * </p>
20645      * <p>
20646      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20647      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20648      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20649      * to the View the user selected for dragging.
20650      * </p>
20651      * @param data A {@link android.content.ClipData} object pointing to the data to be
20652      * transferred by the drag and drop operation.
20653      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20654      * drag shadow.
20655      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20656      * drop operation. When dispatching drag events to views in the same activity this object
20657      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
20658      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
20659      * will return null).
20660      * <p>
20661      * myLocalState is a lightweight mechanism for the sending information from the dragged View
20662      * to the target Views. For example, it can contain flags that differentiate between a
20663      * a copy operation and a move operation.
20664      * </p>
20665      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20666      * flags, or any combination of the following:
20667      *     <ul>
20668      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
20669      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20670      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20671      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20672      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20673      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
20674      *     </ul>
20675      * @return {@code true} if the method completes successfully, or
20676      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20677      * do a drag, and so no drag operation is in progress.
20678      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20679     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20680             Object myLocalState, int flags) {
20681         if (ViewDebug.DEBUG_DRAG) {
20682             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20683         }
20684         if (mAttachInfo == null) {
20685             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20686             return false;
20687         }
20688         boolean okay = false;
20689 
20690         Point shadowSize = new Point();
20691         Point shadowTouchPoint = new Point();
20692         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20693 
20694         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20695                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20696             throw new IllegalStateException("Drag shadow dimensions must not be negative");
20697         }
20698 
20699         if (ViewDebug.DEBUG_DRAG) {
20700             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20701                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20702         }
20703         if (mAttachInfo.mDragSurface != null) {
20704             mAttachInfo.mDragSurface.release();
20705         }
20706         mAttachInfo.mDragSurface = new Surface();
20707         try {
20708             mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20709                     flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20710             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20711                     + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20712             if (mAttachInfo.mDragToken != null) {
20713                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20714                 try {
20715                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20716                     shadowBuilder.onDrawShadow(canvas);
20717                 } finally {
20718                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20719                 }
20720 
20721                 final ViewRootImpl root = getViewRootImpl();
20722 
20723                 // Cache the local state object for delivery with DragEvents
20724                 root.setLocalDragState(myLocalState);
20725 
20726                 // repurpose 'shadowSize' for the last touch point
20727                 root.getLastTouchPoint(shadowSize);
20728 
20729                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20730                         root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20731                         shadowTouchPoint.x, shadowTouchPoint.y, data);
20732                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20733             }
20734         } catch (Exception e) {
20735             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20736             mAttachInfo.mDragSurface.destroy();
20737             mAttachInfo.mDragSurface = null;
20738         }
20739 
20740         return okay;
20741     }
20742 
20743     /**
20744      * Cancels an ongoing drag and drop operation.
20745      * <p>
20746      * A {@link android.view.DragEvent} object with
20747      * {@link android.view.DragEvent#getAction()} value of
20748      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20749      * {@link android.view.DragEvent#getResult()} value of {@code false}
20750      * will be sent to every
20751      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20752      * even if they are not currently visible.
20753      * </p>
20754      * <p>
20755      * This method can be called on any View in the same window as the View on which
20756      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20757      * was called.
20758      * </p>
20759      */
cancelDragAndDrop()20760     public final void cancelDragAndDrop() {
20761         if (ViewDebug.DEBUG_DRAG) {
20762             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20763         }
20764         if (mAttachInfo == null) {
20765             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20766             return;
20767         }
20768         if (mAttachInfo.mDragToken != null) {
20769             try {
20770                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20771             } catch (Exception e) {
20772                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20773             }
20774             mAttachInfo.mDragToken = null;
20775         } else {
20776             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20777         }
20778     }
20779 
20780     /**
20781      * Updates the drag shadow for the ongoing drag and drop operation.
20782      *
20783      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20784      * new drag shadow.
20785      */
updateDragShadow(DragShadowBuilder shadowBuilder)20786     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20787         if (ViewDebug.DEBUG_DRAG) {
20788             Log.d(VIEW_LOG_TAG, "updateDragShadow");
20789         }
20790         if (mAttachInfo == null) {
20791             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20792             return;
20793         }
20794         if (mAttachInfo.mDragToken != null) {
20795             try {
20796                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20797                 try {
20798                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20799                     shadowBuilder.onDrawShadow(canvas);
20800                 } finally {
20801                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20802                 }
20803             } catch (Exception e) {
20804                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20805             }
20806         } else {
20807             Log.e(VIEW_LOG_TAG, "No active drag");
20808         }
20809     }
20810 
20811     /**
20812      * Starts a move from {startX, startY}, the amount of the movement will be the offset
20813      * between {startX, startY} and the new cursor positon.
20814      * @param startX horizontal coordinate where the move started.
20815      * @param startY vertical coordinate where the move started.
20816      * @return whether moving was started successfully.
20817      * @hide
20818      */
startMovingTask(float startX, float startY)20819     public final boolean startMovingTask(float startX, float startY) {
20820         if (ViewDebug.DEBUG_POSITIONING) {
20821             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20822         }
20823         try {
20824             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20825         } catch (RemoteException e) {
20826             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20827         }
20828         return false;
20829     }
20830 
20831     /**
20832      * Handles drag events sent by the system following a call to
20833      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20834      * startDragAndDrop()}.
20835      *<p>
20836      * When the system calls this method, it passes a
20837      * {@link android.view.DragEvent} object. A call to
20838      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20839      * in DragEvent. The method uses these to determine what is happening in the drag and drop
20840      * operation.
20841      * @param event The {@link android.view.DragEvent} sent by the system.
20842      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20843      * in DragEvent, indicating the type of drag event represented by this object.
20844      * @return {@code true} if the method was successful, otherwise {@code false}.
20845      * <p>
20846      *  The method should return {@code true} in response to an action type of
20847      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20848      *  operation.
20849      * </p>
20850      * <p>
20851      *  The method should also return {@code true} in response to an action type of
20852      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20853      *  {@code false} if it didn't.
20854      * </p>
20855      */
onDragEvent(DragEvent event)20856     public boolean onDragEvent(DragEvent event) {
20857         return false;
20858     }
20859 
20860     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)20861     boolean dispatchDragEnterExitInPreN(DragEvent event) {
20862         return callDragEventHandler(event);
20863     }
20864 
20865     /**
20866      * Detects if this View is enabled and has a drag event listener.
20867      * If both are true, then it calls the drag event listener with the
20868      * {@link android.view.DragEvent} it received. If the drag event listener returns
20869      * {@code true}, then dispatchDragEvent() returns {@code true}.
20870      * <p>
20871      * For all other cases, the method calls the
20872      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20873      * method and returns its result.
20874      * </p>
20875      * <p>
20876      * This ensures that a drag event is always consumed, even if the View does not have a drag
20877      * event listener. However, if the View has a listener and the listener returns true, then
20878      * onDragEvent() is not called.
20879      * </p>
20880      */
dispatchDragEvent(DragEvent event)20881     public boolean dispatchDragEvent(DragEvent event) {
20882         event.mEventHandlerWasCalled = true;
20883         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
20884             event.mAction == DragEvent.ACTION_DROP) {
20885             // About to deliver an event with coordinates to this view. Notify that now this view
20886             // has drag focus. This will send exit/enter events as needed.
20887             getViewRootImpl().setDragFocus(this, event);
20888         }
20889         return callDragEventHandler(event);
20890     }
20891 
callDragEventHandler(DragEvent event)20892     final boolean callDragEventHandler(DragEvent event) {
20893         final boolean result;
20894 
20895         ListenerInfo li = mListenerInfo;
20896         //noinspection SimplifiableIfStatement
20897         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20898                 && li.mOnDragListener.onDrag(this, event)) {
20899             result = true;
20900         } else {
20901             result = onDragEvent(event);
20902         }
20903 
20904         switch (event.mAction) {
20905             case DragEvent.ACTION_DRAG_ENTERED: {
20906                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
20907                 refreshDrawableState();
20908             } break;
20909             case DragEvent.ACTION_DRAG_EXITED: {
20910                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
20911                 refreshDrawableState();
20912             } break;
20913             case DragEvent.ACTION_DRAG_ENDED: {
20914                 mPrivateFlags2 &= ~View.DRAG_MASK;
20915                 refreshDrawableState();
20916             } break;
20917         }
20918 
20919         return result;
20920     }
20921 
canAcceptDrag()20922     boolean canAcceptDrag() {
20923         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20924     }
20925 
20926     /**
20927      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20928      * it is ever exposed at all.
20929      * @hide
20930      */
onCloseSystemDialogs(String reason)20931     public void onCloseSystemDialogs(String reason) {
20932     }
20933 
20934     /**
20935      * Given a Drawable whose bounds have been set to draw into this view,
20936      * update a Region being computed for
20937      * {@link #gatherTransparentRegion(android.graphics.Region)} so
20938      * that any non-transparent parts of the Drawable are removed from the
20939      * given transparent region.
20940      *
20941      * @param dr The Drawable whose transparency is to be applied to the region.
20942      * @param region A Region holding the current transparency information,
20943      * where any parts of the region that are set are considered to be
20944      * transparent.  On return, this region will be modified to have the
20945      * transparency information reduced by the corresponding parts of the
20946      * Drawable that are not transparent.
20947      * {@hide}
20948      */
applyDrawableToTransparentRegion(Drawable dr, Region region)20949     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20950         if (DBG) {
20951             Log.i("View", "Getting transparent region for: " + this);
20952         }
20953         final Region r = dr.getTransparentRegion();
20954         final Rect db = dr.getBounds();
20955         final AttachInfo attachInfo = mAttachInfo;
20956         if (r != null && attachInfo != null) {
20957             final int w = getRight()-getLeft();
20958             final int h = getBottom()-getTop();
20959             if (db.left > 0) {
20960                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20961                 r.op(0, 0, db.left, h, Region.Op.UNION);
20962             }
20963             if (db.right < w) {
20964                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20965                 r.op(db.right, 0, w, h, Region.Op.UNION);
20966             }
20967             if (db.top > 0) {
20968                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20969                 r.op(0, 0, w, db.top, Region.Op.UNION);
20970             }
20971             if (db.bottom < h) {
20972                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20973                 r.op(0, db.bottom, w, h, Region.Op.UNION);
20974             }
20975             final int[] location = attachInfo.mTransparentLocation;
20976             getLocationInWindow(location);
20977             r.translate(location[0], location[1]);
20978             region.op(r, Region.Op.INTERSECT);
20979         } else {
20980             region.op(db, Region.Op.DIFFERENCE);
20981         }
20982     }
20983 
checkForLongClick(int delayOffset, float x, float y)20984     private void checkForLongClick(int delayOffset, float x, float y) {
20985         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20986             mHasPerformedLongPress = false;
20987 
20988             if (mPendingCheckForLongPress == null) {
20989                 mPendingCheckForLongPress = new CheckForLongPress();
20990             }
20991             mPendingCheckForLongPress.setAnchor(x, y);
20992             mPendingCheckForLongPress.rememberWindowAttachCount();
20993             postDelayed(mPendingCheckForLongPress,
20994                     ViewConfiguration.getLongPressTimeout() - delayOffset);
20995         }
20996     }
20997 
20998     /**
20999      * Inflate a view from an XML resource.  This convenience method wraps the {@link
21000      * LayoutInflater} class, which provides a full range of options for view inflation.
21001      *
21002      * @param context The Context object for your activity or application.
21003      * @param resource The resource ID to inflate
21004      * @param root A view group that will be the parent.  Used to properly inflate the
21005      * layout_* parameters.
21006      * @see LayoutInflater
21007      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)21008     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
21009         LayoutInflater factory = LayoutInflater.from(context);
21010         return factory.inflate(resource, root);
21011     }
21012 
21013     /**
21014      * Scroll the view with standard behavior for scrolling beyond the normal
21015      * content boundaries. Views that call this method should override
21016      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
21017      * results of an over-scroll operation.
21018      *
21019      * Views can use this method to handle any touch or fling-based scrolling.
21020      *
21021      * @param deltaX Change in X in pixels
21022      * @param deltaY Change in Y in pixels
21023      * @param scrollX Current X scroll value in pixels before applying deltaX
21024      * @param scrollY Current Y scroll value in pixels before applying deltaY
21025      * @param scrollRangeX Maximum content scroll range along the X axis
21026      * @param scrollRangeY Maximum content scroll range along the Y axis
21027      * @param maxOverScrollX Number of pixels to overscroll by in either direction
21028      *          along the X axis.
21029      * @param maxOverScrollY Number of pixels to overscroll by in either direction
21030      *          along the Y axis.
21031      * @param isTouchEvent true if this scroll operation is the result of a touch event.
21032      * @return true if scrolling was clamped to an over-scroll boundary along either
21033      *          axis, false otherwise.
21034      */
21035     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)21036     protected boolean overScrollBy(int deltaX, int deltaY,
21037             int scrollX, int scrollY,
21038             int scrollRangeX, int scrollRangeY,
21039             int maxOverScrollX, int maxOverScrollY,
21040             boolean isTouchEvent) {
21041         final int overScrollMode = mOverScrollMode;
21042         final boolean canScrollHorizontal =
21043                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21044         final boolean canScrollVertical =
21045                 computeVerticalScrollRange() > computeVerticalScrollExtent();
21046         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21047                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21048         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21049                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21050 
21051         int newScrollX = scrollX + deltaX;
21052         if (!overScrollHorizontal) {
21053             maxOverScrollX = 0;
21054         }
21055 
21056         int newScrollY = scrollY + deltaY;
21057         if (!overScrollVertical) {
21058             maxOverScrollY = 0;
21059         }
21060 
21061         // Clamp values if at the limits and record
21062         final int left = -maxOverScrollX;
21063         final int right = maxOverScrollX + scrollRangeX;
21064         final int top = -maxOverScrollY;
21065         final int bottom = maxOverScrollY + scrollRangeY;
21066 
21067         boolean clampedX = false;
21068         if (newScrollX > right) {
21069             newScrollX = right;
21070             clampedX = true;
21071         } else if (newScrollX < left) {
21072             newScrollX = left;
21073             clampedX = true;
21074         }
21075 
21076         boolean clampedY = false;
21077         if (newScrollY > bottom) {
21078             newScrollY = bottom;
21079             clampedY = true;
21080         } else if (newScrollY < top) {
21081             newScrollY = top;
21082             clampedY = true;
21083         }
21084 
21085         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21086 
21087         return clampedX || clampedY;
21088     }
21089 
21090     /**
21091      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21092      * respond to the results of an over-scroll operation.
21093      *
21094      * @param scrollX New X scroll value in pixels
21095      * @param scrollY New Y scroll value in pixels
21096      * @param clampedX True if scrollX was clamped to an over-scroll boundary
21097      * @param clampedY True if scrollY was clamped to an over-scroll boundary
21098      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)21099     protected void onOverScrolled(int scrollX, int scrollY,
21100             boolean clampedX, boolean clampedY) {
21101         // Intentionally empty.
21102     }
21103 
21104     /**
21105      * Returns the over-scroll mode for this view. The result will be
21106      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21107      * (allow over-scrolling only if the view content is larger than the container),
21108      * or {@link #OVER_SCROLL_NEVER}.
21109      *
21110      * @return This view's over-scroll mode.
21111      */
getOverScrollMode()21112     public int getOverScrollMode() {
21113         return mOverScrollMode;
21114     }
21115 
21116     /**
21117      * Set the over-scroll mode for this view. Valid over-scroll modes are
21118      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21119      * (allow over-scrolling only if the view content is larger than the container),
21120      * or {@link #OVER_SCROLL_NEVER}.
21121      *
21122      * Setting the over-scroll mode of a view will have an effect only if the
21123      * view is capable of scrolling.
21124      *
21125      * @param overScrollMode The new over-scroll mode for this view.
21126      */
setOverScrollMode(int overScrollMode)21127     public void setOverScrollMode(int overScrollMode) {
21128         if (overScrollMode != OVER_SCROLL_ALWAYS &&
21129                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21130                 overScrollMode != OVER_SCROLL_NEVER) {
21131             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21132         }
21133         mOverScrollMode = overScrollMode;
21134     }
21135 
21136     /**
21137      * Enable or disable nested scrolling for this view.
21138      *
21139      * <p>If this property is set to true the view will be permitted to initiate nested
21140      * scrolling operations with a compatible parent view in the current hierarchy. If this
21141      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21142      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21143      * the nested scroll.</p>
21144      *
21145      * @param enabled true to enable nested scrolling, false to disable
21146      *
21147      * @see #isNestedScrollingEnabled()
21148      */
setNestedScrollingEnabled(boolean enabled)21149     public void setNestedScrollingEnabled(boolean enabled) {
21150         if (enabled) {
21151             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21152         } else {
21153             stopNestedScroll();
21154             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21155         }
21156     }
21157 
21158     /**
21159      * Returns true if nested scrolling is enabled for this view.
21160      *
21161      * <p>If nested scrolling is enabled and this View class implementation supports it,
21162      * this view will act as a nested scrolling child view when applicable, forwarding data
21163      * about the scroll operation in progress to a compatible and cooperating nested scrolling
21164      * parent.</p>
21165      *
21166      * @return true if nested scrolling is enabled
21167      *
21168      * @see #setNestedScrollingEnabled(boolean)
21169      */
isNestedScrollingEnabled()21170     public boolean isNestedScrollingEnabled() {
21171         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21172                 PFLAG3_NESTED_SCROLLING_ENABLED;
21173     }
21174 
21175     /**
21176      * Begin a nestable scroll operation along the given axes.
21177      *
21178      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21179      *
21180      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21181      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21182      * In the case of touch scrolling the nested scroll will be terminated automatically in
21183      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21184      * In the event of programmatic scrolling the caller must explicitly call
21185      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21186      *
21187      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21188      * If it returns false the caller may ignore the rest of this contract until the next scroll.
21189      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21190      *
21191      * <p>At each incremental step of the scroll the caller should invoke
21192      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21193      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21194      * parent at least partially consumed the scroll and the caller should adjust the amount it
21195      * scrolls by.</p>
21196      *
21197      * <p>After applying the remainder of the scroll delta the caller should invoke
21198      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21199      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21200      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21201      * </p>
21202      *
21203      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21204      *             {@link #SCROLL_AXIS_VERTICAL}.
21205      * @return true if a cooperative parent was found and nested scrolling has been enabled for
21206      *         the current gesture.
21207      *
21208      * @see #stopNestedScroll()
21209      * @see #dispatchNestedPreScroll(int, int, int[], int[])
21210      * @see #dispatchNestedScroll(int, int, int, int, int[])
21211      */
startNestedScroll(int axes)21212     public boolean startNestedScroll(int axes) {
21213         if (hasNestedScrollingParent()) {
21214             // Already in progress
21215             return true;
21216         }
21217         if (isNestedScrollingEnabled()) {
21218             ViewParent p = getParent();
21219             View child = this;
21220             while (p != null) {
21221                 try {
21222                     if (p.onStartNestedScroll(child, this, axes)) {
21223                         mNestedScrollingParent = p;
21224                         p.onNestedScrollAccepted(child, this, axes);
21225                         return true;
21226                     }
21227                 } catch (AbstractMethodError e) {
21228                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21229                             "method onStartNestedScroll", e);
21230                     // Allow the search upward to continue
21231                 }
21232                 if (p instanceof View) {
21233                     child = (View) p;
21234                 }
21235                 p = p.getParent();
21236             }
21237         }
21238         return false;
21239     }
21240 
21241     /**
21242      * Stop a nested scroll in progress.
21243      *
21244      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21245      *
21246      * @see #startNestedScroll(int)
21247      */
stopNestedScroll()21248     public void stopNestedScroll() {
21249         if (mNestedScrollingParent != null) {
21250             mNestedScrollingParent.onStopNestedScroll(this);
21251             mNestedScrollingParent = null;
21252         }
21253     }
21254 
21255     /**
21256      * Returns true if this view has a nested scrolling parent.
21257      *
21258      * <p>The presence of a nested scrolling parent indicates that this view has initiated
21259      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21260      *
21261      * @return whether this view has a nested scrolling parent
21262      */
hasNestedScrollingParent()21263     public boolean hasNestedScrollingParent() {
21264         return mNestedScrollingParent != null;
21265     }
21266 
21267     /**
21268      * Dispatch one step of a nested scroll in progress.
21269      *
21270      * <p>Implementations of views that support nested scrolling should call this to report
21271      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21272      * is not currently in progress or nested scrolling is not
21273      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21274      *
21275      * <p>Compatible View implementations should also call
21276      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21277      * consuming a component of the scroll event themselves.</p>
21278      *
21279      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21280      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21281      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21282      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21283      * @param offsetInWindow Optional. If not null, on return this will contain the offset
21284      *                       in local view coordinates of this view from before this operation
21285      *                       to after it completes. View implementations may use this to adjust
21286      *                       expected input coordinate tracking.
21287      * @return true if the event was dispatched, false if it could not be dispatched.
21288      * @see #dispatchNestedPreScroll(int, int, int[], int[])
21289      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)21290     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21291             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21292         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21293             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21294                 int startX = 0;
21295                 int startY = 0;
21296                 if (offsetInWindow != null) {
21297                     getLocationInWindow(offsetInWindow);
21298                     startX = offsetInWindow[0];
21299                     startY = offsetInWindow[1];
21300                 }
21301 
21302                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21303                         dxUnconsumed, dyUnconsumed);
21304 
21305                 if (offsetInWindow != null) {
21306                     getLocationInWindow(offsetInWindow);
21307                     offsetInWindow[0] -= startX;
21308                     offsetInWindow[1] -= startY;
21309                 }
21310                 return true;
21311             } else if (offsetInWindow != null) {
21312                 // No motion, no dispatch. Keep offsetInWindow up to date.
21313                 offsetInWindow[0] = 0;
21314                 offsetInWindow[1] = 0;
21315             }
21316         }
21317         return false;
21318     }
21319 
21320     /**
21321      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21322      *
21323      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21324      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21325      * scrolling operation to consume some or all of the scroll operation before the child view
21326      * consumes it.</p>
21327      *
21328      * @param dx Horizontal scroll distance in pixels
21329      * @param dy Vertical scroll distance in pixels
21330      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21331      *                 and consumed[1] the consumed dy.
21332      * @param offsetInWindow Optional. If not null, on return this will contain the offset
21333      *                       in local view coordinates of this view from before this operation
21334      *                       to after it completes. View implementations may use this to adjust
21335      *                       expected input coordinate tracking.
21336      * @return true if the parent consumed some or all of the scroll delta
21337      * @see #dispatchNestedScroll(int, int, int, int, int[])
21338      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)21339     public boolean dispatchNestedPreScroll(int dx, int dy,
21340             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21341         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21342             if (dx != 0 || dy != 0) {
21343                 int startX = 0;
21344                 int startY = 0;
21345                 if (offsetInWindow != null) {
21346                     getLocationInWindow(offsetInWindow);
21347                     startX = offsetInWindow[0];
21348                     startY = offsetInWindow[1];
21349                 }
21350 
21351                 if (consumed == null) {
21352                     if (mTempNestedScrollConsumed == null) {
21353                         mTempNestedScrollConsumed = new int[2];
21354                     }
21355                     consumed = mTempNestedScrollConsumed;
21356                 }
21357                 consumed[0] = 0;
21358                 consumed[1] = 0;
21359                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21360 
21361                 if (offsetInWindow != null) {
21362                     getLocationInWindow(offsetInWindow);
21363                     offsetInWindow[0] -= startX;
21364                     offsetInWindow[1] -= startY;
21365                 }
21366                 return consumed[0] != 0 || consumed[1] != 0;
21367             } else if (offsetInWindow != null) {
21368                 offsetInWindow[0] = 0;
21369                 offsetInWindow[1] = 0;
21370             }
21371         }
21372         return false;
21373     }
21374 
21375     /**
21376      * Dispatch a fling to a nested scrolling parent.
21377      *
21378      * <p>This method should be used to indicate that a nested scrolling child has detected
21379      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21380      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21381      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21382      * along a scrollable axis.</p>
21383      *
21384      * <p>If a nested scrolling child view would normally fling but it is at the edge of
21385      * its own content, it can use this method to delegate the fling to its nested scrolling
21386      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21387      *
21388      * @param velocityX Horizontal fling velocity in pixels per second
21389      * @param velocityY Vertical fling velocity in pixels per second
21390      * @param consumed true if the child consumed the fling, false otherwise
21391      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21392      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)21393     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21394         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21395             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21396         }
21397         return false;
21398     }
21399 
21400     /**
21401      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21402      *
21403      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21404      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21405      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21406      * before the child view consumes it. If this method returns <code>true</code>, a nested
21407      * parent view consumed the fling and this view should not scroll as a result.</p>
21408      *
21409      * <p>For a better user experience, only one view in a nested scrolling chain should consume
21410      * the fling at a time. If a parent view consumed the fling this method will return false.
21411      * Custom view implementations should account for this in two ways:</p>
21412      *
21413      * <ul>
21414      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21415      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21416      *     position regardless.</li>
21417      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21418      *     even to settle back to a valid idle position.</li>
21419      * </ul>
21420      *
21421      * <p>Views should also not offer fling velocities to nested parent views along an axis
21422      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21423      * should not offer a horizontal fling velocity to its parents since scrolling along that
21424      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21425      *
21426      * @param velocityX Horizontal fling velocity in pixels per second
21427      * @param velocityY Vertical fling velocity in pixels per second
21428      * @return true if a nested scrolling parent consumed the fling
21429      */
dispatchNestedPreFling(float velocityX, float velocityY)21430     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21431         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21432             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21433         }
21434         return false;
21435     }
21436 
21437     /**
21438      * Gets a scale factor that determines the distance the view should scroll
21439      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21440      * @return The vertical scroll scale factor.
21441      * @hide
21442      */
getVerticalScrollFactor()21443     protected float getVerticalScrollFactor() {
21444         if (mVerticalScrollFactor == 0) {
21445             TypedValue outValue = new TypedValue();
21446             if (!mContext.getTheme().resolveAttribute(
21447                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21448                 throw new IllegalStateException(
21449                         "Expected theme to define listPreferredItemHeight.");
21450             }
21451             mVerticalScrollFactor = outValue.getDimension(
21452                     mContext.getResources().getDisplayMetrics());
21453         }
21454         return mVerticalScrollFactor;
21455     }
21456 
21457     /**
21458      * Gets a scale factor that determines the distance the view should scroll
21459      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21460      * @return The horizontal scroll scale factor.
21461      * @hide
21462      */
getHorizontalScrollFactor()21463     protected float getHorizontalScrollFactor() {
21464         // TODO: Should use something else.
21465         return getVerticalScrollFactor();
21466     }
21467 
21468     /**
21469      * Return the value specifying the text direction or policy that was set with
21470      * {@link #setTextDirection(int)}.
21471      *
21472      * @return the defined text direction. It can be one of:
21473      *
21474      * {@link #TEXT_DIRECTION_INHERIT},
21475      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21476      * {@link #TEXT_DIRECTION_ANY_RTL},
21477      * {@link #TEXT_DIRECTION_LTR},
21478      * {@link #TEXT_DIRECTION_RTL},
21479      * {@link #TEXT_DIRECTION_LOCALE},
21480      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21481      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21482      *
21483      * @attr ref android.R.styleable#View_textDirection
21484      *
21485      * @hide
21486      */
21487     @ViewDebug.ExportedProperty(category = "text", mapping = {
21488             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21489             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21490             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21491             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21492             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21493             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21494             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21495             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21496     })
getRawTextDirection()21497     public int getRawTextDirection() {
21498         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21499     }
21500 
21501     /**
21502      * Set the text direction.
21503      *
21504      * @param textDirection the direction to set. Should be one of:
21505      *
21506      * {@link #TEXT_DIRECTION_INHERIT},
21507      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21508      * {@link #TEXT_DIRECTION_ANY_RTL},
21509      * {@link #TEXT_DIRECTION_LTR},
21510      * {@link #TEXT_DIRECTION_RTL},
21511      * {@link #TEXT_DIRECTION_LOCALE}
21512      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21513      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21514      *
21515      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21516      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21517      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21518      *
21519      * @attr ref android.R.styleable#View_textDirection
21520      */
setTextDirection(int textDirection)21521     public void setTextDirection(int textDirection) {
21522         if (getRawTextDirection() != textDirection) {
21523             // Reset the current text direction and the resolved one
21524             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21525             resetResolvedTextDirection();
21526             // Set the new text direction
21527             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21528             // Do resolution
21529             resolveTextDirection();
21530             // Notify change
21531             onRtlPropertiesChanged(getLayoutDirection());
21532             // Refresh
21533             requestLayout();
21534             invalidate(true);
21535         }
21536     }
21537 
21538     /**
21539      * Return the resolved text direction.
21540      *
21541      * @return the resolved text direction. Returns one of:
21542      *
21543      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21544      * {@link #TEXT_DIRECTION_ANY_RTL},
21545      * {@link #TEXT_DIRECTION_LTR},
21546      * {@link #TEXT_DIRECTION_RTL},
21547      * {@link #TEXT_DIRECTION_LOCALE},
21548      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21549      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21550      *
21551      * @attr ref android.R.styleable#View_textDirection
21552      */
21553     @ViewDebug.ExportedProperty(category = "text", mapping = {
21554             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21555             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21556             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21557             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21558             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21559             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21560             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21561             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21562     })
getTextDirection()21563     public int getTextDirection() {
21564         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21565     }
21566 
21567     /**
21568      * Resolve the text direction.
21569      *
21570      * @return true if resolution has been done, false otherwise.
21571      *
21572      * @hide
21573      */
resolveTextDirection()21574     public boolean resolveTextDirection() {
21575         // Reset any previous text direction resolution
21576         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21577 
21578         if (hasRtlSupport()) {
21579             // Set resolved text direction flag depending on text direction flag
21580             final int textDirection = getRawTextDirection();
21581             switch(textDirection) {
21582                 case TEXT_DIRECTION_INHERIT:
21583                     if (!canResolveTextDirection()) {
21584                         // We cannot do the resolution if there is no parent, so use the default one
21585                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21586                         // Resolution will need to happen again later
21587                         return false;
21588                     }
21589 
21590                     // Parent has not yet resolved, so we still return the default
21591                     try {
21592                         if (!mParent.isTextDirectionResolved()) {
21593                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21594                             // Resolution will need to happen again later
21595                             return false;
21596                         }
21597                     } catch (AbstractMethodError e) {
21598                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21599                                 " does not fully implement ViewParent", e);
21600                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21601                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21602                         return true;
21603                     }
21604 
21605                     // Set current resolved direction to the same value as the parent's one
21606                     int parentResolvedDirection;
21607                     try {
21608                         parentResolvedDirection = mParent.getTextDirection();
21609                     } catch (AbstractMethodError e) {
21610                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21611                                 " does not fully implement ViewParent", e);
21612                         parentResolvedDirection = TEXT_DIRECTION_LTR;
21613                     }
21614                     switch (parentResolvedDirection) {
21615                         case TEXT_DIRECTION_FIRST_STRONG:
21616                         case TEXT_DIRECTION_ANY_RTL:
21617                         case TEXT_DIRECTION_LTR:
21618                         case TEXT_DIRECTION_RTL:
21619                         case TEXT_DIRECTION_LOCALE:
21620                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
21621                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
21622                             mPrivateFlags2 |=
21623                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21624                             break;
21625                         default:
21626                             // Default resolved direction is "first strong" heuristic
21627                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21628                     }
21629                     break;
21630                 case TEXT_DIRECTION_FIRST_STRONG:
21631                 case TEXT_DIRECTION_ANY_RTL:
21632                 case TEXT_DIRECTION_LTR:
21633                 case TEXT_DIRECTION_RTL:
21634                 case TEXT_DIRECTION_LOCALE:
21635                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
21636                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
21637                     // Resolved direction is the same as text direction
21638                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21639                     break;
21640                 default:
21641                     // Default resolved direction is "first strong" heuristic
21642                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21643             }
21644         } else {
21645             // Default resolved direction is "first strong" heuristic
21646             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21647         }
21648 
21649         // Set to resolved
21650         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21651         return true;
21652     }
21653 
21654     /**
21655      * Check if text direction resolution can be done.
21656      *
21657      * @return true if text direction resolution can be done otherwise return false.
21658      */
canResolveTextDirection()21659     public boolean canResolveTextDirection() {
21660         switch (getRawTextDirection()) {
21661             case TEXT_DIRECTION_INHERIT:
21662                 if (mParent != null) {
21663                     try {
21664                         return mParent.canResolveTextDirection();
21665                     } catch (AbstractMethodError e) {
21666                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21667                                 " does not fully implement ViewParent", e);
21668                     }
21669                 }
21670                 return false;
21671 
21672             default:
21673                 return true;
21674         }
21675     }
21676 
21677     /**
21678      * Reset resolved text direction. Text direction will be resolved during a call to
21679      * {@link #onMeasure(int, int)}.
21680      *
21681      * @hide
21682      */
resetResolvedTextDirection()21683     public void resetResolvedTextDirection() {
21684         // Reset any previous text direction resolution
21685         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21686         // Set to default value
21687         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21688     }
21689 
21690     /**
21691      * @return true if text direction is inherited.
21692      *
21693      * @hide
21694      */
isTextDirectionInherited()21695     public boolean isTextDirectionInherited() {
21696         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21697     }
21698 
21699     /**
21700      * @return true if text direction is resolved.
21701      */
isTextDirectionResolved()21702     public boolean isTextDirectionResolved() {
21703         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21704     }
21705 
21706     /**
21707      * Return the value specifying the text alignment or policy that was set with
21708      * {@link #setTextAlignment(int)}.
21709      *
21710      * @return the defined text alignment. It can be one of:
21711      *
21712      * {@link #TEXT_ALIGNMENT_INHERIT},
21713      * {@link #TEXT_ALIGNMENT_GRAVITY},
21714      * {@link #TEXT_ALIGNMENT_CENTER},
21715      * {@link #TEXT_ALIGNMENT_TEXT_START},
21716      * {@link #TEXT_ALIGNMENT_TEXT_END},
21717      * {@link #TEXT_ALIGNMENT_VIEW_START},
21718      * {@link #TEXT_ALIGNMENT_VIEW_END}
21719      *
21720      * @attr ref android.R.styleable#View_textAlignment
21721      *
21722      * @hide
21723      */
21724     @ViewDebug.ExportedProperty(category = "text", mapping = {
21725             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21726             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21727             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21728             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21729             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21730             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21731             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21732     })
21733     @TextAlignment
getRawTextAlignment()21734     public int getRawTextAlignment() {
21735         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21736     }
21737 
21738     /**
21739      * Set the text alignment.
21740      *
21741      * @param textAlignment The text alignment to set. Should be one of
21742      *
21743      * {@link #TEXT_ALIGNMENT_INHERIT},
21744      * {@link #TEXT_ALIGNMENT_GRAVITY},
21745      * {@link #TEXT_ALIGNMENT_CENTER},
21746      * {@link #TEXT_ALIGNMENT_TEXT_START},
21747      * {@link #TEXT_ALIGNMENT_TEXT_END},
21748      * {@link #TEXT_ALIGNMENT_VIEW_START},
21749      * {@link #TEXT_ALIGNMENT_VIEW_END}
21750      *
21751      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21752      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21753      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21754      *
21755      * @attr ref android.R.styleable#View_textAlignment
21756      */
setTextAlignment(@extAlignment int textAlignment)21757     public void setTextAlignment(@TextAlignment int textAlignment) {
21758         if (textAlignment != getRawTextAlignment()) {
21759             // Reset the current and resolved text alignment
21760             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21761             resetResolvedTextAlignment();
21762             // Set the new text alignment
21763             mPrivateFlags2 |=
21764                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21765             // Do resolution
21766             resolveTextAlignment();
21767             // Notify change
21768             onRtlPropertiesChanged(getLayoutDirection());
21769             // Refresh
21770             requestLayout();
21771             invalidate(true);
21772         }
21773     }
21774 
21775     /**
21776      * Return the resolved text alignment.
21777      *
21778      * @return the resolved text alignment. Returns one of:
21779      *
21780      * {@link #TEXT_ALIGNMENT_GRAVITY},
21781      * {@link #TEXT_ALIGNMENT_CENTER},
21782      * {@link #TEXT_ALIGNMENT_TEXT_START},
21783      * {@link #TEXT_ALIGNMENT_TEXT_END},
21784      * {@link #TEXT_ALIGNMENT_VIEW_START},
21785      * {@link #TEXT_ALIGNMENT_VIEW_END}
21786      *
21787      * @attr ref android.R.styleable#View_textAlignment
21788      */
21789     @ViewDebug.ExportedProperty(category = "text", mapping = {
21790             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21791             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21792             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21793             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21794             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21795             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21796             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21797     })
21798     @TextAlignment
getTextAlignment()21799     public int getTextAlignment() {
21800         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21801                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21802     }
21803 
21804     /**
21805      * Resolve the text alignment.
21806      *
21807      * @return true if resolution has been done, false otherwise.
21808      *
21809      * @hide
21810      */
resolveTextAlignment()21811     public boolean resolveTextAlignment() {
21812         // Reset any previous text alignment resolution
21813         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21814 
21815         if (hasRtlSupport()) {
21816             // Set resolved text alignment flag depending on text alignment flag
21817             final int textAlignment = getRawTextAlignment();
21818             switch (textAlignment) {
21819                 case TEXT_ALIGNMENT_INHERIT:
21820                     // Check if we can resolve the text alignment
21821                     if (!canResolveTextAlignment()) {
21822                         // We cannot do the resolution if there is no parent so use the default
21823                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21824                         // Resolution will need to happen again later
21825                         return false;
21826                     }
21827 
21828                     // Parent has not yet resolved, so we still return the default
21829                     try {
21830                         if (!mParent.isTextAlignmentResolved()) {
21831                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21832                             // Resolution will need to happen again later
21833                             return false;
21834                         }
21835                     } catch (AbstractMethodError e) {
21836                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21837                                 " does not fully implement ViewParent", e);
21838                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21839                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21840                         return true;
21841                     }
21842 
21843                     int parentResolvedTextAlignment;
21844                     try {
21845                         parentResolvedTextAlignment = mParent.getTextAlignment();
21846                     } catch (AbstractMethodError e) {
21847                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21848                                 " does not fully implement ViewParent", e);
21849                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21850                     }
21851                     switch (parentResolvedTextAlignment) {
21852                         case TEXT_ALIGNMENT_GRAVITY:
21853                         case TEXT_ALIGNMENT_TEXT_START:
21854                         case TEXT_ALIGNMENT_TEXT_END:
21855                         case TEXT_ALIGNMENT_CENTER:
21856                         case TEXT_ALIGNMENT_VIEW_START:
21857                         case TEXT_ALIGNMENT_VIEW_END:
21858                             // Resolved text alignment is the same as the parent resolved
21859                             // text alignment
21860                             mPrivateFlags2 |=
21861                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21862                             break;
21863                         default:
21864                             // Use default resolved text alignment
21865                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21866                     }
21867                     break;
21868                 case TEXT_ALIGNMENT_GRAVITY:
21869                 case TEXT_ALIGNMENT_TEXT_START:
21870                 case TEXT_ALIGNMENT_TEXT_END:
21871                 case TEXT_ALIGNMENT_CENTER:
21872                 case TEXT_ALIGNMENT_VIEW_START:
21873                 case TEXT_ALIGNMENT_VIEW_END:
21874                     // Resolved text alignment is the same as text alignment
21875                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21876                     break;
21877                 default:
21878                     // Use default resolved text alignment
21879                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21880             }
21881         } else {
21882             // Use default resolved text alignment
21883             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21884         }
21885 
21886         // Set the resolved
21887         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21888         return true;
21889     }
21890 
21891     /**
21892      * Check if text alignment resolution can be done.
21893      *
21894      * @return true if text alignment resolution can be done otherwise return false.
21895      */
canResolveTextAlignment()21896     public boolean canResolveTextAlignment() {
21897         switch (getRawTextAlignment()) {
21898             case TEXT_DIRECTION_INHERIT:
21899                 if (mParent != null) {
21900                     try {
21901                         return mParent.canResolveTextAlignment();
21902                     } catch (AbstractMethodError e) {
21903                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21904                                 " does not fully implement ViewParent", e);
21905                     }
21906                 }
21907                 return false;
21908 
21909             default:
21910                 return true;
21911         }
21912     }
21913 
21914     /**
21915      * Reset resolved text alignment. Text alignment will be resolved during a call to
21916      * {@link #onMeasure(int, int)}.
21917      *
21918      * @hide
21919      */
resetResolvedTextAlignment()21920     public void resetResolvedTextAlignment() {
21921         // Reset any previous text alignment resolution
21922         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21923         // Set to default
21924         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21925     }
21926 
21927     /**
21928      * @return true if text alignment is inherited.
21929      *
21930      * @hide
21931      */
isTextAlignmentInherited()21932     public boolean isTextAlignmentInherited() {
21933         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21934     }
21935 
21936     /**
21937      * @return true if text alignment is resolved.
21938      */
isTextAlignmentResolved()21939     public boolean isTextAlignmentResolved() {
21940         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21941     }
21942 
21943     /**
21944      * Generate a value suitable for use in {@link #setId(int)}.
21945      * This value will not collide with ID values generated at build time by aapt for R.id.
21946      *
21947      * @return a generated ID value
21948      */
generateViewId()21949     public static int generateViewId() {
21950         for (;;) {
21951             final int result = sNextGeneratedId.get();
21952             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21953             int newValue = result + 1;
21954             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21955             if (sNextGeneratedId.compareAndSet(result, newValue)) {
21956                 return result;
21957             }
21958         }
21959     }
21960 
21961     /**
21962      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21963      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21964      *                           a normal View or a ViewGroup with
21965      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21966      * @hide
21967      */
captureTransitioningViews(List<View> transitioningViews)21968     public void captureTransitioningViews(List<View> transitioningViews) {
21969         if (getVisibility() == View.VISIBLE) {
21970             transitioningViews.add(this);
21971         }
21972     }
21973 
21974     /**
21975      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21976      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21977      * @hide
21978      */
findNamedViews(Map<String, View> namedElements)21979     public void findNamedViews(Map<String, View> namedElements) {
21980         if (getVisibility() == VISIBLE || mGhostView != null) {
21981             String transitionName = getTransitionName();
21982             if (transitionName != null) {
21983                 namedElements.put(transitionName, this);
21984             }
21985         }
21986     }
21987 
21988     /**
21989      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
21990      * The default implementation does not care the location or event types, but some subclasses
21991      * may use it (such as WebViews).
21992      * @param event The MotionEvent from a mouse
21993      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
21994      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
21995      * @see PointerIcon
21996      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)21997     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
21998         final float x = event.getX(pointerIndex);
21999         final float y = event.getY(pointerIndex);
22000         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
22001             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
22002         }
22003         return mPointerIcon;
22004     }
22005 
22006     /**
22007      * Set the pointer icon for the current view.
22008      * Passing {@code null} will restore the pointer icon to its default value.
22009      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
22010      */
setPointerIcon(PointerIcon pointerIcon)22011     public void setPointerIcon(PointerIcon pointerIcon) {
22012         mPointerIcon = pointerIcon;
22013         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
22014             return;
22015         }
22016         try {
22017             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
22018         } catch (RemoteException e) {
22019         }
22020     }
22021 
22022     /**
22023      * Gets the pointer icon for the current view.
22024      */
getPointerIcon()22025     public PointerIcon getPointerIcon() {
22026         return mPointerIcon;
22027     }
22028 
22029     //
22030     // Properties
22031     //
22032     /**
22033      * A Property wrapper around the <code>alpha</code> functionality handled by the
22034      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
22035      */
22036     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
22037         @Override
22038         public void setValue(View object, float value) {
22039             object.setAlpha(value);
22040         }
22041 
22042         @Override
22043         public Float get(View object) {
22044             return object.getAlpha();
22045         }
22046     };
22047 
22048     /**
22049      * A Property wrapper around the <code>translationX</code> functionality handled by the
22050      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
22051      */
22052     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
22053         @Override
22054         public void setValue(View object, float value) {
22055             object.setTranslationX(value);
22056         }
22057 
22058                 @Override
22059         public Float get(View object) {
22060             return object.getTranslationX();
22061         }
22062     };
22063 
22064     /**
22065      * A Property wrapper around the <code>translationY</code> functionality handled by the
22066      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22067      */
22068     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22069         @Override
22070         public void setValue(View object, float value) {
22071             object.setTranslationY(value);
22072         }
22073 
22074         @Override
22075         public Float get(View object) {
22076             return object.getTranslationY();
22077         }
22078     };
22079 
22080     /**
22081      * A Property wrapper around the <code>translationZ</code> functionality handled by the
22082      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22083      */
22084     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22085         @Override
22086         public void setValue(View object, float value) {
22087             object.setTranslationZ(value);
22088         }
22089 
22090         @Override
22091         public Float get(View object) {
22092             return object.getTranslationZ();
22093         }
22094     };
22095 
22096     /**
22097      * A Property wrapper around the <code>x</code> functionality handled by the
22098      * {@link View#setX(float)} and {@link View#getX()} methods.
22099      */
22100     public static final Property<View, Float> X = new FloatProperty<View>("x") {
22101         @Override
22102         public void setValue(View object, float value) {
22103             object.setX(value);
22104         }
22105 
22106         @Override
22107         public Float get(View object) {
22108             return object.getX();
22109         }
22110     };
22111 
22112     /**
22113      * A Property wrapper around the <code>y</code> functionality handled by the
22114      * {@link View#setY(float)} and {@link View#getY()} methods.
22115      */
22116     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22117         @Override
22118         public void setValue(View object, float value) {
22119             object.setY(value);
22120         }
22121 
22122         @Override
22123         public Float get(View object) {
22124             return object.getY();
22125         }
22126     };
22127 
22128     /**
22129      * A Property wrapper around the <code>z</code> functionality handled by the
22130      * {@link View#setZ(float)} and {@link View#getZ()} methods.
22131      */
22132     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22133         @Override
22134         public void setValue(View object, float value) {
22135             object.setZ(value);
22136         }
22137 
22138         @Override
22139         public Float get(View object) {
22140             return object.getZ();
22141         }
22142     };
22143 
22144     /**
22145      * A Property wrapper around the <code>rotation</code> functionality handled by the
22146      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22147      */
22148     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22149         @Override
22150         public void setValue(View object, float value) {
22151             object.setRotation(value);
22152         }
22153 
22154         @Override
22155         public Float get(View object) {
22156             return object.getRotation();
22157         }
22158     };
22159 
22160     /**
22161      * A Property wrapper around the <code>rotationX</code> functionality handled by the
22162      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22163      */
22164     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22165         @Override
22166         public void setValue(View object, float value) {
22167             object.setRotationX(value);
22168         }
22169 
22170         @Override
22171         public Float get(View object) {
22172             return object.getRotationX();
22173         }
22174     };
22175 
22176     /**
22177      * A Property wrapper around the <code>rotationY</code> functionality handled by the
22178      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22179      */
22180     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22181         @Override
22182         public void setValue(View object, float value) {
22183             object.setRotationY(value);
22184         }
22185 
22186         @Override
22187         public Float get(View object) {
22188             return object.getRotationY();
22189         }
22190     };
22191 
22192     /**
22193      * A Property wrapper around the <code>scaleX</code> functionality handled by the
22194      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22195      */
22196     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22197         @Override
22198         public void setValue(View object, float value) {
22199             object.setScaleX(value);
22200         }
22201 
22202         @Override
22203         public Float get(View object) {
22204             return object.getScaleX();
22205         }
22206     };
22207 
22208     /**
22209      * A Property wrapper around the <code>scaleY</code> functionality handled by the
22210      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22211      */
22212     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22213         @Override
22214         public void setValue(View object, float value) {
22215             object.setScaleY(value);
22216         }
22217 
22218         @Override
22219         public Float get(View object) {
22220             return object.getScaleY();
22221         }
22222     };
22223 
22224     /**
22225      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22226      * Each MeasureSpec represents a requirement for either the width or the height.
22227      * A MeasureSpec is comprised of a size and a mode. There are three possible
22228      * modes:
22229      * <dl>
22230      * <dt>UNSPECIFIED</dt>
22231      * <dd>
22232      * The parent has not imposed any constraint on the child. It can be whatever size
22233      * it wants.
22234      * </dd>
22235      *
22236      * <dt>EXACTLY</dt>
22237      * <dd>
22238      * The parent has determined an exact size for the child. The child is going to be
22239      * given those bounds regardless of how big it wants to be.
22240      * </dd>
22241      *
22242      * <dt>AT_MOST</dt>
22243      * <dd>
22244      * The child can be as large as it wants up to the specified size.
22245      * </dd>
22246      * </dl>
22247      *
22248      * MeasureSpecs are implemented as ints to reduce object allocation. This class
22249      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22250      */
22251     public static class MeasureSpec {
22252         private static final int MODE_SHIFT = 30;
22253         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22254 
22255         /** @hide */
22256         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22257         @Retention(RetentionPolicy.SOURCE)
22258         public @interface MeasureSpecMode {}
22259 
22260         /**
22261          * Measure specification mode: The parent has not imposed any constraint
22262          * on the child. It can be whatever size it wants.
22263          */
22264         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22265 
22266         /**
22267          * Measure specification mode: The parent has determined an exact size
22268          * for the child. The child is going to be given those bounds regardless
22269          * of how big it wants to be.
22270          */
22271         public static final int EXACTLY     = 1 << MODE_SHIFT;
22272 
22273         /**
22274          * Measure specification mode: The child can be as large as it wants up
22275          * to the specified size.
22276          */
22277         public static final int AT_MOST     = 2 << MODE_SHIFT;
22278 
22279         /**
22280          * Creates a measure specification based on the supplied size and mode.
22281          *
22282          * The mode must always be one of the following:
22283          * <ul>
22284          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22285          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22286          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22287          * </ul>
22288          *
22289          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22290          * implementation was such that the order of arguments did not matter
22291          * and overflow in either value could impact the resulting MeasureSpec.
22292          * {@link android.widget.RelativeLayout} was affected by this bug.
22293          * Apps targeting API levels greater than 17 will get the fixed, more strict
22294          * behavior.</p>
22295          *
22296          * @param size the size of the measure specification
22297          * @param mode the mode of the measure specification
22298          * @return the measure specification based on size and mode
22299          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)22300         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22301                                           @MeasureSpecMode int mode) {
22302             if (sUseBrokenMakeMeasureSpec) {
22303                 return size + mode;
22304             } else {
22305                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
22306             }
22307         }
22308 
22309         /**
22310          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22311          * will automatically get a size of 0. Older apps expect this.
22312          *
22313          * @hide internal use only for compatibility with system widgets and older apps
22314          */
makeSafeMeasureSpec(int size, int mode)22315         public static int makeSafeMeasureSpec(int size, int mode) {
22316             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22317                 return 0;
22318             }
22319             return makeMeasureSpec(size, mode);
22320         }
22321 
22322         /**
22323          * Extracts the mode from the supplied measure specification.
22324          *
22325          * @param measureSpec the measure specification to extract the mode from
22326          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22327          *         {@link android.view.View.MeasureSpec#AT_MOST} or
22328          *         {@link android.view.View.MeasureSpec#EXACTLY}
22329          */
22330         @MeasureSpecMode
getMode(int measureSpec)22331         public static int getMode(int measureSpec) {
22332             //noinspection ResourceType
22333             return (measureSpec & MODE_MASK);
22334         }
22335 
22336         /**
22337          * Extracts the size from the supplied measure specification.
22338          *
22339          * @param measureSpec the measure specification to extract the size from
22340          * @return the size in pixels defined in the supplied measure specification
22341          */
getSize(int measureSpec)22342         public static int getSize(int measureSpec) {
22343             return (measureSpec & ~MODE_MASK);
22344         }
22345 
adjust(int measureSpec, int delta)22346         static int adjust(int measureSpec, int delta) {
22347             final int mode = getMode(measureSpec);
22348             int size = getSize(measureSpec);
22349             if (mode == UNSPECIFIED) {
22350                 // No need to adjust size for UNSPECIFIED mode.
22351                 return makeMeasureSpec(size, UNSPECIFIED);
22352             }
22353             size += delta;
22354             if (size < 0) {
22355                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22356                         ") spec: " + toString(measureSpec) + " delta: " + delta);
22357                 size = 0;
22358             }
22359             return makeMeasureSpec(size, mode);
22360         }
22361 
22362         /**
22363          * Returns a String representation of the specified measure
22364          * specification.
22365          *
22366          * @param measureSpec the measure specification to convert to a String
22367          * @return a String with the following format: "MeasureSpec: MODE SIZE"
22368          */
toString(int measureSpec)22369         public static String toString(int measureSpec) {
22370             int mode = getMode(measureSpec);
22371             int size = getSize(measureSpec);
22372 
22373             StringBuilder sb = new StringBuilder("MeasureSpec: ");
22374 
22375             if (mode == UNSPECIFIED)
22376                 sb.append("UNSPECIFIED ");
22377             else if (mode == EXACTLY)
22378                 sb.append("EXACTLY ");
22379             else if (mode == AT_MOST)
22380                 sb.append("AT_MOST ");
22381             else
22382                 sb.append(mode).append(" ");
22383 
22384             sb.append(size);
22385             return sb.toString();
22386         }
22387     }
22388 
22389     private final class CheckForLongPress implements Runnable {
22390         private int mOriginalWindowAttachCount;
22391         private float mX;
22392         private float mY;
22393 
22394         @Override
run()22395         public void run() {
22396             if (isPressed() && (mParent != null)
22397                     && mOriginalWindowAttachCount == mWindowAttachCount) {
22398                 if (performLongClick(mX, mY)) {
22399                     mHasPerformedLongPress = true;
22400                 }
22401             }
22402         }
22403 
setAnchor(float x, float y)22404         public void setAnchor(float x, float y) {
22405             mX = x;
22406             mY = y;
22407         }
22408 
rememberWindowAttachCount()22409         public void rememberWindowAttachCount() {
22410             mOriginalWindowAttachCount = mWindowAttachCount;
22411         }
22412     }
22413 
22414     private final class CheckForTap implements Runnable {
22415         public float x;
22416         public float y;
22417 
22418         @Override
run()22419         public void run() {
22420             mPrivateFlags &= ~PFLAG_PREPRESSED;
22421             setPressed(true, x, y);
22422             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22423         }
22424     }
22425 
22426     private final class PerformClick implements Runnable {
22427         @Override
run()22428         public void run() {
22429             performClick();
22430         }
22431     }
22432 
22433     /**
22434      * This method returns a ViewPropertyAnimator object, which can be used to animate
22435      * specific properties on this View.
22436      *
22437      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22438      */
animate()22439     public ViewPropertyAnimator animate() {
22440         if (mAnimator == null) {
22441             mAnimator = new ViewPropertyAnimator(this);
22442         }
22443         return mAnimator;
22444     }
22445 
22446     /**
22447      * Sets the name of the View to be used to identify Views in Transitions.
22448      * Names should be unique in the View hierarchy.
22449      *
22450      * @param transitionName The name of the View to uniquely identify it for Transitions.
22451      */
setTransitionName(String transitionName)22452     public final void setTransitionName(String transitionName) {
22453         mTransitionName = transitionName;
22454     }
22455 
22456     /**
22457      * Returns the name of the View to be used to identify Views in Transitions.
22458      * Names should be unique in the View hierarchy.
22459      *
22460      * <p>This returns null if the View has not been given a name.</p>
22461      *
22462      * @return The name used of the View to be used to identify Views in Transitions or null
22463      * if no name has been given.
22464      */
22465     @ViewDebug.ExportedProperty
getTransitionName()22466     public String getTransitionName() {
22467         return mTransitionName;
22468     }
22469 
22470     /**
22471      * @hide
22472      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)22473     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22474         // Do nothing.
22475     }
22476 
22477     /**
22478      * Interface definition for a callback to be invoked when a hardware key event is
22479      * dispatched to this view. The callback will be invoked before the key event is
22480      * given to the view. This is only useful for hardware keyboards; a software input
22481      * method has no obligation to trigger this listener.
22482      */
22483     public interface OnKeyListener {
22484         /**
22485          * Called when a hardware key is dispatched to a view. This allows listeners to
22486          * get a chance to respond before the target view.
22487          * <p>Key presses in software keyboards will generally NOT trigger this method,
22488          * although some may elect to do so in some situations. Do not assume a
22489          * software input method has to be key-based; even if it is, it may use key presses
22490          * in a different way than you expect, so there is no way to reliably catch soft
22491          * input key presses.
22492          *
22493          * @param v The view the key has been dispatched to.
22494          * @param keyCode The code for the physical key that was pressed
22495          * @param event The KeyEvent object containing full information about
22496          *        the event.
22497          * @return True if the listener has consumed the event, false otherwise.
22498          */
onKey(View v, int keyCode, KeyEvent event)22499         boolean onKey(View v, int keyCode, KeyEvent event);
22500     }
22501 
22502     /**
22503      * Interface definition for a callback to be invoked when a touch event is
22504      * dispatched to this view. The callback will be invoked before the touch
22505      * event is given to the view.
22506      */
22507     public interface OnTouchListener {
22508         /**
22509          * Called when a touch event is dispatched to a view. This allows listeners to
22510          * get a chance to respond before the target view.
22511          *
22512          * @param v The view the touch event has been dispatched to.
22513          * @param event The MotionEvent object containing full information about
22514          *        the event.
22515          * @return True if the listener has consumed the event, false otherwise.
22516          */
onTouch(View v, MotionEvent event)22517         boolean onTouch(View v, MotionEvent event);
22518     }
22519 
22520     /**
22521      * Interface definition for a callback to be invoked when a hover event is
22522      * dispatched to this view. The callback will be invoked before the hover
22523      * event is given to the view.
22524      */
22525     public interface OnHoverListener {
22526         /**
22527          * Called when a hover event is dispatched to a view. This allows listeners to
22528          * get a chance to respond before the target view.
22529          *
22530          * @param v The view the hover event has been dispatched to.
22531          * @param event The MotionEvent object containing full information about
22532          *        the event.
22533          * @return True if the listener has consumed the event, false otherwise.
22534          */
onHover(View v, MotionEvent event)22535         boolean onHover(View v, MotionEvent event);
22536     }
22537 
22538     /**
22539      * Interface definition for a callback to be invoked when a generic motion event is
22540      * dispatched to this view. The callback will be invoked before the generic motion
22541      * event is given to the view.
22542      */
22543     public interface OnGenericMotionListener {
22544         /**
22545          * Called when a generic motion event is dispatched to a view. This allows listeners to
22546          * get a chance to respond before the target view.
22547          *
22548          * @param v The view the generic motion event has been dispatched to.
22549          * @param event The MotionEvent object containing full information about
22550          *        the event.
22551          * @return True if the listener has consumed the event, false otherwise.
22552          */
onGenericMotion(View v, MotionEvent event)22553         boolean onGenericMotion(View v, MotionEvent event);
22554     }
22555 
22556     /**
22557      * Interface definition for a callback to be invoked when a view has been clicked and held.
22558      */
22559     public interface OnLongClickListener {
22560         /**
22561          * Called when a view has been clicked and held.
22562          *
22563          * @param v The view that was clicked and held.
22564          *
22565          * @return true if the callback consumed the long click, false otherwise.
22566          */
onLongClick(View v)22567         boolean onLongClick(View v);
22568     }
22569 
22570     /**
22571      * Interface definition for a callback to be invoked when a drag is being dispatched
22572      * to this view.  The callback will be invoked before the hosting view's own
22573      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
22574      * onDrag(event) behavior, it should return 'false' from this callback.
22575      *
22576      * <div class="special reference">
22577      * <h3>Developer Guides</h3>
22578      * <p>For a guide to implementing drag and drop features, read the
22579      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22580      * </div>
22581      */
22582     public interface OnDragListener {
22583         /**
22584          * Called when a drag event is dispatched to a view. This allows listeners
22585          * to get a chance to override base View behavior.
22586          *
22587          * @param v The View that received the drag event.
22588          * @param event The {@link android.view.DragEvent} object for the drag event.
22589          * @return {@code true} if the drag event was handled successfully, or {@code false}
22590          * if the drag event was not handled. Note that {@code false} will trigger the View
22591          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22592          */
onDrag(View v, DragEvent event)22593         boolean onDrag(View v, DragEvent event);
22594     }
22595 
22596     /**
22597      * Interface definition for a callback to be invoked when the focus state of
22598      * a view changed.
22599      */
22600     public interface OnFocusChangeListener {
22601         /**
22602          * Called when the focus state of a view has changed.
22603          *
22604          * @param v The view whose state has changed.
22605          * @param hasFocus The new focus state of v.
22606          */
onFocusChange(View v, boolean hasFocus)22607         void onFocusChange(View v, boolean hasFocus);
22608     }
22609 
22610     /**
22611      * Interface definition for a callback to be invoked when a view is clicked.
22612      */
22613     public interface OnClickListener {
22614         /**
22615          * Called when a view has been clicked.
22616          *
22617          * @param v The view that was clicked.
22618          */
onClick(View v)22619         void onClick(View v);
22620     }
22621 
22622     /**
22623      * Interface definition for a callback to be invoked when a view is context clicked.
22624      */
22625     public interface OnContextClickListener {
22626         /**
22627          * Called when a view is context clicked.
22628          *
22629          * @param v The view that has been context clicked.
22630          * @return true if the callback consumed the context click, false otherwise.
22631          */
onContextClick(View v)22632         boolean onContextClick(View v);
22633     }
22634 
22635     /**
22636      * Interface definition for a callback to be invoked when the context menu
22637      * for this view is being built.
22638      */
22639     public interface OnCreateContextMenuListener {
22640         /**
22641          * Called when the context menu for this view is being built. It is not
22642          * safe to hold onto the menu after this method returns.
22643          *
22644          * @param menu The context menu that is being built
22645          * @param v The view for which the context menu is being built
22646          * @param menuInfo Extra information about the item for which the
22647          *            context menu should be shown. This information will vary
22648          *            depending on the class of v.
22649          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)22650         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22651     }
22652 
22653     /**
22654      * Interface definition for a callback to be invoked when the status bar changes
22655      * visibility.  This reports <strong>global</strong> changes to the system UI
22656      * state, not what the application is requesting.
22657      *
22658      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22659      */
22660     public interface OnSystemUiVisibilityChangeListener {
22661         /**
22662          * Called when the status bar changes visibility because of a call to
22663          * {@link View#setSystemUiVisibility(int)}.
22664          *
22665          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22666          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22667          * This tells you the <strong>global</strong> state of these UI visibility
22668          * flags, not what your app is currently applying.
22669          */
onSystemUiVisibilityChange(int visibility)22670         public void onSystemUiVisibilityChange(int visibility);
22671     }
22672 
22673     /**
22674      * Interface definition for a callback to be invoked when this view is attached
22675      * or detached from its window.
22676      */
22677     public interface OnAttachStateChangeListener {
22678         /**
22679          * Called when the view is attached to a window.
22680          * @param v The view that was attached
22681          */
onViewAttachedToWindow(View v)22682         public void onViewAttachedToWindow(View v);
22683         /**
22684          * Called when the view is detached from a window.
22685          * @param v The view that was detached
22686          */
onViewDetachedFromWindow(View v)22687         public void onViewDetachedFromWindow(View v);
22688     }
22689 
22690     /**
22691      * Listener for applying window insets on a view in a custom way.
22692      *
22693      * <p>Apps may choose to implement this interface if they want to apply custom policy
22694      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22695      * is set, its
22696      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22697      * method will be called instead of the View's own
22698      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22699      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22700      * the View's normal behavior as part of its own.</p>
22701      */
22702     public interface OnApplyWindowInsetsListener {
22703         /**
22704          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22705          * on a View, this listener method will be called instead of the view's own
22706          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22707          *
22708          * @param v The view applying window insets
22709          * @param insets The insets to apply
22710          * @return The insets supplied, minus any insets that were consumed
22711          */
onApplyWindowInsets(View v, WindowInsets insets)22712         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22713     }
22714 
22715     private final class UnsetPressedState implements Runnable {
22716         @Override
run()22717         public void run() {
22718             setPressed(false);
22719         }
22720     }
22721 
22722     /**
22723      * Base class for derived classes that want to save and restore their own
22724      * state in {@link android.view.View#onSaveInstanceState()}.
22725      */
22726     public static class BaseSavedState extends AbsSavedState {
22727         String mStartActivityRequestWhoSaved;
22728 
22729         /**
22730          * Constructor used when reading from a parcel. Reads the state of the superclass.
22731          *
22732          * @param source parcel to read from
22733          */
BaseSavedState(Parcel source)22734         public BaseSavedState(Parcel source) {
22735             this(source, null);
22736         }
22737 
22738         /**
22739          * Constructor used when reading from a parcel using a given class loader.
22740          * Reads the state of the superclass.
22741          *
22742          * @param source parcel to read from
22743          * @param loader ClassLoader to use for reading
22744          */
BaseSavedState(Parcel source, ClassLoader loader)22745         public BaseSavedState(Parcel source, ClassLoader loader) {
22746             super(source, loader);
22747             mStartActivityRequestWhoSaved = source.readString();
22748         }
22749 
22750         /**
22751          * Constructor called by derived classes when creating their SavedState objects
22752          *
22753          * @param superState The state of the superclass of this view
22754          */
BaseSavedState(Parcelable superState)22755         public BaseSavedState(Parcelable superState) {
22756             super(superState);
22757         }
22758 
22759         @Override
writeToParcel(Parcel out, int flags)22760         public void writeToParcel(Parcel out, int flags) {
22761             super.writeToParcel(out, flags);
22762             out.writeString(mStartActivityRequestWhoSaved);
22763         }
22764 
22765         public static final Parcelable.Creator<BaseSavedState> CREATOR
22766                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22767             @Override
22768             public BaseSavedState createFromParcel(Parcel in) {
22769                 return new BaseSavedState(in);
22770             }
22771 
22772             @Override
22773             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22774                 return new BaseSavedState(in, loader);
22775             }
22776 
22777             @Override
22778             public BaseSavedState[] newArray(int size) {
22779                 return new BaseSavedState[size];
22780             }
22781         };
22782     }
22783 
22784     /**
22785      * A set of information given to a view when it is attached to its parent
22786      * window.
22787      */
22788     final static class AttachInfo {
22789         interface Callbacks {
playSoundEffect(int effectId)22790             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)22791             boolean performHapticFeedback(int effectId, boolean always);
22792         }
22793 
22794         /**
22795          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22796          * to a Handler. This class contains the target (View) to invalidate and
22797          * the coordinates of the dirty rectangle.
22798          *
22799          * For performance purposes, this class also implements a pool of up to
22800          * POOL_LIMIT objects that get reused. This reduces memory allocations
22801          * whenever possible.
22802          */
22803         static class InvalidateInfo {
22804             private static final int POOL_LIMIT = 10;
22805 
22806             private static final SynchronizedPool<InvalidateInfo> sPool =
22807                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22808 
22809             View target;
22810 
22811             int left;
22812             int top;
22813             int right;
22814             int bottom;
22815 
obtain()22816             public static InvalidateInfo obtain() {
22817                 InvalidateInfo instance = sPool.acquire();
22818                 return (instance != null) ? instance : new InvalidateInfo();
22819             }
22820 
recycle()22821             public void recycle() {
22822                 target = null;
22823                 sPool.release(this);
22824             }
22825         }
22826 
22827         final IWindowSession mSession;
22828 
22829         final IWindow mWindow;
22830 
22831         final IBinder mWindowToken;
22832 
22833         final Display mDisplay;
22834 
22835         final Callbacks mRootCallbacks;
22836 
22837         IWindowId mIWindowId;
22838         WindowId mWindowId;
22839 
22840         /**
22841          * The top view of the hierarchy.
22842          */
22843         View mRootView;
22844 
22845         IBinder mPanelParentWindowToken;
22846 
22847         boolean mHardwareAccelerated;
22848         boolean mHardwareAccelerationRequested;
22849         ThreadedRenderer mHardwareRenderer;
22850         List<RenderNode> mPendingAnimatingRenderNodes;
22851 
22852         /**
22853          * The state of the display to which the window is attached, as reported
22854          * by {@link Display#getState()}.  Note that the display state constants
22855          * declared by {@link Display} do not exactly line up with the screen state
22856          * constants declared by {@link View} (there are more display states than
22857          * screen states).
22858          */
22859         int mDisplayState = Display.STATE_UNKNOWN;
22860 
22861         /**
22862          * Scale factor used by the compatibility mode
22863          */
22864         float mApplicationScale;
22865 
22866         /**
22867          * Indicates whether the application is in compatibility mode
22868          */
22869         boolean mScalingRequired;
22870 
22871         /**
22872          * Left position of this view's window
22873          */
22874         int mWindowLeft;
22875 
22876         /**
22877          * Top position of this view's window
22878          */
22879         int mWindowTop;
22880 
22881         /**
22882          * Indicates whether views need to use 32-bit drawing caches
22883          */
22884         boolean mUse32BitDrawingCache;
22885 
22886         /**
22887          * For windows that are full-screen but using insets to layout inside
22888          * of the screen areas, these are the current insets to appear inside
22889          * the overscan area of the display.
22890          */
22891         final Rect mOverscanInsets = new Rect();
22892 
22893         /**
22894          * For windows that are full-screen but using insets to layout inside
22895          * of the screen decorations, these are the current insets for the
22896          * content of the window.
22897          */
22898         final Rect mContentInsets = new Rect();
22899 
22900         /**
22901          * For windows that are full-screen but using insets to layout inside
22902          * of the screen decorations, these are the current insets for the
22903          * actual visible parts of the window.
22904          */
22905         final Rect mVisibleInsets = new Rect();
22906 
22907         /**
22908          * For windows that are full-screen but using insets to layout inside
22909          * of the screen decorations, these are the current insets for the
22910          * stable system windows.
22911          */
22912         final Rect mStableInsets = new Rect();
22913 
22914         /**
22915          * For windows that include areas that are not covered by real surface these are the outsets
22916          * for real surface.
22917          */
22918         final Rect mOutsets = new Rect();
22919 
22920         /**
22921          * In multi-window we force show the navigation bar. Because we don't want that the surface
22922          * size changes in this mode, we instead have a flag whether the navigation bar size should
22923          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22924          */
22925         boolean mAlwaysConsumeNavBar;
22926 
22927         /**
22928          * The internal insets given by this window.  This value is
22929          * supplied by the client (through
22930          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22931          * be given to the window manager when changed to be used in laying
22932          * out windows behind it.
22933          */
22934         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22935                 = new ViewTreeObserver.InternalInsetsInfo();
22936 
22937         /**
22938          * Set to true when mGivenInternalInsets is non-empty.
22939          */
22940         boolean mHasNonEmptyGivenInternalInsets;
22941 
22942         /**
22943          * All views in the window's hierarchy that serve as scroll containers,
22944          * used to determine if the window can be resized or must be panned
22945          * to adjust for a soft input area.
22946          */
22947         final ArrayList<View> mScrollContainers = new ArrayList<View>();
22948 
22949         final KeyEvent.DispatcherState mKeyDispatchState
22950                 = new KeyEvent.DispatcherState();
22951 
22952         /**
22953          * Indicates whether the view's window currently has the focus.
22954          */
22955         boolean mHasWindowFocus;
22956 
22957         /**
22958          * The current visibility of the window.
22959          */
22960         int mWindowVisibility;
22961 
22962         /**
22963          * Indicates the time at which drawing started to occur.
22964          */
22965         long mDrawingTime;
22966 
22967         /**
22968          * Indicates whether or not ignoring the DIRTY_MASK flags.
22969          */
22970         boolean mIgnoreDirtyState;
22971 
22972         /**
22973          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22974          * to avoid clearing that flag prematurely.
22975          */
22976         boolean mSetIgnoreDirtyState = false;
22977 
22978         /**
22979          * Indicates whether the view's window is currently in touch mode.
22980          */
22981         boolean mInTouchMode;
22982 
22983         /**
22984          * Indicates whether the view has requested unbuffered input dispatching for the current
22985          * event stream.
22986          */
22987         boolean mUnbufferedDispatchRequested;
22988 
22989         /**
22990          * Indicates that ViewAncestor should trigger a global layout change
22991          * the next time it performs a traversal
22992          */
22993         boolean mRecomputeGlobalAttributes;
22994 
22995         /**
22996          * Always report new attributes at next traversal.
22997          */
22998         boolean mForceReportNewAttributes;
22999 
23000         /**
23001          * Set during a traveral if any views want to keep the screen on.
23002          */
23003         boolean mKeepScreenOn;
23004 
23005         /**
23006          * Set during a traveral if the light center needs to be updated.
23007          */
23008         boolean mNeedsUpdateLightCenter;
23009 
23010         /**
23011          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
23012          */
23013         int mSystemUiVisibility;
23014 
23015         /**
23016          * Hack to force certain system UI visibility flags to be cleared.
23017          */
23018         int mDisabledSystemUiVisibility;
23019 
23020         /**
23021          * Last global system UI visibility reported by the window manager.
23022          */
23023         int mGlobalSystemUiVisibility = -1;
23024 
23025         /**
23026          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
23027          * attached.
23028          */
23029         boolean mHasSystemUiListeners;
23030 
23031         /**
23032          * Set if the window has requested to extend into the overscan region
23033          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
23034          */
23035         boolean mOverscanRequested;
23036 
23037         /**
23038          * Set if the visibility of any views has changed.
23039          */
23040         boolean mViewVisibilityChanged;
23041 
23042         /**
23043          * Set to true if a view has been scrolled.
23044          */
23045         boolean mViewScrollChanged;
23046 
23047         /**
23048          * Set to true if high contrast mode enabled
23049          */
23050         boolean mHighContrastText;
23051 
23052         /**
23053          * Set to true if a pointer event is currently being handled.
23054          */
23055         boolean mHandlingPointerEvent;
23056 
23057         /**
23058          * Global to the view hierarchy used as a temporary for dealing with
23059          * x/y points in the transparent region computations.
23060          */
23061         final int[] mTransparentLocation = new int[2];
23062 
23063         /**
23064          * Global to the view hierarchy used as a temporary for dealing with
23065          * x/y points in the ViewGroup.invalidateChild implementation.
23066          */
23067         final int[] mInvalidateChildLocation = new int[2];
23068 
23069         /**
23070          * Global to the view hierarchy used as a temporary for dealing with
23071          * computing absolute on-screen location.
23072          */
23073         final int[] mTmpLocation = new int[2];
23074 
23075         /**
23076          * Global to the view hierarchy used as a temporary for dealing with
23077          * x/y location when view is transformed.
23078          */
23079         final float[] mTmpTransformLocation = new float[2];
23080 
23081         /**
23082          * The view tree observer used to dispatch global events like
23083          * layout, pre-draw, touch mode change, etc.
23084          */
23085         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
23086 
23087         /**
23088          * A Canvas used by the view hierarchy to perform bitmap caching.
23089          */
23090         Canvas mCanvas;
23091 
23092         /**
23093          * The view root impl.
23094          */
23095         final ViewRootImpl mViewRootImpl;
23096 
23097         /**
23098          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23099          * handler can be used to pump events in the UI events queue.
23100          */
23101         final Handler mHandler;
23102 
23103         /**
23104          * Temporary for use in computing invalidate rectangles while
23105          * calling up the hierarchy.
23106          */
23107         final Rect mTmpInvalRect = new Rect();
23108 
23109         /**
23110          * Temporary for use in computing hit areas with transformed views
23111          */
23112         final RectF mTmpTransformRect = new RectF();
23113 
23114         /**
23115          * Temporary for use in computing hit areas with transformed views
23116          */
23117         final RectF mTmpTransformRect1 = new RectF();
23118 
23119         /**
23120          * Temporary list of rectanges.
23121          */
23122         final List<RectF> mTmpRectList = new ArrayList<>();
23123 
23124         /**
23125          * Temporary for use in transforming invalidation rect
23126          */
23127         final Matrix mTmpMatrix = new Matrix();
23128 
23129         /**
23130          * Temporary for use in transforming invalidation rect
23131          */
23132         final Transformation mTmpTransformation = new Transformation();
23133 
23134         /**
23135          * Temporary for use in querying outlines from OutlineProviders
23136          */
23137         final Outline mTmpOutline = new Outline();
23138 
23139         /**
23140          * Temporary list for use in collecting focusable descendents of a view.
23141          */
23142         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23143 
23144         /**
23145          * The id of the window for accessibility purposes.
23146          */
23147         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23148 
23149         /**
23150          * Flags related to accessibility processing.
23151          *
23152          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23153          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23154          */
23155         int mAccessibilityFetchFlags;
23156 
23157         /**
23158          * The drawable for highlighting accessibility focus.
23159          */
23160         Drawable mAccessibilityFocusDrawable;
23161 
23162         /**
23163          * Show where the margins, bounds and layout bounds are for each view.
23164          */
23165         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23166 
23167         /**
23168          * Point used to compute visible regions.
23169          */
23170         final Point mPoint = new Point();
23171 
23172         /**
23173          * Used to track which View originated a requestLayout() call, used when
23174          * requestLayout() is called during layout.
23175          */
23176         View mViewRequestingLayout;
23177 
23178         /**
23179          * Used to track views that need (at least) a partial relayout at their current size
23180          * during the next traversal.
23181          */
23182         List<View> mPartialLayoutViews = new ArrayList<>();
23183 
23184         /**
23185          * Swapped with mPartialLayoutViews during layout to avoid concurrent
23186          * modification. Lazily assigned during ViewRootImpl layout.
23187          */
23188         List<View> mEmptyPartialLayoutViews;
23189 
23190         /**
23191          * Used to track the identity of the current drag operation.
23192          */
23193         IBinder mDragToken;
23194 
23195         /**
23196          * The drag shadow surface for the current drag operation.
23197          */
23198         public Surface mDragSurface;
23199 
23200         /**
23201          * Creates a new set of attachment information with the specified
23202          * events handler and thread.
23203          *
23204          * @param handler the events handler the view must use
23205          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer)23206         AttachInfo(IWindowSession session, IWindow window, Display display,
23207                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23208             mSession = session;
23209             mWindow = window;
23210             mWindowToken = window.asBinder();
23211             mDisplay = display;
23212             mViewRootImpl = viewRootImpl;
23213             mHandler = handler;
23214             mRootCallbacks = effectPlayer;
23215         }
23216     }
23217 
23218     /**
23219      * <p>ScrollabilityCache holds various fields used by a View when scrolling
23220      * is supported. This avoids keeping too many unused fields in most
23221      * instances of View.</p>
23222      */
23223     private static class ScrollabilityCache implements Runnable {
23224 
23225         /**
23226          * Scrollbars are not visible
23227          */
23228         public static final int OFF = 0;
23229 
23230         /**
23231          * Scrollbars are visible
23232          */
23233         public static final int ON = 1;
23234 
23235         /**
23236          * Scrollbars are fading away
23237          */
23238         public static final int FADING = 2;
23239 
23240         public boolean fadeScrollBars;
23241 
23242         public int fadingEdgeLength;
23243         public int scrollBarDefaultDelayBeforeFade;
23244         public int scrollBarFadeDuration;
23245 
23246         public int scrollBarSize;
23247         public ScrollBarDrawable scrollBar;
23248         public float[] interpolatorValues;
23249         public View host;
23250 
23251         public final Paint paint;
23252         public final Matrix matrix;
23253         public Shader shader;
23254 
23255         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23256 
23257         private static final float[] OPAQUE = { 255 };
23258         private static final float[] TRANSPARENT = { 0.0f };
23259 
23260         /**
23261          * When fading should start. This time moves into the future every time
23262          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23263          */
23264         public long fadeStartTime;
23265 
23266 
23267         /**
23268          * The current state of the scrollbars: ON, OFF, or FADING
23269          */
23270         public int state = OFF;
23271 
23272         private int mLastColor;
23273 
23274         public final Rect mScrollBarBounds = new Rect();
23275 
23276         public static final int NOT_DRAGGING = 0;
23277         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23278         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23279         public int mScrollBarDraggingState = NOT_DRAGGING;
23280 
23281         public float mScrollBarDraggingPos = 0;
23282 
ScrollabilityCache(ViewConfiguration configuration, View host)23283         public ScrollabilityCache(ViewConfiguration configuration, View host) {
23284             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23285             scrollBarSize = configuration.getScaledScrollBarSize();
23286             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23287             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23288 
23289             paint = new Paint();
23290             matrix = new Matrix();
23291             // use use a height of 1, and then wack the matrix each time we
23292             // actually use it.
23293             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23294             paint.setShader(shader);
23295             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23296 
23297             this.host = host;
23298         }
23299 
setFadeColor(int color)23300         public void setFadeColor(int color) {
23301             if (color != mLastColor) {
23302                 mLastColor = color;
23303 
23304                 if (color != 0) {
23305                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23306                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23307                     paint.setShader(shader);
23308                     // Restore the default transfer mode (src_over)
23309                     paint.setXfermode(null);
23310                 } else {
23311                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23312                     paint.setShader(shader);
23313                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23314                 }
23315             }
23316         }
23317 
run()23318         public void run() {
23319             long now = AnimationUtils.currentAnimationTimeMillis();
23320             if (now >= fadeStartTime) {
23321 
23322                 // the animation fades the scrollbars out by changing
23323                 // the opacity (alpha) from fully opaque to fully
23324                 // transparent
23325                 int nextFrame = (int) now;
23326                 int framesCount = 0;
23327 
23328                 Interpolator interpolator = scrollBarInterpolator;
23329 
23330                 // Start opaque
23331                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23332 
23333                 // End transparent
23334                 nextFrame += scrollBarFadeDuration;
23335                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23336 
23337                 state = FADING;
23338 
23339                 // Kick off the fade animation
23340                 host.invalidate(true);
23341             }
23342         }
23343     }
23344 
23345     /**
23346      * Resuable callback for sending
23347      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23348      */
23349     private class SendViewScrolledAccessibilityEvent implements Runnable {
23350         public volatile boolean mIsPending;
23351 
run()23352         public void run() {
23353             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23354             mIsPending = false;
23355         }
23356     }
23357 
23358     /**
23359      * <p>
23360      * This class represents a delegate that can be registered in a {@link View}
23361      * to enhance accessibility support via composition rather via inheritance.
23362      * It is specifically targeted to widget developers that extend basic View
23363      * classes i.e. classes in package android.view, that would like their
23364      * applications to be backwards compatible.
23365      * </p>
23366      * <div class="special reference">
23367      * <h3>Developer Guides</h3>
23368      * <p>For more information about making applications accessible, read the
23369      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23370      * developer guide.</p>
23371      * </div>
23372      * <p>
23373      * A scenario in which a developer would like to use an accessibility delegate
23374      * is overriding a method introduced in a later API version then the minimal API
23375      * version supported by the application. For example, the method
23376      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23377      * in API version 4 when the accessibility APIs were first introduced. If a
23378      * developer would like his application to run on API version 4 devices (assuming
23379      * all other APIs used by the application are version 4 or lower) and take advantage
23380      * of this method, instead of overriding the method which would break the application's
23381      * backwards compatibility, he can override the corresponding method in this
23382      * delegate and register the delegate in the target View if the API version of
23383      * the system is high enough i.e. the API version is same or higher to the API
23384      * version that introduced
23385      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23386      * </p>
23387      * <p>
23388      * Here is an example implementation:
23389      * </p>
23390      * <code><pre><p>
23391      * if (Build.VERSION.SDK_INT >= 14) {
23392      *     // If the API version is equal of higher than the version in
23393      *     // which onInitializeAccessibilityNodeInfo was introduced we
23394      *     // register a delegate with a customized implementation.
23395      *     View view = findViewById(R.id.view_id);
23396      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23397      *         public void onInitializeAccessibilityNodeInfo(View host,
23398      *                 AccessibilityNodeInfo info) {
23399      *             // Let the default implementation populate the info.
23400      *             super.onInitializeAccessibilityNodeInfo(host, info);
23401      *             // Set some other information.
23402      *             info.setEnabled(host.isEnabled());
23403      *         }
23404      *     });
23405      * }
23406      * </code></pre></p>
23407      * <p>
23408      * This delegate contains methods that correspond to the accessibility methods
23409      * in View. If a delegate has been specified the implementation in View hands
23410      * off handling to the corresponding method in this delegate. The default
23411      * implementation the delegate methods behaves exactly as the corresponding
23412      * method in View for the case of no accessibility delegate been set. Hence,
23413      * to customize the behavior of a View method, clients can override only the
23414      * corresponding delegate method without altering the behavior of the rest
23415      * accessibility related methods of the host view.
23416      * </p>
23417      * <p>
23418      * <strong>Note:</strong> On platform versions prior to
23419      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23420      * views in the {@code android.widget.*} package are called <i>before</i>
23421      * host methods. This prevents certain properties such as class name from
23422      * being modified by overriding
23423      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23424      * as any changes will be overwritten by the host class.
23425      * <p>
23426      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23427      * methods are called <i>after</i> host methods, which all properties to be
23428      * modified without being overwritten by the host class.
23429      */
23430     public static class AccessibilityDelegate {
23431 
23432         /**
23433          * Sends an accessibility event of the given type. If accessibility is not
23434          * enabled this method has no effect.
23435          * <p>
23436          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23437          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23438          * been set.
23439          * </p>
23440          *
23441          * @param host The View hosting the delegate.
23442          * @param eventType The type of the event to send.
23443          *
23444          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23445          */
sendAccessibilityEvent(View host, int eventType)23446         public void sendAccessibilityEvent(View host, int eventType) {
23447             host.sendAccessibilityEventInternal(eventType);
23448         }
23449 
23450         /**
23451          * Performs the specified accessibility action on the view. For
23452          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23453          * <p>
23454          * The default implementation behaves as
23455          * {@link View#performAccessibilityAction(int, Bundle)
23456          *  View#performAccessibilityAction(int, Bundle)} for the case of
23457          *  no accessibility delegate been set.
23458          * </p>
23459          *
23460          * @param action The action to perform.
23461          * @return Whether the action was performed.
23462          *
23463          * @see View#performAccessibilityAction(int, Bundle)
23464          *      View#performAccessibilityAction(int, Bundle)
23465          */
performAccessibilityAction(View host, int action, Bundle args)23466         public boolean performAccessibilityAction(View host, int action, Bundle args) {
23467             return host.performAccessibilityActionInternal(action, args);
23468         }
23469 
23470         /**
23471          * Sends an accessibility event. This method behaves exactly as
23472          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23473          * empty {@link AccessibilityEvent} and does not perform a check whether
23474          * accessibility is enabled.
23475          * <p>
23476          * The default implementation behaves as
23477          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23478          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23479          * the case of no accessibility delegate been set.
23480          * </p>
23481          *
23482          * @param host The View hosting the delegate.
23483          * @param event The event to send.
23484          *
23485          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23486          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23487          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)23488         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23489             host.sendAccessibilityEventUncheckedInternal(event);
23490         }
23491 
23492         /**
23493          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23494          * to its children for adding their text content to the event.
23495          * <p>
23496          * The default implementation behaves as
23497          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23498          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23499          * the case of no accessibility delegate been set.
23500          * </p>
23501          *
23502          * @param host The View hosting the delegate.
23503          * @param event The event.
23504          * @return True if the event population was completed.
23505          *
23506          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23507          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23508          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)23509         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23510             return host.dispatchPopulateAccessibilityEventInternal(event);
23511         }
23512 
23513         /**
23514          * Gives a chance to the host View to populate the accessibility event with its
23515          * text content.
23516          * <p>
23517          * The default implementation behaves as
23518          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23519          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23520          * the case of no accessibility delegate been set.
23521          * </p>
23522          *
23523          * @param host The View hosting the delegate.
23524          * @param event The accessibility event which to populate.
23525          *
23526          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23527          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23528          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)23529         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23530             host.onPopulateAccessibilityEventInternal(event);
23531         }
23532 
23533         /**
23534          * Initializes an {@link AccessibilityEvent} with information about the
23535          * the host View which is the event source.
23536          * <p>
23537          * The default implementation behaves as
23538          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23539          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23540          * the case of no accessibility delegate been set.
23541          * </p>
23542          *
23543          * @param host The View hosting the delegate.
23544          * @param event The event to initialize.
23545          *
23546          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23547          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
23548          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)23549         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23550             host.onInitializeAccessibilityEventInternal(event);
23551         }
23552 
23553         /**
23554          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23555          * <p>
23556          * The default implementation behaves as
23557          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23558          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23559          * the case of no accessibility delegate been set.
23560          * </p>
23561          *
23562          * @param host The View hosting the delegate.
23563          * @param info The instance to initialize.
23564          *
23565          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23566          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23567          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)23568         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23569             host.onInitializeAccessibilityNodeInfoInternal(info);
23570         }
23571 
23572         /**
23573          * Called when a child of the host View has requested sending an
23574          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23575          * to augment the event.
23576          * <p>
23577          * The default implementation behaves as
23578          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23579          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23580          * the case of no accessibility delegate been set.
23581          * </p>
23582          *
23583          * @param host The View hosting the delegate.
23584          * @param child The child which requests sending the event.
23585          * @param event The event to be sent.
23586          * @return True if the event should be sent
23587          *
23588          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23589          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23590          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)23591         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23592                 AccessibilityEvent event) {
23593             return host.onRequestSendAccessibilityEventInternal(child, event);
23594         }
23595 
23596         /**
23597          * Gets the provider for managing a virtual view hierarchy rooted at this View
23598          * and reported to {@link android.accessibilityservice.AccessibilityService}s
23599          * that explore the window content.
23600          * <p>
23601          * The default implementation behaves as
23602          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23603          * the case of no accessibility delegate been set.
23604          * </p>
23605          *
23606          * @return The provider.
23607          *
23608          * @see AccessibilityNodeProvider
23609          */
getAccessibilityNodeProvider(View host)23610         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23611             return null;
23612         }
23613 
23614         /**
23615          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23616          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23617          * This method is responsible for obtaining an accessibility node info from a
23618          * pool of reusable instances and calling
23619          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23620          * view to initialize the former.
23621          * <p>
23622          * <strong>Note:</strong> The client is responsible for recycling the obtained
23623          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23624          * creation.
23625          * </p>
23626          * <p>
23627          * The default implementation behaves as
23628          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23629          * the case of no accessibility delegate been set.
23630          * </p>
23631          * @return A populated {@link AccessibilityNodeInfo}.
23632          *
23633          * @see AccessibilityNodeInfo
23634          *
23635          * @hide
23636          */
createAccessibilityNodeInfo(View host)23637         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23638             return host.createAccessibilityNodeInfoInternal();
23639         }
23640     }
23641 
23642     private class MatchIdPredicate implements Predicate<View> {
23643         public int mId;
23644 
23645         @Override
apply(View view)23646         public boolean apply(View view) {
23647             return (view.mID == mId);
23648         }
23649     }
23650 
23651     private class MatchLabelForPredicate implements Predicate<View> {
23652         private int mLabeledId;
23653 
23654         @Override
apply(View view)23655         public boolean apply(View view) {
23656             return (view.mLabelForId == mLabeledId);
23657         }
23658     }
23659 
23660     private class SendViewStateChangedAccessibilityEvent implements Runnable {
23661         private int mChangeTypes = 0;
23662         private boolean mPosted;
23663         private boolean mPostedWithDelay;
23664         private long mLastEventTimeMillis;
23665 
23666         @Override
run()23667         public void run() {
23668             mPosted = false;
23669             mPostedWithDelay = false;
23670             mLastEventTimeMillis = SystemClock.uptimeMillis();
23671             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23672                 final AccessibilityEvent event = AccessibilityEvent.obtain();
23673                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23674                 event.setContentChangeTypes(mChangeTypes);
23675                 sendAccessibilityEventUnchecked(event);
23676             }
23677             mChangeTypes = 0;
23678         }
23679 
runOrPost(int changeType)23680         public void runOrPost(int changeType) {
23681             mChangeTypes |= changeType;
23682 
23683             // If this is a live region or the child of a live region, collect
23684             // all events from this frame and send them on the next frame.
23685             if (inLiveRegion()) {
23686                 // If we're already posted with a delay, remove that.
23687                 if (mPostedWithDelay) {
23688                     removeCallbacks(this);
23689                     mPostedWithDelay = false;
23690                 }
23691                 // Only post if we're not already posted.
23692                 if (!mPosted) {
23693                     post(this);
23694                     mPosted = true;
23695                 }
23696                 return;
23697             }
23698 
23699             if (mPosted) {
23700                 return;
23701             }
23702 
23703             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23704             final long minEventIntevalMillis =
23705                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23706             if (timeSinceLastMillis >= minEventIntevalMillis) {
23707                 removeCallbacks(this);
23708                 run();
23709             } else {
23710                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23711                 mPostedWithDelay = true;
23712             }
23713         }
23714     }
23715 
inLiveRegion()23716     private boolean inLiveRegion() {
23717         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23718             return true;
23719         }
23720 
23721         ViewParent parent = getParent();
23722         while (parent instanceof View) {
23723             if (((View) parent).getAccessibilityLiveRegion()
23724                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23725                 return true;
23726             }
23727             parent = parent.getParent();
23728         }
23729 
23730         return false;
23731     }
23732 
23733     /**
23734      * Dump all private flags in readable format, useful for documentation and
23735      * sanity checking.
23736      */
dumpFlags()23737     private static void dumpFlags() {
23738         final HashMap<String, String> found = Maps.newHashMap();
23739         try {
23740             for (Field field : View.class.getDeclaredFields()) {
23741                 final int modifiers = field.getModifiers();
23742                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23743                     if (field.getType().equals(int.class)) {
23744                         final int value = field.getInt(null);
23745                         dumpFlag(found, field.getName(), value);
23746                     } else if (field.getType().equals(int[].class)) {
23747                         final int[] values = (int[]) field.get(null);
23748                         for (int i = 0; i < values.length; i++) {
23749                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23750                         }
23751                     }
23752                 }
23753             }
23754         } catch (IllegalAccessException e) {
23755             throw new RuntimeException(e);
23756         }
23757 
23758         final ArrayList<String> keys = Lists.newArrayList();
23759         keys.addAll(found.keySet());
23760         Collections.sort(keys);
23761         for (String key : keys) {
23762             Log.d(VIEW_LOG_TAG, found.get(key));
23763         }
23764     }
23765 
dumpFlag(HashMap<String, String> found, String name, int value)23766     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23767         // Sort flags by prefix, then by bits, always keeping unique keys
23768         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23769         final int prefix = name.indexOf('_');
23770         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23771         final String output = bits + " " + name;
23772         found.put(key, output);
23773     }
23774 
23775     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)23776     public void encode(@NonNull ViewHierarchyEncoder stream) {
23777         stream.beginObject(this);
23778         encodeProperties(stream);
23779         stream.endObject();
23780     }
23781 
23782     /** {@hide} */
23783     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)23784     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23785         Object resolveId = ViewDebug.resolveId(getContext(), mID);
23786         if (resolveId instanceof String) {
23787             stream.addProperty("id", (String) resolveId);
23788         } else {
23789             stream.addProperty("id", mID);
23790         }
23791 
23792         stream.addProperty("misc:transformation.alpha",
23793                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23794         stream.addProperty("misc:transitionName", getTransitionName());
23795 
23796         // layout
23797         stream.addProperty("layout:left", mLeft);
23798         stream.addProperty("layout:right", mRight);
23799         stream.addProperty("layout:top", mTop);
23800         stream.addProperty("layout:bottom", mBottom);
23801         stream.addProperty("layout:width", getWidth());
23802         stream.addProperty("layout:height", getHeight());
23803         stream.addProperty("layout:layoutDirection", getLayoutDirection());
23804         stream.addProperty("layout:layoutRtl", isLayoutRtl());
23805         stream.addProperty("layout:hasTransientState", hasTransientState());
23806         stream.addProperty("layout:baseline", getBaseline());
23807 
23808         // layout params
23809         ViewGroup.LayoutParams layoutParams = getLayoutParams();
23810         if (layoutParams != null) {
23811             stream.addPropertyKey("layoutParams");
23812             layoutParams.encode(stream);
23813         }
23814 
23815         // scrolling
23816         stream.addProperty("scrolling:scrollX", mScrollX);
23817         stream.addProperty("scrolling:scrollY", mScrollY);
23818 
23819         // padding
23820         stream.addProperty("padding:paddingLeft", mPaddingLeft);
23821         stream.addProperty("padding:paddingRight", mPaddingRight);
23822         stream.addProperty("padding:paddingTop", mPaddingTop);
23823         stream.addProperty("padding:paddingBottom", mPaddingBottom);
23824         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23825         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23826         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23827         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23828         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23829 
23830         // measurement
23831         stream.addProperty("measurement:minHeight", mMinHeight);
23832         stream.addProperty("measurement:minWidth", mMinWidth);
23833         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23834         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23835 
23836         // drawing
23837         stream.addProperty("drawing:elevation", getElevation());
23838         stream.addProperty("drawing:translationX", getTranslationX());
23839         stream.addProperty("drawing:translationY", getTranslationY());
23840         stream.addProperty("drawing:translationZ", getTranslationZ());
23841         stream.addProperty("drawing:rotation", getRotation());
23842         stream.addProperty("drawing:rotationX", getRotationX());
23843         stream.addProperty("drawing:rotationY", getRotationY());
23844         stream.addProperty("drawing:scaleX", getScaleX());
23845         stream.addProperty("drawing:scaleY", getScaleY());
23846         stream.addProperty("drawing:pivotX", getPivotX());
23847         stream.addProperty("drawing:pivotY", getPivotY());
23848         stream.addProperty("drawing:opaque", isOpaque());
23849         stream.addProperty("drawing:alpha", getAlpha());
23850         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23851         stream.addProperty("drawing:shadow", hasShadow());
23852         stream.addProperty("drawing:solidColor", getSolidColor());
23853         stream.addProperty("drawing:layerType", mLayerType);
23854         stream.addProperty("drawing:willNotDraw", willNotDraw());
23855         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23856         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23857         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23858         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23859 
23860         // focus
23861         stream.addProperty("focus:hasFocus", hasFocus());
23862         stream.addProperty("focus:isFocused", isFocused());
23863         stream.addProperty("focus:isFocusable", isFocusable());
23864         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23865 
23866         stream.addProperty("misc:clickable", isClickable());
23867         stream.addProperty("misc:pressed", isPressed());
23868         stream.addProperty("misc:selected", isSelected());
23869         stream.addProperty("misc:touchMode", isInTouchMode());
23870         stream.addProperty("misc:hovered", isHovered());
23871         stream.addProperty("misc:activated", isActivated());
23872 
23873         stream.addProperty("misc:visibility", getVisibility());
23874         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23875         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23876 
23877         stream.addProperty("misc:enabled", isEnabled());
23878         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23879         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23880 
23881         // theme attributes
23882         Resources.Theme theme = getContext().getTheme();
23883         if (theme != null) {
23884             stream.addPropertyKey("theme");
23885             theme.encode(stream);
23886         }
23887 
23888         // view attribute information
23889         int n = mAttributes != null ? mAttributes.length : 0;
23890         stream.addProperty("meta:__attrCount__", n/2);
23891         for (int i = 0; i < n; i += 2) {
23892             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23893         }
23894 
23895         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23896 
23897         // text
23898         stream.addProperty("text:textDirection", getTextDirection());
23899         stream.addProperty("text:textAlignment", getTextAlignment());
23900 
23901         // accessibility
23902         CharSequence contentDescription = getContentDescription();
23903         stream.addProperty("accessibility:contentDescription",
23904                 contentDescription == null ? "" : contentDescription.toString());
23905         stream.addProperty("accessibility:labelFor", getLabelFor());
23906         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23907     }
23908 
23909     /**
23910      * Determine if this view is rendered on a round wearable device and is the main view
23911      * on the screen.
23912      */
shouldDrawRoundScrollbar()23913     boolean shouldDrawRoundScrollbar() {
23914         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
23915             return false;
23916         }
23917 
23918         final View rootView = getRootView();
23919         final WindowInsets insets = getRootWindowInsets();
23920 
23921         int height = getHeight();
23922         int width = getWidth();
23923         int displayHeight = rootView.getHeight();
23924         int displayWidth = rootView.getWidth();
23925 
23926         if (height != displayHeight || width != displayWidth) {
23927             return false;
23928         }
23929 
23930         getLocationInWindow(mAttachInfo.mTmpLocation);
23931         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
23932                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
23933     }
23934 }
23935