• 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.Color;
44 import android.graphics.Insets;
45 import android.graphics.Interpolator;
46 import android.graphics.LinearGradient;
47 import android.graphics.Matrix;
48 import android.graphics.Outline;
49 import android.graphics.Paint;
50 import android.graphics.PixelFormat;
51 import android.graphics.Point;
52 import android.graphics.PorterDuff;
53 import android.graphics.PorterDuffXfermode;
54 import android.graphics.Rect;
55 import android.graphics.RectF;
56 import android.graphics.Region;
57 import android.graphics.Shader;
58 import android.graphics.drawable.ColorDrawable;
59 import android.graphics.drawable.Drawable;
60 import android.hardware.display.DisplayManagerGlobal;
61 import android.os.Build.VERSION_CODES;
62 import android.os.Bundle;
63 import android.os.Handler;
64 import android.os.IBinder;
65 import android.os.Parcel;
66 import android.os.Parcelable;
67 import android.os.RemoteException;
68 import android.os.SystemClock;
69 import android.os.SystemProperties;
70 import android.os.Trace;
71 import android.text.TextUtils;
72 import android.util.AttributeSet;
73 import android.util.FloatProperty;
74 import android.util.LayoutDirection;
75 import android.util.Log;
76 import android.util.LongSparseLongArray;
77 import android.util.Pools.SynchronizedPool;
78 import android.util.Property;
79 import android.util.SparseArray;
80 import android.util.StateSet;
81 import android.util.SuperNotCalledException;
82 import android.util.TypedValue;
83 import android.view.ContextMenu.ContextMenuInfo;
84 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
85 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86 import android.view.AccessibilityIterators.TextSegmentIterator;
87 import android.view.AccessibilityIterators.WordTextSegmentIterator;
88 import android.view.accessibility.AccessibilityEvent;
89 import android.view.accessibility.AccessibilityEventSource;
90 import android.view.accessibility.AccessibilityManager;
91 import android.view.accessibility.AccessibilityNodeInfo;
92 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
93 import android.view.accessibility.AccessibilityNodeProvider;
94 import android.view.animation.Animation;
95 import android.view.animation.AnimationUtils;
96 import android.view.animation.Transformation;
97 import android.view.inputmethod.EditorInfo;
98 import android.view.inputmethod.InputConnection;
99 import android.view.inputmethod.InputMethodManager;
100 import android.widget.Checkable;
101 import android.widget.FrameLayout;
102 import android.widget.ScrollBarDrawable;
103 import static android.os.Build.VERSION_CODES.*;
104 import static java.lang.Math.max;
105 
106 import com.android.internal.R;
107 import com.android.internal.util.Predicate;
108 import com.android.internal.view.menu.MenuBuilder;
109 import com.android.internal.widget.ScrollBarUtils;
110 import com.google.android.collect.Lists;
111 import com.google.android.collect.Maps;
112 
113 import java.lang.NullPointerException;
114 import java.lang.annotation.Retention;
115 import java.lang.annotation.RetentionPolicy;
116 import java.lang.ref.WeakReference;
117 import java.lang.reflect.Field;
118 import java.lang.reflect.InvocationTargetException;
119 import java.lang.reflect.Method;
120 import java.lang.reflect.Modifier;
121 import java.util.ArrayList;
122 import java.util.Arrays;
123 import java.util.Collections;
124 import java.util.HashMap;
125 import java.util.List;
126 import java.util.Locale;
127 import java.util.Map;
128 import java.util.concurrent.CopyOnWriteArrayList;
129 import java.util.concurrent.atomic.AtomicInteger;
130 
131 /**
132  * <p>
133  * This class represents the basic building block for user interface components. A View
134  * occupies a rectangular area on the screen and is responsible for drawing and
135  * event handling. View is the base class for <em>widgets</em>, which are
136  * used to create interactive UI components (buttons, text fields, etc.). The
137  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
138  * are invisible containers that hold other Views (or other ViewGroups) and define
139  * their layout properties.
140  * </p>
141  *
142  * <div class="special reference">
143  * <h3>Developer Guides</h3>
144  * <p>For information about using this class to develop your application's user interface,
145  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
146  * </div>
147  *
148  * <a name="Using"></a>
149  * <h3>Using Views</h3>
150  * <p>
151  * All of the views in a window are arranged in a single tree. You can add views
152  * either from code or by specifying a tree of views in one or more XML layout
153  * files. There are many specialized subclasses of views that act as controls or
154  * are capable of displaying text, images, or other content.
155  * </p>
156  * <p>
157  * Once you have created a tree of views, there are typically a few types of
158  * common operations you may wish to perform:
159  * <ul>
160  * <li><strong>Set properties:</strong> for example setting the text of a
161  * {@link android.widget.TextView}. The available properties and the methods
162  * that set them will vary among the different subclasses of views. Note that
163  * properties that are known at build time can be set in the XML layout
164  * files.</li>
165  * <li><strong>Set focus:</strong> The framework will handle moving focus in
166  * response to user input. To force focus to a specific view, call
167  * {@link #requestFocus}.</li>
168  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
169  * that will be notified when something interesting happens to the view. For
170  * example, all views will let you set a listener to be notified when the view
171  * gains or loses focus. You can register such a listener using
172  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
173  * Other view subclasses offer more specialized listeners. For example, a Button
174  * exposes a listener to notify clients when the button is clicked.</li>
175  * <li><strong>Set visibility:</strong> You can hide or show views using
176  * {@link #setVisibility(int)}.</li>
177  * </ul>
178  * </p>
179  * <p><em>
180  * Note: The Android framework is responsible for measuring, laying out and
181  * drawing views. You should not call methods that perform these actions on
182  * views yourself unless you are actually implementing a
183  * {@link android.view.ViewGroup}.
184  * </em></p>
185  *
186  * <a name="Lifecycle"></a>
187  * <h3>Implementing a Custom View</h3>
188  *
189  * <p>
190  * To implement a custom view, you will usually begin by providing overrides for
191  * some of the standard methods that the framework calls on all views. You do
192  * not need to override all of these methods. In fact, you can start by just
193  * overriding {@link #onDraw(android.graphics.Canvas)}.
194  * <table border="2" width="85%" align="center" cellpadding="5">
195  *     <thead>
196  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
197  *     </thead>
198  *
199  *     <tbody>
200  *     <tr>
201  *         <td rowspan="2">Creation</td>
202  *         <td>Constructors</td>
203  *         <td>There is a form of the constructor that are called when the view
204  *         is created from code and a form that is called when the view is
205  *         inflated from a layout file. The second form should parse and apply
206  *         any attributes defined in the layout file.
207  *         </td>
208  *     </tr>
209  *     <tr>
210  *         <td><code>{@link #onFinishInflate()}</code></td>
211  *         <td>Called after a view and all of its children has been inflated
212  *         from XML.</td>
213  *     </tr>
214  *
215  *     <tr>
216  *         <td rowspan="3">Layout</td>
217  *         <td><code>{@link #onMeasure(int, int)}</code></td>
218  *         <td>Called to determine the size requirements for this view and all
219  *         of its children.
220  *         </td>
221  *     </tr>
222  *     <tr>
223  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
224  *         <td>Called when this view should assign a size and position to all
225  *         of its children.
226  *         </td>
227  *     </tr>
228  *     <tr>
229  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
230  *         <td>Called when the size of this view has changed.
231  *         </td>
232  *     </tr>
233  *
234  *     <tr>
235  *         <td>Drawing</td>
236  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
237  *         <td>Called when the view should render its content.
238  *         </td>
239  *     </tr>
240  *
241  *     <tr>
242  *         <td rowspan="4">Event processing</td>
243  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
244  *         <td>Called when a new hardware key event occurs.
245  *         </td>
246  *     </tr>
247  *     <tr>
248  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
249  *         <td>Called when a hardware key up event occurs.
250  *         </td>
251  *     </tr>
252  *     <tr>
253  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
254  *         <td>Called when a trackball motion event occurs.
255  *         </td>
256  *     </tr>
257  *     <tr>
258  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
259  *         <td>Called when a touch screen motion event occurs.
260  *         </td>
261  *     </tr>
262  *
263  *     <tr>
264  *         <td rowspan="2">Focus</td>
265  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
266  *         <td>Called when the view gains or loses focus.
267  *         </td>
268  *     </tr>
269  *
270  *     <tr>
271  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
272  *         <td>Called when the window containing the view gains or loses focus.
273  *         </td>
274  *     </tr>
275  *
276  *     <tr>
277  *         <td rowspan="3">Attaching</td>
278  *         <td><code>{@link #onAttachedToWindow()}</code></td>
279  *         <td>Called when the view is attached to a window.
280  *         </td>
281  *     </tr>
282  *
283  *     <tr>
284  *         <td><code>{@link #onDetachedFromWindow}</code></td>
285  *         <td>Called when the view is detached from its window.
286  *         </td>
287  *     </tr>
288  *
289  *     <tr>
290  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
291  *         <td>Called when the visibility of the window containing the view
292  *         has changed.
293  *         </td>
294  *     </tr>
295  *     </tbody>
296  *
297  * </table>
298  * </p>
299  *
300  * <a name="IDs"></a>
301  * <h3>IDs</h3>
302  * Views may have an integer id associated with them. These ids are typically
303  * assigned in the layout XML files, and are used to find specific views within
304  * the view tree. A common pattern is to:
305  * <ul>
306  * <li>Define a Button in the layout file and assign it a unique ID.
307  * <pre>
308  * &lt;Button
309  *     android:id="@+id/my_button"
310  *     android:layout_width="wrap_content"
311  *     android:layout_height="wrap_content"
312  *     android:text="@string/my_button_text"/&gt;
313  * </pre></li>
314  * <li>From the onCreate method of an Activity, find the Button
315  * <pre class="prettyprint">
316  *      Button myButton = (Button) findViewById(R.id.my_button);
317  * </pre></li>
318  * </ul>
319  * <p>
320  * View IDs need not be unique throughout the tree, but it is good practice to
321  * ensure that they are at least unique within the part of the tree you are
322  * searching.
323  * </p>
324  *
325  * <a name="Position"></a>
326  * <h3>Position</h3>
327  * <p>
328  * The geometry of a view is that of a rectangle. A view has a location,
329  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
330  * two dimensions, expressed as a width and a height. The unit for location
331  * and dimensions is the pixel.
332  * </p>
333  *
334  * <p>
335  * It is possible to retrieve the location of a view by invoking the methods
336  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
337  * coordinate of the rectangle representing the view. The latter returns the
338  * top, or Y, coordinate of the rectangle representing the view. These methods
339  * both return the location of the view relative to its parent. For instance,
340  * when getLeft() returns 20, that means the view is located 20 pixels to the
341  * right of the left edge of its direct parent.
342  * </p>
343  *
344  * <p>
345  * In addition, several convenience methods are offered to avoid unnecessary
346  * computations, namely {@link #getRight()} and {@link #getBottom()}.
347  * These methods return the coordinates of the right and bottom edges of the
348  * rectangle representing the view. For instance, calling {@link #getRight()}
349  * is similar to the following computation: <code>getLeft() + getWidth()</code>
350  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
351  * </p>
352  *
353  * <a name="SizePaddingMargins"></a>
354  * <h3>Size, padding and margins</h3>
355  * <p>
356  * The size of a view is expressed with a width and a height. A view actually
357  * possess two pairs of width and height values.
358  * </p>
359  *
360  * <p>
361  * The first pair is known as <em>measured width</em> and
362  * <em>measured height</em>. These dimensions define how big a view wants to be
363  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
364  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
365  * and {@link #getMeasuredHeight()}.
366  * </p>
367  *
368  * <p>
369  * The second pair is simply known as <em>width</em> and <em>height</em>, or
370  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
371  * dimensions define the actual size of the view on screen, at drawing time and
372  * after layout. These values may, but do not have to, be different from the
373  * measured width and height. The width and height can be obtained by calling
374  * {@link #getWidth()} and {@link #getHeight()}.
375  * </p>
376  *
377  * <p>
378  * To measure its dimensions, a view takes into account its padding. The padding
379  * is expressed in pixels for the left, top, right and bottom parts of the view.
380  * Padding can be used to offset the content of the view by a specific amount of
381  * pixels. For instance, a left padding of 2 will push the view's content by
382  * 2 pixels to the right of the left edge. Padding can be set using the
383  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
384  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
385  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
386  * {@link #getPaddingEnd()}.
387  * </p>
388  *
389  * <p>
390  * Even though a view can define a padding, it does not provide any support for
391  * margins. However, view groups provide such a support. Refer to
392  * {@link android.view.ViewGroup} and
393  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
394  * </p>
395  *
396  * <a name="Layout"></a>
397  * <h3>Layout</h3>
398  * <p>
399  * Layout is a two pass process: a measure pass and a layout pass. The measuring
400  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
401  * of the view tree. Each view pushes dimension specifications down the tree
402  * during the recursion. At the end of the measure pass, every view has stored
403  * its measurements. The second pass happens in
404  * {@link #layout(int,int,int,int)} and is also top-down. During
405  * this pass each parent is responsible for positioning all of its children
406  * using the sizes computed in the measure pass.
407  * </p>
408  *
409  * <p>
410  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
411  * {@link #getMeasuredHeight()} values must be set, along with those for all of
412  * that view's descendants. A view's measured width and measured height values
413  * must respect the constraints imposed by the view's parents. This guarantees
414  * that at the end of the measure pass, all parents accept all of their
415  * children's measurements. A parent view may call measure() more than once on
416  * its children. For example, the parent may measure each child once with
417  * unspecified dimensions to find out how big they want to be, then call
418  * measure() on them again with actual numbers if the sum of all the children's
419  * unconstrained sizes is too big or too small.
420  * </p>
421  *
422  * <p>
423  * The measure pass uses two classes to communicate dimensions. The
424  * {@link MeasureSpec} class is used by views to tell their parents how they
425  * want to be measured and positioned. The base LayoutParams class just
426  * describes how big the view wants to be for both width and height. For each
427  * dimension, it can specify one of:
428  * <ul>
429  * <li> an exact number
430  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
431  * (minus padding)
432  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
433  * enclose its content (plus padding).
434  * </ul>
435  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
436  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
437  * an X and Y value.
438  * </p>
439  *
440  * <p>
441  * MeasureSpecs are used to push requirements down the tree from parent to
442  * child. A MeasureSpec can be in one of three modes:
443  * <ul>
444  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
445  * of a child view. For example, a LinearLayout may call measure() on its child
446  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
447  * tall the child view wants to be given a width of 240 pixels.
448  * <li>EXACTLY: This is used by the parent to impose an exact size on the
449  * child. The child must use this size, and guarantee that all of its
450  * descendants will fit within this size.
451  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
452  * child. The child must guarantee that it and all of its descendants will fit
453  * within this size.
454  * </ul>
455  * </p>
456  *
457  * <p>
458  * To initiate a layout, call {@link #requestLayout}. This method is typically
459  * called by a view on itself when it believes that is can no longer fit within
460  * its current bounds.
461  * </p>
462  *
463  * <a name="Drawing"></a>
464  * <h3>Drawing</h3>
465  * <p>
466  * Drawing is handled by walking the tree and recording the drawing commands of
467  * any View that needs to update. After this, the drawing commands of the
468  * entire tree are issued to screen, clipped to the newly damaged area.
469  * </p>
470  *
471  * <p>
472  * The tree is largely recorded and drawn in order, with parents drawn before
473  * (i.e., behind) their children, with siblings drawn in the order they appear
474  * in the tree. If you set a background drawable for a View, then the View will
475  * draw it before calling back to its <code>onDraw()</code> method. The child
476  * drawing order can be overridden with
477  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
478  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
479  * </p>
480  *
481  * <p>
482  * To force a view to draw, call {@link #invalidate()}.
483  * </p>
484  *
485  * <a name="EventHandlingThreading"></a>
486  * <h3>Event Handling and Threading</h3>
487  * <p>
488  * The basic cycle of a view is as follows:
489  * <ol>
490  * <li>An event comes in and is dispatched to the appropriate view. The view
491  * handles the event and notifies any listeners.</li>
492  * <li>If in the course of processing the event, the view's bounds may need
493  * to be changed, the view will call {@link #requestLayout()}.</li>
494  * <li>Similarly, if in the course of processing the event the view's appearance
495  * may need to be changed, the view will call {@link #invalidate()}.</li>
496  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
497  * the framework will take care of measuring, laying out, and drawing the tree
498  * as appropriate.</li>
499  * </ol>
500  * </p>
501  *
502  * <p><em>Note: The entire view tree is single threaded. You must always be on
503  * the UI thread when calling any method on any view.</em>
504  * If you are doing work on other threads and want to update the state of a view
505  * from that thread, you should use a {@link Handler}.
506  * </p>
507  *
508  * <a name="FocusHandling"></a>
509  * <h3>Focus Handling</h3>
510  * <p>
511  * The framework will handle routine focus movement in response to user input.
512  * This includes changing the focus as views are removed or hidden, or as new
513  * views become available. Views indicate their willingness to take focus
514  * through the {@link #isFocusable} method. To change whether a view can take
515  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
516  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
517  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
518  * </p>
519  * <p>
520  * Focus movement is based on an algorithm which finds the nearest neighbor in a
521  * given direction. In rare cases, the default algorithm may not match the
522  * intended behavior of the developer. In these situations, you can provide
523  * explicit overrides by using these XML attributes in the layout file:
524  * <pre>
525  * nextFocusDown
526  * nextFocusLeft
527  * nextFocusRight
528  * nextFocusUp
529  * </pre>
530  * </p>
531  *
532  *
533  * <p>
534  * To get a particular view to take focus, call {@link #requestFocus()}.
535  * </p>
536  *
537  * <a name="TouchMode"></a>
538  * <h3>Touch Mode</h3>
539  * <p>
540  * When a user is navigating a user interface via directional keys such as a D-pad, it is
541  * necessary to give focus to actionable items such as buttons so the user can see
542  * what will take input.  If the device has touch capabilities, however, and the user
543  * begins interacting with the interface by touching it, it is no longer necessary to
544  * always highlight, or give focus to, a particular view.  This motivates a mode
545  * for interaction named 'touch mode'.
546  * </p>
547  * <p>
548  * For a touch capable device, once the user touches the screen, the device
549  * will enter touch mode.  From this point onward, only views for which
550  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
551  * Other views that are touchable, like buttons, will not take focus when touched; they will
552  * only fire the on click listeners.
553  * </p>
554  * <p>
555  * Any time a user hits a directional key, such as a D-pad direction, the view device will
556  * exit touch mode, and find a view to take focus, so that the user may resume interacting
557  * with the user interface without touching the screen again.
558  * </p>
559  * <p>
560  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
561  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
562  * </p>
563  *
564  * <a name="Scrolling"></a>
565  * <h3>Scrolling</h3>
566  * <p>
567  * The framework provides basic support for views that wish to internally
568  * scroll their content. This includes keeping track of the X and Y scroll
569  * offset as well as mechanisms for drawing scrollbars. See
570  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
571  * {@link #awakenScrollBars()} for more details.
572  * </p>
573  *
574  * <a name="Tags"></a>
575  * <h3>Tags</h3>
576  * <p>
577  * Unlike IDs, tags are not used to identify views. Tags are essentially an
578  * extra piece of information that can be associated with a view. They are most
579  * often used as a convenience to store data related to views in the views
580  * themselves rather than by putting them in a separate structure.
581  * </p>
582  * <p>
583  * Tags may be specified with character sequence values in layout XML as either
584  * a single tag using the {@link android.R.styleable#View_tag android:tag}
585  * attribute or multiple tags using the {@code <tag>} child element:
586  * <pre>
587  *     &ltView ...
588  *           android:tag="@string/mytag_value" /&gt;
589  *     &ltView ...&gt;
590  *         &lttag android:id="@+id/mytag"
591  *              android:value="@string/mytag_value" /&gt;
592  *     &lt/View>
593  * </pre>
594  * </p>
595  * <p>
596  * Tags may also be specified with arbitrary objects from code using
597  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
598  * </p>
599  *
600  * <a name="Themes"></a>
601  * <h3>Themes</h3>
602  * <p>
603  * By default, Views are created using the theme of the Context object supplied
604  * to their constructor; however, a different theme may be specified by using
605  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
606  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
607  * code.
608  * </p>
609  * <p>
610  * When the {@link android.R.styleable#View_theme android:theme} attribute is
611  * used in XML, the specified theme is applied on top of the inflation
612  * context's theme (see {@link LayoutInflater}) and used for the view itself as
613  * well as any child elements.
614  * </p>
615  * <p>
616  * In the following example, both views will be created using the Material dark
617  * color scheme; however, because an overlay theme is used which only defines a
618  * subset of attributes, the value of
619  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
620  * the inflation context's theme (e.g. the Activity theme) will be preserved.
621  * <pre>
622  *     &ltLinearLayout
623  *             ...
624  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
625  *         &ltView ...&gt;
626  *     &lt/LinearLayout&gt;
627  * </pre>
628  * </p>
629  *
630  * <a name="Properties"></a>
631  * <h3>Properties</h3>
632  * <p>
633  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
634  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
635  * available both in the {@link Property} form as well as in similarly-named setter/getter
636  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
637  * be used to set persistent state associated with these rendering-related properties on the view.
638  * The properties and methods can also be used in conjunction with
639  * {@link android.animation.Animator Animator}-based animations, described more in the
640  * <a href="#Animation">Animation</a> section.
641  * </p>
642  *
643  * <a name="Animation"></a>
644  * <h3>Animation</h3>
645  * <p>
646  * Starting with Android 3.0, the preferred way of animating views is to use the
647  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
648  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
649  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
650  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
651  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
652  * makes animating these View properties particularly easy and efficient.
653  * </p>
654  * <p>
655  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
656  * You can attach an {@link Animation} object to a view using
657  * {@link #setAnimation(Animation)} or
658  * {@link #startAnimation(Animation)}. The animation can alter the scale,
659  * rotation, translation and alpha of a view over time. If the animation is
660  * attached to a view that has children, the animation will affect the entire
661  * subtree rooted by that node. When an animation is started, the framework will
662  * take care of redrawing the appropriate views until the animation completes.
663  * </p>
664  *
665  * <a name="Security"></a>
666  * <h3>Security</h3>
667  * <p>
668  * Sometimes it is essential that an application be able to verify that an action
669  * is being performed with the full knowledge and consent of the user, such as
670  * granting a permission request, making a purchase or clicking on an advertisement.
671  * Unfortunately, a malicious application could try to spoof the user into
672  * performing these actions, unaware, by concealing the intended purpose of the view.
673  * As a remedy, the framework offers a touch filtering mechanism that can be used to
674  * improve the security of views that provide access to sensitive functionality.
675  * </p><p>
676  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
677  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
678  * will discard touches that are received whenever the view's window is obscured by
679  * another visible window.  As a result, the view will not receive touches whenever a
680  * toast, dialog or other window appears above the view's window.
681  * </p><p>
682  * For more fine-grained control over security, consider overriding the
683  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
684  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
685  * </p>
686  *
687  * @attr ref android.R.styleable#View_alpha
688  * @attr ref android.R.styleable#View_background
689  * @attr ref android.R.styleable#View_clickable
690  * @attr ref android.R.styleable#View_contentDescription
691  * @attr ref android.R.styleable#View_drawingCacheQuality
692  * @attr ref android.R.styleable#View_duplicateParentState
693  * @attr ref android.R.styleable#View_id
694  * @attr ref android.R.styleable#View_requiresFadingEdge
695  * @attr ref android.R.styleable#View_fadeScrollbars
696  * @attr ref android.R.styleable#View_fadingEdgeLength
697  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
698  * @attr ref android.R.styleable#View_fitsSystemWindows
699  * @attr ref android.R.styleable#View_isScrollContainer
700  * @attr ref android.R.styleable#View_focusable
701  * @attr ref android.R.styleable#View_focusableInTouchMode
702  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
703  * @attr ref android.R.styleable#View_keepScreenOn
704  * @attr ref android.R.styleable#View_layerType
705  * @attr ref android.R.styleable#View_layoutDirection
706  * @attr ref android.R.styleable#View_longClickable
707  * @attr ref android.R.styleable#View_minHeight
708  * @attr ref android.R.styleable#View_minWidth
709  * @attr ref android.R.styleable#View_nextFocusDown
710  * @attr ref android.R.styleable#View_nextFocusLeft
711  * @attr ref android.R.styleable#View_nextFocusRight
712  * @attr ref android.R.styleable#View_nextFocusUp
713  * @attr ref android.R.styleable#View_onClick
714  * @attr ref android.R.styleable#View_padding
715  * @attr ref android.R.styleable#View_paddingBottom
716  * @attr ref android.R.styleable#View_paddingLeft
717  * @attr ref android.R.styleable#View_paddingRight
718  * @attr ref android.R.styleable#View_paddingTop
719  * @attr ref android.R.styleable#View_paddingStart
720  * @attr ref android.R.styleable#View_paddingEnd
721  * @attr ref android.R.styleable#View_saveEnabled
722  * @attr ref android.R.styleable#View_rotation
723  * @attr ref android.R.styleable#View_rotationX
724  * @attr ref android.R.styleable#View_rotationY
725  * @attr ref android.R.styleable#View_scaleX
726  * @attr ref android.R.styleable#View_scaleY
727  * @attr ref android.R.styleable#View_scrollX
728  * @attr ref android.R.styleable#View_scrollY
729  * @attr ref android.R.styleable#View_scrollbarSize
730  * @attr ref android.R.styleable#View_scrollbarStyle
731  * @attr ref android.R.styleable#View_scrollbars
732  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
733  * @attr ref android.R.styleable#View_scrollbarFadeDuration
734  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
735  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
736  * @attr ref android.R.styleable#View_scrollbarThumbVertical
737  * @attr ref android.R.styleable#View_scrollbarTrackVertical
738  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
739  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
740  * @attr ref android.R.styleable#View_stateListAnimator
741  * @attr ref android.R.styleable#View_transitionName
742  * @attr ref android.R.styleable#View_soundEffectsEnabled
743  * @attr ref android.R.styleable#View_tag
744  * @attr ref android.R.styleable#View_textAlignment
745  * @attr ref android.R.styleable#View_textDirection
746  * @attr ref android.R.styleable#View_transformPivotX
747  * @attr ref android.R.styleable#View_transformPivotY
748  * @attr ref android.R.styleable#View_translationX
749  * @attr ref android.R.styleable#View_translationY
750  * @attr ref android.R.styleable#View_translationZ
751  * @attr ref android.R.styleable#View_visibility
752  * @attr ref android.R.styleable#View_theme
753  *
754  * @see android.view.ViewGroup
755  */
756 @UiThread
757 public class View implements Drawable.Callback, KeyEvent.Callback,
758         AccessibilityEventSource {
759     private static final boolean DBG = false;
760 
761     /**
762      * The logging tag used by this class with android.util.Log.
763      */
764     protected static final String VIEW_LOG_TAG = "View";
765 
766     /**
767      * When set to true, apps will draw debugging information about their layouts.
768      *
769      * @hide
770      */
771     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
772 
773     /**
774      * When set to true, this view will save its attribute data.
775      *
776      * @hide
777      */
778     public static boolean mDebugViewAttributes = false;
779 
780     /**
781      * Used to mark a View that has no ID.
782      */
783     public static final int NO_ID = -1;
784 
785     /**
786      * Signals that compatibility booleans have been initialized according to
787      * target SDK versions.
788      */
789     private static boolean sCompatibilityDone = false;
790 
791     /**
792      * Use the old (broken) way of building MeasureSpecs.
793      */
794     private static boolean sUseBrokenMakeMeasureSpec = false;
795 
796     /**
797      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
798      */
799     static boolean sUseZeroUnspecifiedMeasureSpec = false;
800 
801     /**
802      * Ignore any optimizations using the measure cache.
803      */
804     private static boolean sIgnoreMeasureCache = false;
805 
806     /**
807      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
808      */
809     private static boolean sAlwaysRemeasureExactly = false;
810 
811     /**
812      * Relax constraints around whether setLayoutParams() must be called after
813      * modifying the layout params.
814      */
815     private static boolean sLayoutParamsAlwaysChanged = false;
816 
817     /**
818      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
819      * without throwing
820      */
821     static boolean sTextureViewIgnoresDrawableSetters = false;
822 
823     /**
824      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
825      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
826      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
827      * check is implemented for backwards compatibility.
828      *
829      * {@hide}
830      */
831     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
832 
833     /**
834      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
835      * calling setFlags.
836      */
837     private static final int NOT_FOCUSABLE = 0x00000000;
838 
839     /**
840      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
841      * setFlags.
842      */
843     private static final int FOCUSABLE = 0x00000001;
844 
845     /**
846      * Mask for use with setFlags indicating bits used for focus.
847      */
848     private static final int FOCUSABLE_MASK = 0x00000001;
849 
850     /**
851      * This view will adjust its padding to fit sytem windows (e.g. status bar)
852      */
853     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
854 
855     /** @hide */
856     @IntDef({VISIBLE, INVISIBLE, GONE})
857     @Retention(RetentionPolicy.SOURCE)
858     public @interface Visibility {}
859 
860     /**
861      * This view is visible.
862      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
863      * android:visibility}.
864      */
865     public static final int VISIBLE = 0x00000000;
866 
867     /**
868      * This view is invisible, but it still takes up space for layout purposes.
869      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
870      * android:visibility}.
871      */
872     public static final int INVISIBLE = 0x00000004;
873 
874     /**
875      * This view is invisible, and it doesn't take any space for layout
876      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
877      * android:visibility}.
878      */
879     public static final int GONE = 0x00000008;
880 
881     /**
882      * Mask for use with setFlags indicating bits used for visibility.
883      * {@hide}
884      */
885     static final int VISIBILITY_MASK = 0x0000000C;
886 
887     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
888 
889     /**
890      * This view is enabled. Interpretation varies by subclass.
891      * Use with ENABLED_MASK when calling setFlags.
892      * {@hide}
893      */
894     static final int ENABLED = 0x00000000;
895 
896     /**
897      * This view is disabled. Interpretation varies by subclass.
898      * Use with ENABLED_MASK when calling setFlags.
899      * {@hide}
900      */
901     static final int DISABLED = 0x00000020;
902 
903    /**
904     * Mask for use with setFlags indicating bits used for indicating whether
905     * this view is enabled
906     * {@hide}
907     */
908     static final int ENABLED_MASK = 0x00000020;
909 
910     /**
911      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
912      * called and further optimizations will be performed. It is okay to have
913      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
914      * {@hide}
915      */
916     static final int WILL_NOT_DRAW = 0x00000080;
917 
918     /**
919      * Mask for use with setFlags indicating bits used for indicating whether
920      * this view is will draw
921      * {@hide}
922      */
923     static final int DRAW_MASK = 0x00000080;
924 
925     /**
926      * <p>This view doesn't show scrollbars.</p>
927      * {@hide}
928      */
929     static final int SCROLLBARS_NONE = 0x00000000;
930 
931     /**
932      * <p>This view shows horizontal scrollbars.</p>
933      * {@hide}
934      */
935     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
936 
937     /**
938      * <p>This view shows vertical scrollbars.</p>
939      * {@hide}
940      */
941     static final int SCROLLBARS_VERTICAL = 0x00000200;
942 
943     /**
944      * <p>Mask for use with setFlags indicating bits used for indicating which
945      * scrollbars are enabled.</p>
946      * {@hide}
947      */
948     static final int SCROLLBARS_MASK = 0x00000300;
949 
950     /**
951      * Indicates that the view should filter touches when its window is obscured.
952      * Refer to the class comments for more information about this security feature.
953      * {@hide}
954      */
955     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
956 
957     /**
958      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
959      * that they are optional and should be skipped if the window has
960      * requested system UI flags that ignore those insets for layout.
961      */
962     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
963 
964     /**
965      * <p>This view doesn't show fading edges.</p>
966      * {@hide}
967      */
968     static final int FADING_EDGE_NONE = 0x00000000;
969 
970     /**
971      * <p>This view shows horizontal fading edges.</p>
972      * {@hide}
973      */
974     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
975 
976     /**
977      * <p>This view shows vertical fading edges.</p>
978      * {@hide}
979      */
980     static final int FADING_EDGE_VERTICAL = 0x00002000;
981 
982     /**
983      * <p>Mask for use with setFlags indicating bits used for indicating which
984      * fading edges are enabled.</p>
985      * {@hide}
986      */
987     static final int FADING_EDGE_MASK = 0x00003000;
988 
989     /**
990      * <p>Indicates this view can be clicked. When clickable, a View reacts
991      * to clicks by notifying the OnClickListener.<p>
992      * {@hide}
993      */
994     static final int CLICKABLE = 0x00004000;
995 
996     /**
997      * <p>Indicates this view is caching its drawing into a bitmap.</p>
998      * {@hide}
999      */
1000     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1001 
1002     /**
1003      * <p>Indicates that no icicle should be saved for this view.<p>
1004      * {@hide}
1005      */
1006     static final int SAVE_DISABLED = 0x000010000;
1007 
1008     /**
1009      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1010      * property.</p>
1011      * {@hide}
1012      */
1013     static final int SAVE_DISABLED_MASK = 0x000010000;
1014 
1015     /**
1016      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1017      * {@hide}
1018      */
1019     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1020 
1021     /**
1022      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1023      * {@hide}
1024      */
1025     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1026 
1027     /** @hide */
1028     @Retention(RetentionPolicy.SOURCE)
1029     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1030     public @interface DrawingCacheQuality {}
1031 
1032     /**
1033      * <p>Enables low quality mode for the drawing cache.</p>
1034      */
1035     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1036 
1037     /**
1038      * <p>Enables high quality mode for the drawing cache.</p>
1039      */
1040     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1041 
1042     /**
1043      * <p>Enables automatic quality mode for the drawing cache.</p>
1044      */
1045     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1046 
1047     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1048             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1049     };
1050 
1051     /**
1052      * <p>Mask for use with setFlags indicating bits used for the cache
1053      * quality property.</p>
1054      * {@hide}
1055      */
1056     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1057 
1058     /**
1059      * <p>
1060      * Indicates this view can be long clicked. When long clickable, a View
1061      * reacts to long clicks by notifying the OnLongClickListener or showing a
1062      * context menu.
1063      * </p>
1064      * {@hide}
1065      */
1066     static final int LONG_CLICKABLE = 0x00200000;
1067 
1068     /**
1069      * <p>Indicates that this view gets its drawable states from its direct parent
1070      * and ignores its original internal states.</p>
1071      *
1072      * @hide
1073      */
1074     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1075 
1076     /**
1077      * <p>
1078      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1079      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1080      * OnContextClickListener.
1081      * </p>
1082      * {@hide}
1083      */
1084     static final int CONTEXT_CLICKABLE = 0x00800000;
1085 
1086 
1087     /** @hide */
1088     @IntDef({
1089         SCROLLBARS_INSIDE_OVERLAY,
1090         SCROLLBARS_INSIDE_INSET,
1091         SCROLLBARS_OUTSIDE_OVERLAY,
1092         SCROLLBARS_OUTSIDE_INSET
1093     })
1094     @Retention(RetentionPolicy.SOURCE)
1095     public @interface ScrollBarStyle {}
1096 
1097     /**
1098      * The scrollbar style to display the scrollbars inside the content area,
1099      * without increasing the padding. The scrollbars will be overlaid with
1100      * translucency on the view's content.
1101      */
1102     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1103 
1104     /**
1105      * The scrollbar style to display the scrollbars inside the padded area,
1106      * increasing the padding of the view. The scrollbars will not overlap the
1107      * content area of the view.
1108      */
1109     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1110 
1111     /**
1112      * The scrollbar style to display the scrollbars at the edge of the view,
1113      * without increasing the padding. The scrollbars will be overlaid with
1114      * translucency.
1115      */
1116     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1117 
1118     /**
1119      * The scrollbar style to display the scrollbars at the edge of the view,
1120      * increasing the padding of the view. The scrollbars will only overlap the
1121      * background, if any.
1122      */
1123     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1124 
1125     /**
1126      * Mask to check if the scrollbar style is overlay or inset.
1127      * {@hide}
1128      */
1129     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1130 
1131     /**
1132      * Mask to check if the scrollbar style is inside or outside.
1133      * {@hide}
1134      */
1135     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1136 
1137     /**
1138      * Mask for scrollbar style.
1139      * {@hide}
1140      */
1141     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1142 
1143     /**
1144      * View flag indicating that the screen should remain on while the
1145      * window containing this view is visible to the user.  This effectively
1146      * takes care of automatically setting the WindowManager's
1147      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1148      */
1149     public static final int KEEP_SCREEN_ON = 0x04000000;
1150 
1151     /**
1152      * View flag indicating whether this view should have sound effects enabled
1153      * for events such as clicking and touching.
1154      */
1155     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1156 
1157     /**
1158      * View flag indicating whether this view should have haptic feedback
1159      * enabled for events such as long presses.
1160      */
1161     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1162 
1163     /**
1164      * <p>Indicates that the view hierarchy should stop saving state when
1165      * it reaches this view.  If state saving is initiated immediately at
1166      * the view, it will be allowed.
1167      * {@hide}
1168      */
1169     static final int PARENT_SAVE_DISABLED = 0x20000000;
1170 
1171     /**
1172      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1173      * {@hide}
1174      */
1175     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1176 
1177     /** @hide */
1178     @IntDef(flag = true,
1179             value = {
1180                 FOCUSABLES_ALL,
1181                 FOCUSABLES_TOUCH_MODE
1182             })
1183     @Retention(RetentionPolicy.SOURCE)
1184     public @interface FocusableMode {}
1185 
1186     /**
1187      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1188      * should add all focusable Views regardless if they are focusable in touch mode.
1189      */
1190     public static final int FOCUSABLES_ALL = 0x00000000;
1191 
1192     /**
1193      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1194      * should add only Views focusable in touch mode.
1195      */
1196     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1197 
1198     /** @hide */
1199     @IntDef({
1200             FOCUS_BACKWARD,
1201             FOCUS_FORWARD,
1202             FOCUS_LEFT,
1203             FOCUS_UP,
1204             FOCUS_RIGHT,
1205             FOCUS_DOWN
1206     })
1207     @Retention(RetentionPolicy.SOURCE)
1208     public @interface FocusDirection {}
1209 
1210     /** @hide */
1211     @IntDef({
1212             FOCUS_LEFT,
1213             FOCUS_UP,
1214             FOCUS_RIGHT,
1215             FOCUS_DOWN
1216     })
1217     @Retention(RetentionPolicy.SOURCE)
1218     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1219 
1220     /**
1221      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1222      * item.
1223      */
1224     public static final int FOCUS_BACKWARD = 0x00000001;
1225 
1226     /**
1227      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1228      * item.
1229      */
1230     public static final int FOCUS_FORWARD = 0x00000002;
1231 
1232     /**
1233      * Use with {@link #focusSearch(int)}. Move focus to the left.
1234      */
1235     public static final int FOCUS_LEFT = 0x00000011;
1236 
1237     /**
1238      * Use with {@link #focusSearch(int)}. Move focus up.
1239      */
1240     public static final int FOCUS_UP = 0x00000021;
1241 
1242     /**
1243      * Use with {@link #focusSearch(int)}. Move focus to the right.
1244      */
1245     public static final int FOCUS_RIGHT = 0x00000042;
1246 
1247     /**
1248      * Use with {@link #focusSearch(int)}. Move focus down.
1249      */
1250     public static final int FOCUS_DOWN = 0x00000082;
1251 
1252     /**
1253      * Bits of {@link #getMeasuredWidthAndState()} and
1254      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1255      */
1256     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1257 
1258     /**
1259      * Bits of {@link #getMeasuredWidthAndState()} and
1260      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1261      */
1262     public static final int MEASURED_STATE_MASK = 0xff000000;
1263 
1264     /**
1265      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1266      * for functions that combine both width and height into a single int,
1267      * such as {@link #getMeasuredState()} and the childState argument of
1268      * {@link #resolveSizeAndState(int, int, int)}.
1269      */
1270     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1271 
1272     /**
1273      * Bit of {@link #getMeasuredWidthAndState()} and
1274      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1275      * is smaller that the space the view would like to have.
1276      */
1277     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1278 
1279     /**
1280      * Base View state sets
1281      */
1282     // Singles
1283     /**
1284      * Indicates the view has no states set. States are used with
1285      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1286      * view depending on its state.
1287      *
1288      * @see android.graphics.drawable.Drawable
1289      * @see #getDrawableState()
1290      */
1291     protected static final int[] EMPTY_STATE_SET;
1292     /**
1293      * Indicates the view is enabled. States are used with
1294      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1295      * view depending on its state.
1296      *
1297      * @see android.graphics.drawable.Drawable
1298      * @see #getDrawableState()
1299      */
1300     protected static final int[] ENABLED_STATE_SET;
1301     /**
1302      * Indicates the view is focused. States are used with
1303      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1304      * view depending on its state.
1305      *
1306      * @see android.graphics.drawable.Drawable
1307      * @see #getDrawableState()
1308      */
1309     protected static final int[] FOCUSED_STATE_SET;
1310     /**
1311      * Indicates the view is selected. States are used with
1312      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1313      * view depending on its state.
1314      *
1315      * @see android.graphics.drawable.Drawable
1316      * @see #getDrawableState()
1317      */
1318     protected static final int[] SELECTED_STATE_SET;
1319     /**
1320      * Indicates the view is pressed. States are used with
1321      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1322      * view depending on its state.
1323      *
1324      * @see android.graphics.drawable.Drawable
1325      * @see #getDrawableState()
1326      */
1327     protected static final int[] PRESSED_STATE_SET;
1328     /**
1329      * Indicates the view's window has focus. States are used with
1330      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1331      * view depending on its state.
1332      *
1333      * @see android.graphics.drawable.Drawable
1334      * @see #getDrawableState()
1335      */
1336     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1337     // Doubles
1338     /**
1339      * Indicates the view is enabled and has the focus.
1340      *
1341      * @see #ENABLED_STATE_SET
1342      * @see #FOCUSED_STATE_SET
1343      */
1344     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1345     /**
1346      * Indicates the view is enabled and selected.
1347      *
1348      * @see #ENABLED_STATE_SET
1349      * @see #SELECTED_STATE_SET
1350      */
1351     protected static final int[] ENABLED_SELECTED_STATE_SET;
1352     /**
1353      * Indicates the view is enabled and that its window has focus.
1354      *
1355      * @see #ENABLED_STATE_SET
1356      * @see #WINDOW_FOCUSED_STATE_SET
1357      */
1358     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1359     /**
1360      * Indicates the view is focused and selected.
1361      *
1362      * @see #FOCUSED_STATE_SET
1363      * @see #SELECTED_STATE_SET
1364      */
1365     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1366     /**
1367      * Indicates the view has the focus and that its window has the focus.
1368      *
1369      * @see #FOCUSED_STATE_SET
1370      * @see #WINDOW_FOCUSED_STATE_SET
1371      */
1372     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1373     /**
1374      * Indicates the view is selected and that its window has the focus.
1375      *
1376      * @see #SELECTED_STATE_SET
1377      * @see #WINDOW_FOCUSED_STATE_SET
1378      */
1379     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1380     // Triples
1381     /**
1382      * Indicates the view is enabled, focused and selected.
1383      *
1384      * @see #ENABLED_STATE_SET
1385      * @see #FOCUSED_STATE_SET
1386      * @see #SELECTED_STATE_SET
1387      */
1388     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1389     /**
1390      * Indicates the view is enabled, focused and its window has the focus.
1391      *
1392      * @see #ENABLED_STATE_SET
1393      * @see #FOCUSED_STATE_SET
1394      * @see #WINDOW_FOCUSED_STATE_SET
1395      */
1396     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1397     /**
1398      * Indicates the view is enabled, selected and its window has the focus.
1399      *
1400      * @see #ENABLED_STATE_SET
1401      * @see #SELECTED_STATE_SET
1402      * @see #WINDOW_FOCUSED_STATE_SET
1403      */
1404     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1405     /**
1406      * Indicates the view is focused, selected and its window has the focus.
1407      *
1408      * @see #FOCUSED_STATE_SET
1409      * @see #SELECTED_STATE_SET
1410      * @see #WINDOW_FOCUSED_STATE_SET
1411      */
1412     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1413     /**
1414      * Indicates the view is enabled, focused, selected and its window
1415      * has the focus.
1416      *
1417      * @see #ENABLED_STATE_SET
1418      * @see #FOCUSED_STATE_SET
1419      * @see #SELECTED_STATE_SET
1420      * @see #WINDOW_FOCUSED_STATE_SET
1421      */
1422     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1423     /**
1424      * Indicates the view is pressed and its window has the focus.
1425      *
1426      * @see #PRESSED_STATE_SET
1427      * @see #WINDOW_FOCUSED_STATE_SET
1428      */
1429     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1430     /**
1431      * Indicates the view is pressed and selected.
1432      *
1433      * @see #PRESSED_STATE_SET
1434      * @see #SELECTED_STATE_SET
1435      */
1436     protected static final int[] PRESSED_SELECTED_STATE_SET;
1437     /**
1438      * Indicates the view is pressed, selected and its window has the focus.
1439      *
1440      * @see #PRESSED_STATE_SET
1441      * @see #SELECTED_STATE_SET
1442      * @see #WINDOW_FOCUSED_STATE_SET
1443      */
1444     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1445     /**
1446      * Indicates the view is pressed and focused.
1447      *
1448      * @see #PRESSED_STATE_SET
1449      * @see #FOCUSED_STATE_SET
1450      */
1451     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1452     /**
1453      * Indicates the view is pressed, focused and its window has the focus.
1454      *
1455      * @see #PRESSED_STATE_SET
1456      * @see #FOCUSED_STATE_SET
1457      * @see #WINDOW_FOCUSED_STATE_SET
1458      */
1459     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1460     /**
1461      * Indicates the view is pressed, focused and selected.
1462      *
1463      * @see #PRESSED_STATE_SET
1464      * @see #SELECTED_STATE_SET
1465      * @see #FOCUSED_STATE_SET
1466      */
1467     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1468     /**
1469      * Indicates the view is pressed, focused, selected and its window has the focus.
1470      *
1471      * @see #PRESSED_STATE_SET
1472      * @see #FOCUSED_STATE_SET
1473      * @see #SELECTED_STATE_SET
1474      * @see #WINDOW_FOCUSED_STATE_SET
1475      */
1476     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1477     /**
1478      * Indicates the view is pressed and enabled.
1479      *
1480      * @see #PRESSED_STATE_SET
1481      * @see #ENABLED_STATE_SET
1482      */
1483     protected static final int[] PRESSED_ENABLED_STATE_SET;
1484     /**
1485      * Indicates the view is pressed, enabled and its window has the focus.
1486      *
1487      * @see #PRESSED_STATE_SET
1488      * @see #ENABLED_STATE_SET
1489      * @see #WINDOW_FOCUSED_STATE_SET
1490      */
1491     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1492     /**
1493      * Indicates the view is pressed, enabled and selected.
1494      *
1495      * @see #PRESSED_STATE_SET
1496      * @see #ENABLED_STATE_SET
1497      * @see #SELECTED_STATE_SET
1498      */
1499     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1500     /**
1501      * Indicates the view is pressed, enabled, selected and its window has the
1502      * focus.
1503      *
1504      * @see #PRESSED_STATE_SET
1505      * @see #ENABLED_STATE_SET
1506      * @see #SELECTED_STATE_SET
1507      * @see #WINDOW_FOCUSED_STATE_SET
1508      */
1509     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1510     /**
1511      * Indicates the view is pressed, enabled and focused.
1512      *
1513      * @see #PRESSED_STATE_SET
1514      * @see #ENABLED_STATE_SET
1515      * @see #FOCUSED_STATE_SET
1516      */
1517     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1518     /**
1519      * Indicates the view is pressed, enabled, focused and its window has the
1520      * focus.
1521      *
1522      * @see #PRESSED_STATE_SET
1523      * @see #ENABLED_STATE_SET
1524      * @see #FOCUSED_STATE_SET
1525      * @see #WINDOW_FOCUSED_STATE_SET
1526      */
1527     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1528     /**
1529      * Indicates the view is pressed, enabled, focused and selected.
1530      *
1531      * @see #PRESSED_STATE_SET
1532      * @see #ENABLED_STATE_SET
1533      * @see #SELECTED_STATE_SET
1534      * @see #FOCUSED_STATE_SET
1535      */
1536     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1537     /**
1538      * Indicates the view is pressed, enabled, focused, selected and its window
1539      * has the focus.
1540      *
1541      * @see #PRESSED_STATE_SET
1542      * @see #ENABLED_STATE_SET
1543      * @see #SELECTED_STATE_SET
1544      * @see #FOCUSED_STATE_SET
1545      * @see #WINDOW_FOCUSED_STATE_SET
1546      */
1547     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1548 
1549     static {
1550         EMPTY_STATE_SET = StateSet.get(0);
1551 
1552         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1553 
1554         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1555         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1556                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1557 
1558         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1559         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1560                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1561         FOCUSED_SELECTED_STATE_SET = StateSet.get(
1562                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1563         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1564                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1565                         | StateSet.VIEW_STATE_FOCUSED);
1566 
1567         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1568         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1569                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1570         ENABLED_SELECTED_STATE_SET = StateSet.get(
1571                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1572         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1573                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1574                         | StateSet.VIEW_STATE_ENABLED);
1575         ENABLED_FOCUSED_STATE_SET = StateSet.get(
1576                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1577         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1578                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1579                         | StateSet.VIEW_STATE_ENABLED);
1580         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1581                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1582                         | StateSet.VIEW_STATE_ENABLED);
1583         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1584                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1585                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1586 
1587         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1588         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1589                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1590         PRESSED_SELECTED_STATE_SET = StateSet.get(
1591                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1592         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1593                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1594                         | StateSet.VIEW_STATE_PRESSED);
1595         PRESSED_FOCUSED_STATE_SET = StateSet.get(
1596                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1597         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1598                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1599                         | StateSet.VIEW_STATE_PRESSED);
1600         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1601                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1602                         | StateSet.VIEW_STATE_PRESSED);
1603         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1604                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1605                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1606         PRESSED_ENABLED_STATE_SET = StateSet.get(
1607                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1608         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1609                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1610                         | StateSet.VIEW_STATE_PRESSED);
1611         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1612                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1613                         | StateSet.VIEW_STATE_PRESSED);
1614         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1615                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1616                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1617         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1618                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1619                         | StateSet.VIEW_STATE_PRESSED);
1620         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1621                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1622                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1623         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1624                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1625                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1626         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1627                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1628                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1629                         | StateSet.VIEW_STATE_PRESSED);
1630     }
1631 
1632     /**
1633      * Accessibility event types that are dispatched for text population.
1634      */
1635     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1636             AccessibilityEvent.TYPE_VIEW_CLICKED
1637             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1638             | AccessibilityEvent.TYPE_VIEW_SELECTED
1639             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1640             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1641             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1642             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1643             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1644             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1645             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1646             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1647 
1648     /**
1649      * Temporary Rect currently for use in setBackground().  This will probably
1650      * be extended in the future to hold our own class with more than just
1651      * a Rect. :)
1652      */
1653     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1654 
1655     /**
1656      * Map used to store views' tags.
1657      */
1658     private SparseArray<Object> mKeyedTags;
1659 
1660     /**
1661      * The next available accessibility id.
1662      */
1663     private static int sNextAccessibilityViewId;
1664 
1665     /**
1666      * The animation currently associated with this view.
1667      * @hide
1668      */
1669     protected Animation mCurrentAnimation = null;
1670 
1671     /**
1672      * Width as measured during measure pass.
1673      * {@hide}
1674      */
1675     @ViewDebug.ExportedProperty(category = "measurement")
1676     int mMeasuredWidth;
1677 
1678     /**
1679      * Height as measured during measure pass.
1680      * {@hide}
1681      */
1682     @ViewDebug.ExportedProperty(category = "measurement")
1683     int mMeasuredHeight;
1684 
1685     /**
1686      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1687      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1688      * its display list. This flag, used only when hw accelerated, allows us to clear the
1689      * flag while retaining this information until it's needed (at getDisplayList() time and
1690      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1691      *
1692      * {@hide}
1693      */
1694     boolean mRecreateDisplayList = false;
1695 
1696     /**
1697      * The view's identifier.
1698      * {@hide}
1699      *
1700      * @see #setId(int)
1701      * @see #getId()
1702      */
1703     @IdRes
1704     @ViewDebug.ExportedProperty(resolveId = true)
1705     int mID = NO_ID;
1706 
1707     /**
1708      * The stable ID of this view for accessibility purposes.
1709      */
1710     int mAccessibilityViewId = NO_ID;
1711 
1712     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1713 
1714     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1715 
1716     /**
1717      * The view's tag.
1718      * {@hide}
1719      *
1720      * @see #setTag(Object)
1721      * @see #getTag()
1722      */
1723     protected Object mTag = null;
1724 
1725     // for mPrivateFlags:
1726     /** {@hide} */
1727     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1728     /** {@hide} */
1729     static final int PFLAG_FOCUSED                     = 0x00000002;
1730     /** {@hide} */
1731     static final int PFLAG_SELECTED                    = 0x00000004;
1732     /** {@hide} */
1733     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1734     /** {@hide} */
1735     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1736     /** {@hide} */
1737     static final int PFLAG_DRAWN                       = 0x00000020;
1738     /**
1739      * When this flag is set, this view is running an animation on behalf of its
1740      * children and should therefore not cancel invalidate requests, even if they
1741      * lie outside of this view's bounds.
1742      *
1743      * {@hide}
1744      */
1745     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1746     /** {@hide} */
1747     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1748     /** {@hide} */
1749     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1750     /** {@hide} */
1751     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1752     /** {@hide} */
1753     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1754     /** {@hide} */
1755     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1756     /** {@hide} */
1757     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1758 
1759     private static final int PFLAG_PRESSED             = 0x00004000;
1760 
1761     /** {@hide} */
1762     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1763     /**
1764      * Flag used to indicate that this view should be drawn once more (and only once
1765      * more) after its animation has completed.
1766      * {@hide}
1767      */
1768     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1769 
1770     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1771 
1772     /**
1773      * Indicates that the View returned true when onSetAlpha() was called and that
1774      * the alpha must be restored.
1775      * {@hide}
1776      */
1777     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1778 
1779     /**
1780      * Set by {@link #setScrollContainer(boolean)}.
1781      */
1782     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1783 
1784     /**
1785      * Set by {@link #setScrollContainer(boolean)}.
1786      */
1787     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1788 
1789     /**
1790      * View flag indicating whether this view was invalidated (fully or partially.)
1791      *
1792      * @hide
1793      */
1794     static final int PFLAG_DIRTY                       = 0x00200000;
1795 
1796     /**
1797      * View flag indicating whether this view was invalidated by an opaque
1798      * invalidate request.
1799      *
1800      * @hide
1801      */
1802     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1803 
1804     /**
1805      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1806      *
1807      * @hide
1808      */
1809     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1810 
1811     /**
1812      * Indicates whether the background is opaque.
1813      *
1814      * @hide
1815      */
1816     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1817 
1818     /**
1819      * Indicates whether the scrollbars are opaque.
1820      *
1821      * @hide
1822      */
1823     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1824 
1825     /**
1826      * Indicates whether the view is opaque.
1827      *
1828      * @hide
1829      */
1830     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1831 
1832     /**
1833      * Indicates a prepressed state;
1834      * the short time between ACTION_DOWN and recognizing
1835      * a 'real' press. Prepressed is used to recognize quick taps
1836      * even when they are shorter than ViewConfiguration.getTapTimeout().
1837      *
1838      * @hide
1839      */
1840     private static final int PFLAG_PREPRESSED          = 0x02000000;
1841 
1842     /**
1843      * Indicates whether the view is temporarily detached.
1844      *
1845      * @hide
1846      */
1847     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1848 
1849     /**
1850      * Indicates that we should awaken scroll bars once attached
1851      *
1852      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1853      * during window attachment and it is no longer needed. Feel free to repurpose it.
1854      *
1855      * @hide
1856      */
1857     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1858 
1859     /**
1860      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1861      * @hide
1862      */
1863     private static final int PFLAG_HOVERED             = 0x10000000;
1864 
1865     /**
1866      * no longer needed, should be reused
1867      */
1868     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1869 
1870     /** {@hide} */
1871     static final int PFLAG_ACTIVATED                   = 0x40000000;
1872 
1873     /**
1874      * Indicates that this view was specifically invalidated, not just dirtied because some
1875      * child view was invalidated. The flag is used to determine when we need to recreate
1876      * a view's display list (as opposed to just returning a reference to its existing
1877      * display list).
1878      *
1879      * @hide
1880      */
1881     static final int PFLAG_INVALIDATED                 = 0x80000000;
1882 
1883     /**
1884      * Masks for mPrivateFlags2, as generated by dumpFlags():
1885      *
1886      * |-------|-------|-------|-------|
1887      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1888      *                                1  PFLAG2_DRAG_HOVERED
1889      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1890      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1891      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1892      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1893      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1894      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1895      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1896      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1897      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1898      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1899      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1900      *                         111       PFLAG2_TEXT_DIRECTION_MASK
1901      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1902      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1903      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1904      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1905      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1906      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1907      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1908      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1909      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1910      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1911      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1912      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1913      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1914      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1915      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1916      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1917      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1918      *     1                             PFLAG2_VIEW_QUICK_REJECTED
1919      *    1                              PFLAG2_PADDING_RESOLVED
1920      *   1                               PFLAG2_DRAWABLE_RESOLVED
1921      *  1                                PFLAG2_HAS_TRANSIENT_STATE
1922      * |-------|-------|-------|-------|
1923      */
1924 
1925     /**
1926      * Indicates that this view has reported that it can accept the current drag's content.
1927      * Cleared when the drag operation concludes.
1928      * @hide
1929      */
1930     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1931 
1932     /**
1933      * Indicates that this view is currently directly under the drag location in a
1934      * drag-and-drop operation involving content that it can accept.  Cleared when
1935      * the drag exits the view, or when the drag operation concludes.
1936      * @hide
1937      */
1938     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1939 
1940     /** @hide */
1941     @IntDef({
1942         LAYOUT_DIRECTION_LTR,
1943         LAYOUT_DIRECTION_RTL,
1944         LAYOUT_DIRECTION_INHERIT,
1945         LAYOUT_DIRECTION_LOCALE
1946     })
1947     @Retention(RetentionPolicy.SOURCE)
1948     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1949     public @interface LayoutDir {}
1950 
1951     /** @hide */
1952     @IntDef({
1953         LAYOUT_DIRECTION_LTR,
1954         LAYOUT_DIRECTION_RTL
1955     })
1956     @Retention(RetentionPolicy.SOURCE)
1957     public @interface ResolvedLayoutDir {}
1958 
1959     /**
1960      * A flag to indicate that the layout direction of this view has not been defined yet.
1961      * @hide
1962      */
1963     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1964 
1965     /**
1966      * Horizontal layout direction of this view is from Left to Right.
1967      * Use with {@link #setLayoutDirection}.
1968      */
1969     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1970 
1971     /**
1972      * Horizontal layout direction of this view is from Right to Left.
1973      * Use with {@link #setLayoutDirection}.
1974      */
1975     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1976 
1977     /**
1978      * Horizontal layout direction of this view is inherited from its parent.
1979      * Use with {@link #setLayoutDirection}.
1980      */
1981     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1982 
1983     /**
1984      * Horizontal layout direction of this view is from deduced from the default language
1985      * script for the locale. Use with {@link #setLayoutDirection}.
1986      */
1987     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1988 
1989     /**
1990      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1991      * @hide
1992      */
1993     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1994 
1995     /**
1996      * Mask for use with private flags indicating bits used for horizontal layout direction.
1997      * @hide
1998      */
1999     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2000 
2001     /**
2002      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2003      * right-to-left direction.
2004      * @hide
2005      */
2006     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2007 
2008     /**
2009      * Indicates whether the view horizontal layout direction has been resolved.
2010      * @hide
2011      */
2012     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2013 
2014     /**
2015      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2016      * @hide
2017      */
2018     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2019             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2020 
2021     /*
2022      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2023      * flag value.
2024      * @hide
2025      */
2026     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2027             LAYOUT_DIRECTION_LTR,
2028             LAYOUT_DIRECTION_RTL,
2029             LAYOUT_DIRECTION_INHERIT,
2030             LAYOUT_DIRECTION_LOCALE
2031     };
2032 
2033     /**
2034      * Default horizontal layout direction.
2035      */
2036     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2037 
2038     /**
2039      * Default horizontal layout direction.
2040      * @hide
2041      */
2042     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2043 
2044     /**
2045      * Text direction is inherited through {@link ViewGroup}
2046      */
2047     public static final int TEXT_DIRECTION_INHERIT = 0;
2048 
2049     /**
2050      * Text direction is using "first strong algorithm". The first strong directional character
2051      * determines the paragraph direction. If there is no strong directional character, the
2052      * paragraph direction is the view's resolved layout direction.
2053      */
2054     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2055 
2056     /**
2057      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2058      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2059      * If there are neither, the paragraph direction is the view's resolved layout direction.
2060      */
2061     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2062 
2063     /**
2064      * Text direction is forced to LTR.
2065      */
2066     public static final int TEXT_DIRECTION_LTR = 3;
2067 
2068     /**
2069      * Text direction is forced to RTL.
2070      */
2071     public static final int TEXT_DIRECTION_RTL = 4;
2072 
2073     /**
2074      * Text direction is coming from the system Locale.
2075      */
2076     public static final int TEXT_DIRECTION_LOCALE = 5;
2077 
2078     /**
2079      * Text direction is using "first strong algorithm". The first strong directional character
2080      * determines the paragraph direction. If there is no strong directional character, the
2081      * paragraph direction is LTR.
2082      */
2083     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2084 
2085     /**
2086      * Text direction is using "first strong algorithm". The first strong directional character
2087      * determines the paragraph direction. If there is no strong directional character, the
2088      * paragraph direction is RTL.
2089      */
2090     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2091 
2092     /**
2093      * Default text direction is inherited
2094      */
2095     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2096 
2097     /**
2098      * Default resolved text direction
2099      * @hide
2100      */
2101     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2102 
2103     /**
2104      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2105      * @hide
2106      */
2107     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2108 
2109     /**
2110      * Mask for use with private flags indicating bits used for text direction.
2111      * @hide
2112      */
2113     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2114             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2115 
2116     /**
2117      * Array of text direction flags for mapping attribute "textDirection" to correct
2118      * flag value.
2119      * @hide
2120      */
2121     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2122             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2123             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2124             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2125             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2126             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2127             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2128             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2129             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2130     };
2131 
2132     /**
2133      * Indicates whether the view text direction has been resolved.
2134      * @hide
2135      */
2136     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2137             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2138 
2139     /**
2140      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2141      * @hide
2142      */
2143     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2144 
2145     /**
2146      * Mask for use with private flags indicating bits used for resolved text direction.
2147      * @hide
2148      */
2149     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2150             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2151 
2152     /**
2153      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2154      * @hide
2155      */
2156     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2157             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2158 
2159     /** @hide */
2160     @IntDef({
2161         TEXT_ALIGNMENT_INHERIT,
2162         TEXT_ALIGNMENT_GRAVITY,
2163         TEXT_ALIGNMENT_CENTER,
2164         TEXT_ALIGNMENT_TEXT_START,
2165         TEXT_ALIGNMENT_TEXT_END,
2166         TEXT_ALIGNMENT_VIEW_START,
2167         TEXT_ALIGNMENT_VIEW_END
2168     })
2169     @Retention(RetentionPolicy.SOURCE)
2170     public @interface TextAlignment {}
2171 
2172     /**
2173      * Default text alignment. The text alignment of this View is inherited from its parent.
2174      * Use with {@link #setTextAlignment(int)}
2175      */
2176     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2177 
2178     /**
2179      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2180      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2181      *
2182      * Use with {@link #setTextAlignment(int)}
2183      */
2184     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2185 
2186     /**
2187      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2188      *
2189      * Use with {@link #setTextAlignment(int)}
2190      */
2191     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2192 
2193     /**
2194      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2195      *
2196      * Use with {@link #setTextAlignment(int)}
2197      */
2198     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2199 
2200     /**
2201      * Center the paragraph, e.g. ALIGN_CENTER.
2202      *
2203      * Use with {@link #setTextAlignment(int)}
2204      */
2205     public static final int TEXT_ALIGNMENT_CENTER = 4;
2206 
2207     /**
2208      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2209      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2210      *
2211      * Use with {@link #setTextAlignment(int)}
2212      */
2213     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2214 
2215     /**
2216      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2217      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2218      *
2219      * Use with {@link #setTextAlignment(int)}
2220      */
2221     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2222 
2223     /**
2224      * Default text alignment is inherited
2225      */
2226     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2227 
2228     /**
2229      * Default resolved text alignment
2230      * @hide
2231      */
2232     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2233 
2234     /**
2235       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2236       * @hide
2237       */
2238     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2239 
2240     /**
2241       * Mask for use with private flags indicating bits used for text alignment.
2242       * @hide
2243       */
2244     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2245 
2246     /**
2247      * Array of text direction flags for mapping attribute "textAlignment" to correct
2248      * flag value.
2249      * @hide
2250      */
2251     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2252             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2253             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2254             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2255             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2256             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2257             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2258             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2259     };
2260 
2261     /**
2262      * Indicates whether the view text alignment has been resolved.
2263      * @hide
2264      */
2265     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2266 
2267     /**
2268      * Bit shift to get the resolved text alignment.
2269      * @hide
2270      */
2271     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2272 
2273     /**
2274      * Mask for use with private flags indicating bits used for text alignment.
2275      * @hide
2276      */
2277     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2278             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2279 
2280     /**
2281      * Indicates whether if the view text alignment has been resolved to gravity
2282      */
2283     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2284             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2285 
2286     // Accessiblity constants for mPrivateFlags2
2287 
2288     /**
2289      * Shift for the bits in {@link #mPrivateFlags2} related to the
2290      * "importantForAccessibility" attribute.
2291      */
2292     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2293 
2294     /**
2295      * Automatically determine whether a view is important for accessibility.
2296      */
2297     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2298 
2299     /**
2300      * The view is important for accessibility.
2301      */
2302     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2303 
2304     /**
2305      * The view is not important for accessibility.
2306      */
2307     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2308 
2309     /**
2310      * The view is not important for accessibility, nor are any of its
2311      * descendant views.
2312      */
2313     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2314 
2315     /**
2316      * The default whether the view is important for accessibility.
2317      */
2318     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2319 
2320     /**
2321      * Mask for obtainig the bits which specify how to determine
2322      * whether a view is important for accessibility.
2323      */
2324     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2325         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2326         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2327         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2328 
2329     /**
2330      * Shift for the bits in {@link #mPrivateFlags2} related to the
2331      * "accessibilityLiveRegion" attribute.
2332      */
2333     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2334 
2335     /**
2336      * Live region mode specifying that accessibility services should not
2337      * automatically announce changes to this view. This is the default live
2338      * region mode for most views.
2339      * <p>
2340      * Use with {@link #setAccessibilityLiveRegion(int)}.
2341      */
2342     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2343 
2344     /**
2345      * Live region mode specifying that accessibility services should announce
2346      * changes to this view.
2347      * <p>
2348      * Use with {@link #setAccessibilityLiveRegion(int)}.
2349      */
2350     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2351 
2352     /**
2353      * Live region mode specifying that accessibility services should interrupt
2354      * ongoing speech to immediately announce changes to this view.
2355      * <p>
2356      * Use with {@link #setAccessibilityLiveRegion(int)}.
2357      */
2358     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2359 
2360     /**
2361      * The default whether the view is important for accessibility.
2362      */
2363     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2364 
2365     /**
2366      * Mask for obtaining the bits which specify a view's accessibility live
2367      * region mode.
2368      */
2369     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2370             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2371             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2372 
2373     /**
2374      * Flag indicating whether a view has accessibility focus.
2375      */
2376     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2377 
2378     /**
2379      * Flag whether the accessibility state of the subtree rooted at this view changed.
2380      */
2381     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2382 
2383     /**
2384      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2385      * is used to check whether later changes to the view's transform should invalidate the
2386      * view to force the quickReject test to run again.
2387      */
2388     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2389 
2390     /**
2391      * Flag indicating that start/end padding has been resolved into left/right padding
2392      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2393      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2394      * during measurement. In some special cases this is required such as when an adapter-based
2395      * view measures prospective children without attaching them to a window.
2396      */
2397     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2398 
2399     /**
2400      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2401      */
2402     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2403 
2404     /**
2405      * Indicates that the view is tracking some sort of transient state
2406      * that the app should not need to be aware of, but that the framework
2407      * should take special care to preserve.
2408      */
2409     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2410 
2411     /**
2412      * Group of bits indicating that RTL properties resolution is done.
2413      */
2414     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2415             PFLAG2_TEXT_DIRECTION_RESOLVED |
2416             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2417             PFLAG2_PADDING_RESOLVED |
2418             PFLAG2_DRAWABLE_RESOLVED;
2419 
2420     // There are a couple of flags left in mPrivateFlags2
2421 
2422     /* End of masks for mPrivateFlags2 */
2423 
2424     /**
2425      * Masks for mPrivateFlags3, as generated by dumpFlags():
2426      *
2427      * |-------|-------|-------|-------|
2428      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2429      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2430      *                               1   PFLAG3_IS_LAID_OUT
2431      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2432      *                             1     PFLAG3_CALLED_SUPER
2433      *                            1      PFLAG3_APPLYING_INSETS
2434      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2435      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2436      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2437      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2438      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2439      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2440      *                     1             PFLAG3_SCROLL_INDICATOR_START
2441      *                    1              PFLAG3_SCROLL_INDICATOR_END
2442      *                   1               PFLAG3_ASSIST_BLOCKED
2443      *                  1                PFLAG3_POINTER_ICON_NULL
2444      *                 1                 PFLAG3_POINTER_ICON_VALUE_START
2445      *           11111111                PFLAG3_POINTER_ICON_MASK
2446      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2447      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2448      *        1                          PFLAG3_TEMPORARY_DETACH
2449      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2450      * |-------|-------|-------|-------|
2451      */
2452 
2453     /**
2454      * Flag indicating that view has a transform animation set on it. This is used to track whether
2455      * an animation is cleared between successive frames, in order to tell the associated
2456      * DisplayList to clear its animation matrix.
2457      */
2458     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2459 
2460     /**
2461      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2462      * animation is cleared between successive frames, in order to tell the associated
2463      * DisplayList to restore its alpha value.
2464      */
2465     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2466 
2467     /**
2468      * Flag indicating that the view has been through at least one layout since it
2469      * was last attached to a window.
2470      */
2471     static final int PFLAG3_IS_LAID_OUT = 0x4;
2472 
2473     /**
2474      * Flag indicating that a call to measure() was skipped and should be done
2475      * instead when layout() is invoked.
2476      */
2477     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2478 
2479     /**
2480      * Flag indicating that an overridden method correctly called down to
2481      * the superclass implementation as required by the API spec.
2482      */
2483     static final int PFLAG3_CALLED_SUPER = 0x10;
2484 
2485     /**
2486      * Flag indicating that we're in the process of applying window insets.
2487      */
2488     static final int PFLAG3_APPLYING_INSETS = 0x20;
2489 
2490     /**
2491      * Flag indicating that we're in the process of fitting system windows using the old method.
2492      */
2493     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2494 
2495     /**
2496      * Flag indicating that nested scrolling is enabled for this view.
2497      * The view will optionally cooperate with views up its parent chain to allow for
2498      * integrated nested scrolling along the same axis.
2499      */
2500     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2501 
2502     /**
2503      * Flag indicating that the bottom scroll indicator should be displayed
2504      * when this view can scroll up.
2505      */
2506     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2507 
2508     /**
2509      * Flag indicating that the bottom scroll indicator should be displayed
2510      * when this view can scroll down.
2511      */
2512     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2513 
2514     /**
2515      * Flag indicating that the left scroll indicator should be displayed
2516      * when this view can scroll left.
2517      */
2518     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2519 
2520     /**
2521      * Flag indicating that the right scroll indicator should be displayed
2522      * when this view can scroll right.
2523      */
2524     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2525 
2526     /**
2527      * Flag indicating that the start scroll indicator should be displayed
2528      * when this view can scroll in the start direction.
2529      */
2530     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2531 
2532     /**
2533      * Flag indicating that the end scroll indicator should be displayed
2534      * when this view can scroll in the end direction.
2535      */
2536     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2537 
2538     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2539 
2540     static final int SCROLL_INDICATORS_NONE = 0x0000;
2541 
2542     /**
2543      * Mask for use with setFlags indicating bits used for indicating which
2544      * scroll indicators are enabled.
2545      */
2546     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2547             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2548             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2549             | PFLAG3_SCROLL_INDICATOR_END;
2550 
2551     /**
2552      * Left-shift required to translate between public scroll indicator flags
2553      * and internal PFLAGS3 flags. When used as a right-shift, translates
2554      * PFLAGS3 flags to public flags.
2555      */
2556     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2557 
2558     /** @hide */
2559     @Retention(RetentionPolicy.SOURCE)
2560     @IntDef(flag = true,
2561             value = {
2562                     SCROLL_INDICATOR_TOP,
2563                     SCROLL_INDICATOR_BOTTOM,
2564                     SCROLL_INDICATOR_LEFT,
2565                     SCROLL_INDICATOR_RIGHT,
2566                     SCROLL_INDICATOR_START,
2567                     SCROLL_INDICATOR_END,
2568             })
2569     public @interface ScrollIndicators {}
2570 
2571     /**
2572      * Scroll indicator direction for the top edge of the view.
2573      *
2574      * @see #setScrollIndicators(int)
2575      * @see #setScrollIndicators(int, int)
2576      * @see #getScrollIndicators()
2577      */
2578     public static final int SCROLL_INDICATOR_TOP =
2579             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2580 
2581     /**
2582      * Scroll indicator direction for the bottom 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_BOTTOM =
2589             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2590 
2591     /**
2592      * Scroll indicator direction for the left 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_LEFT =
2599             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2600 
2601     /**
2602      * Scroll indicator direction for the right 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_RIGHT =
2609             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2610 
2611     /**
2612      * Scroll indicator direction for the starting edge of the view.
2613      * <p>
2614      * Resolved according to the view's layout direction, see
2615      * {@link #getLayoutDirection()} for more information.
2616      *
2617      * @see #setScrollIndicators(int)
2618      * @see #setScrollIndicators(int, int)
2619      * @see #getScrollIndicators()
2620      */
2621     public static final int SCROLL_INDICATOR_START =
2622             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2623 
2624     /**
2625      * Scroll indicator direction for the ending edge of the view.
2626      * <p>
2627      * Resolved according to the view's layout direction, see
2628      * {@link #getLayoutDirection()} for more information.
2629      *
2630      * @see #setScrollIndicators(int)
2631      * @see #setScrollIndicators(int, int)
2632      * @see #getScrollIndicators()
2633      */
2634     public static final int SCROLL_INDICATOR_END =
2635             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2636 
2637     /**
2638      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2639      * into this view.<p>
2640      */
2641     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2642 
2643     /**
2644      * The mask for use with private flags indicating bits used for pointer icon shapes.
2645      */
2646     static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2647 
2648     /**
2649      * Left-shift used for pointer icon shape values in private flags.
2650      */
2651     static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2652 
2653     /**
2654      * Value indicating no specific pointer icons.
2655      */
2656     private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2657 
2658     /**
2659      * Value indicating {@link PointerIcon.TYPE_NULL}.
2660      */
2661     private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2662 
2663     /**
2664      * The base value for other pointer icon shapes.
2665      */
2666     private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2667 
2668     /**
2669      * Whether this view has rendered elements that overlap (see {@link
2670      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2671      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2672      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2673      * determined by whatever {@link #hasOverlappingRendering()} returns.
2674      */
2675     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2676 
2677     /**
2678      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2679      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2680      */
2681     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2682 
2683     /**
2684      * Flag indicating that the view is temporarily detached from the parent view.
2685      *
2686      * @see #onStartTemporaryDetach()
2687      * @see #onFinishTemporaryDetach()
2688      */
2689     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2690 
2691     /**
2692      * Flag indicating that the view does not wish to be revealed within its parent
2693      * hierarchy when it gains focus. Expressed in the negative since the historical
2694      * default behavior is to reveal on focus; this flag suppresses that behavior.
2695      *
2696      * @see #setRevealOnFocusHint(boolean)
2697      * @see #getRevealOnFocusHint()
2698      */
2699     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2700 
2701     /* End of masks for mPrivateFlags3 */
2702 
2703     /**
2704      * Always allow a user to over-scroll this view, provided it is a
2705      * view that can scroll.
2706      *
2707      * @see #getOverScrollMode()
2708      * @see #setOverScrollMode(int)
2709      */
2710     public static final int OVER_SCROLL_ALWAYS = 0;
2711 
2712     /**
2713      * Allow a user to over-scroll this view only if the content is large
2714      * enough to meaningfully scroll, provided it is a view that can scroll.
2715      *
2716      * @see #getOverScrollMode()
2717      * @see #setOverScrollMode(int)
2718      */
2719     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2720 
2721     /**
2722      * Never allow a user to over-scroll this view.
2723      *
2724      * @see #getOverScrollMode()
2725      * @see #setOverScrollMode(int)
2726      */
2727     public static final int OVER_SCROLL_NEVER = 2;
2728 
2729     /**
2730      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2731      * requested the system UI (status bar) to be visible (the default).
2732      *
2733      * @see #setSystemUiVisibility(int)
2734      */
2735     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2736 
2737     /**
2738      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2739      * system UI to enter an unobtrusive "low profile" mode.
2740      *
2741      * <p>This is for use in games, book readers, video players, or any other
2742      * "immersive" application where the usual system chrome is deemed too distracting.
2743      *
2744      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2745      *
2746      * @see #setSystemUiVisibility(int)
2747      */
2748     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2749 
2750     /**
2751      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2752      * system navigation be temporarily hidden.
2753      *
2754      * <p>This is an even less obtrusive state than that called for by
2755      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2756      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2757      * those to disappear. This is useful (in conjunction with the
2758      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2759      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2760      * window flags) for displaying content using every last pixel on the display.
2761      *
2762      * <p>There is a limitation: because navigation controls are so important, the least user
2763      * interaction will cause them to reappear immediately.  When this happens, both
2764      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2765      * so that both elements reappear at the same time.
2766      *
2767      * @see #setSystemUiVisibility(int)
2768      */
2769     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2770 
2771     /**
2772      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2773      * into the normal fullscreen mode so that its content can take over the screen
2774      * while still allowing the user to interact with the application.
2775      *
2776      * <p>This has the same visual effect as
2777      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2778      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2779      * meaning that non-critical screen decorations (such as the status bar) will be
2780      * hidden while the user is in the View's window, focusing the experience on
2781      * that content.  Unlike the window flag, if you are using ActionBar in
2782      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2783      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2784      * hide the action bar.
2785      *
2786      * <p>This approach to going fullscreen is best used over the window flag when
2787      * it is a transient state -- that is, the application does this at certain
2788      * points in its user interaction where it wants to allow the user to focus
2789      * on content, but not as a continuous state.  For situations where the application
2790      * would like to simply stay full screen the entire time (such as a game that
2791      * wants to take over the screen), the
2792      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2793      * is usually a better approach.  The state set here will be removed by the system
2794      * in various situations (such as the user moving to another application) like
2795      * the other system UI states.
2796      *
2797      * <p>When using this flag, the application should provide some easy facility
2798      * for the user to go out of it.  A common example would be in an e-book
2799      * reader, where tapping on the screen brings back whatever screen and UI
2800      * decorations that had been hidden while the user was immersed in reading
2801      * the book.
2802      *
2803      * @see #setSystemUiVisibility(int)
2804      */
2805     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2806 
2807     /**
2808      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2809      * flags, we would like a stable view of the content insets given to
2810      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2811      * will always represent the worst case that the application can expect
2812      * as a continuous state.  In the stock Android UI this is the space for
2813      * the system bar, nav bar, and status bar, but not more transient elements
2814      * such as an input method.
2815      *
2816      * The stable layout your UI sees is based on the system UI modes you can
2817      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2818      * then you will get a stable layout for changes of the
2819      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2820      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2821      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2822      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2823      * with a stable layout.  (Note that you should avoid using
2824      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2825      *
2826      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2827      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2828      * then a hidden status bar will be considered a "stable" state for purposes
2829      * here.  This allows your UI to continually hide the status bar, while still
2830      * using the system UI flags to hide the action bar while still retaining
2831      * a stable layout.  Note that changing the window fullscreen flag will never
2832      * provide a stable layout for a clean transition.
2833      *
2834      * <p>If you are using ActionBar in
2835      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2836      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2837      * insets it adds to those given to the application.
2838      */
2839     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2840 
2841     /**
2842      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2843      * to be laid out as if it has requested
2844      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2845      * allows it to avoid artifacts when switching in and out of that mode, at
2846      * the expense that some of its user interface may be covered by screen
2847      * decorations when they are shown.  You can perform layout of your inner
2848      * UI elements to account for the navigation system UI through the
2849      * {@link #fitSystemWindows(Rect)} method.
2850      */
2851     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2852 
2853     /**
2854      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2855      * to be laid out as if it has requested
2856      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2857      * allows it to avoid artifacts when switching in and out of that mode, at
2858      * the expense that some of its user interface may be covered by screen
2859      * decorations when they are shown.  You can perform layout of your inner
2860      * UI elements to account for non-fullscreen system UI through the
2861      * {@link #fitSystemWindows(Rect)} method.
2862      */
2863     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2864 
2865     /**
2866      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2867      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2868      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2869      * user interaction.
2870      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2871      * has an effect when used in combination with that flag.</p>
2872      */
2873     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2874 
2875     /**
2876      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2877      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2878      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2879      * experience while also hiding the system bars.  If this flag is not set,
2880      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2881      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2882      * if the user swipes from the top of the screen.
2883      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2884      * system gestures, such as swiping from the top of the screen.  These transient system bars
2885      * will overlay app’s content, may have some degree of transparency, and will automatically
2886      * hide after a short timeout.
2887      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2888      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2889      * with one or both of those flags.</p>
2890      */
2891     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2892 
2893     /**
2894      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2895      * is compatible with light status bar backgrounds.
2896      *
2897      * <p>For this to take effect, the window must request
2898      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2899      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2900      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2901      *         FLAG_TRANSLUCENT_STATUS}.
2902      *
2903      * @see android.R.attr#windowLightStatusBar
2904      */
2905     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2906 
2907     /**
2908      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2909      */
2910     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2911 
2912     /**
2913      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2914      */
2915     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2916 
2917     /**
2918      * @hide
2919      *
2920      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2921      * out of the public fields to keep the undefined bits out of the developer's way.
2922      *
2923      * Flag to make the status bar not expandable.  Unless you also
2924      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2925      */
2926     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2927 
2928     /**
2929      * @hide
2930      *
2931      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2932      * out of the public fields to keep the undefined bits out of the developer's way.
2933      *
2934      * Flag to hide notification icons and scrolling ticker text.
2935      */
2936     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
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 disable incoming notification alerts.  This will not block
2945      * icons, but it will block sound, vibrating and other visual or aural notifications.
2946      */
2947     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2948 
2949     /**
2950      * @hide
2951      *
2952      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2953      * out of the public fields to keep the undefined bits out of the developer's way.
2954      *
2955      * Flag to hide only the scrolling ticker.  Note that
2956      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2957      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2958      */
2959     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2960 
2961     /**
2962      * @hide
2963      *
2964      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2965      * out of the public fields to keep the undefined bits out of the developer's way.
2966      *
2967      * Flag to hide the center system info area.
2968      */
2969     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
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 only the home button.  Don't use this
2978      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2979      */
2980     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2981 
2982     /**
2983      * @hide
2984      *
2985      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2986      * out of the public fields to keep the undefined bits out of the developer's way.
2987      *
2988      * Flag to hide only the back button. Don't use this
2989      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2990      */
2991     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2992 
2993     /**
2994      * @hide
2995      *
2996      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2997      * out of the public fields to keep the undefined bits out of the developer's way.
2998      *
2999      * Flag to hide only the clock.  You might use this if your activity has
3000      * its own clock making the status bar's clock redundant.
3001      */
3002     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3003 
3004     /**
3005      * @hide
3006      *
3007      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3008      * out of the public fields to keep the undefined bits out of the developer's way.
3009      *
3010      * Flag to hide only the recent apps button. Don't use this
3011      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3012      */
3013     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3014 
3015     /**
3016      * @hide
3017      *
3018      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3019      * out of the public fields to keep the undefined bits out of the developer's way.
3020      *
3021      * Flag to disable the global search gesture. Don't use this
3022      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3023      */
3024     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3025 
3026     /**
3027      * @hide
3028      *
3029      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3030      * out of the public fields to keep the undefined bits out of the developer's way.
3031      *
3032      * Flag to specify that the status bar is displayed in transient mode.
3033      */
3034     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
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 navigation bar is displayed in transient mode.
3043      */
3044     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
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 hidden status bar would like to be shown.
3053      */
3054     public static final int STATUS_BAR_UNHIDE = 0x10000000;
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 navigation bar would like to be shown.
3063      */
3064     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
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 status bar is displayed in translucent mode.
3073      */
3074     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
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 navigation bar is displayed in translucent mode.
3083      */
3084     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3085 
3086     /**
3087      * @hide
3088      *
3089      * Whether Recents is visible or not.
3090      */
3091     public static final int RECENT_APPS_VISIBLE = 0x00004000;
3092 
3093     /**
3094      * @hide
3095      *
3096      * Whether the TV's picture-in-picture is visible or not.
3097      */
3098     public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
3099 
3100     /**
3101      * @hide
3102      *
3103      * Makes navigation bar transparent (but not the status bar).
3104      */
3105     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3106 
3107     /**
3108      * @hide
3109      *
3110      * Makes status bar transparent (but not the navigation bar).
3111      */
3112     public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3113 
3114     /**
3115      * @hide
3116      *
3117      * Makes both status bar and navigation bar transparent.
3118      */
3119     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3120             | STATUS_BAR_TRANSPARENT;
3121 
3122     /**
3123      * @hide
3124      */
3125     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3126 
3127     /**
3128      * These are the system UI flags that can be cleared by events outside
3129      * of an application.  Currently this is just the ability to tap on the
3130      * screen while hiding the navigation bar to have it return.
3131      * @hide
3132      */
3133     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3134             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3135             | SYSTEM_UI_FLAG_FULLSCREEN;
3136 
3137     /**
3138      * Flags that can impact the layout in relation to system UI.
3139      */
3140     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3141             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3142             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3143 
3144     /** @hide */
3145     @IntDef(flag = true,
3146             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3147     @Retention(RetentionPolicy.SOURCE)
3148     public @interface FindViewFlags {}
3149 
3150     /**
3151      * Find views that render the specified text.
3152      *
3153      * @see #findViewsWithText(ArrayList, CharSequence, int)
3154      */
3155     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3156 
3157     /**
3158      * Find find views that contain the specified content description.
3159      *
3160      * @see #findViewsWithText(ArrayList, CharSequence, int)
3161      */
3162     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3163 
3164     /**
3165      * Find views that contain {@link AccessibilityNodeProvider}. Such
3166      * a View is a root of virtual view hierarchy and may contain the searched
3167      * text. If this flag is set Views with providers are automatically
3168      * added and it is a responsibility of the client to call the APIs of
3169      * the provider to determine whether the virtual tree rooted at this View
3170      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3171      * representing the virtual views with this text.
3172      *
3173      * @see #findViewsWithText(ArrayList, CharSequence, int)
3174      *
3175      * @hide
3176      */
3177     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3178 
3179     /**
3180      * The undefined cursor position.
3181      *
3182      * @hide
3183      */
3184     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3185 
3186     /**
3187      * Indicates that the screen has changed state and is now off.
3188      *
3189      * @see #onScreenStateChanged(int)
3190      */
3191     public static final int SCREEN_STATE_OFF = 0x0;
3192 
3193     /**
3194      * Indicates that the screen has changed state and is now on.
3195      *
3196      * @see #onScreenStateChanged(int)
3197      */
3198     public static final int SCREEN_STATE_ON = 0x1;
3199 
3200     /**
3201      * Indicates no axis of view scrolling.
3202      */
3203     public static final int SCROLL_AXIS_NONE = 0;
3204 
3205     /**
3206      * Indicates scrolling along the horizontal axis.
3207      */
3208     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3209 
3210     /**
3211      * Indicates scrolling along the vertical axis.
3212      */
3213     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3214 
3215     /**
3216      * Controls the over-scroll mode for this view.
3217      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3218      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3219      * and {@link #OVER_SCROLL_NEVER}.
3220      */
3221     private int mOverScrollMode;
3222 
3223     /**
3224      * The parent this view is attached to.
3225      * {@hide}
3226      *
3227      * @see #getParent()
3228      */
3229     protected ViewParent mParent;
3230 
3231     /**
3232      * {@hide}
3233      */
3234     AttachInfo mAttachInfo;
3235 
3236     /**
3237      * {@hide}
3238      */
3239     @ViewDebug.ExportedProperty(flagMapping = {
3240         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3241                 name = "FORCE_LAYOUT"),
3242         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3243                 name = "LAYOUT_REQUIRED"),
3244         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3245             name = "DRAWING_CACHE_INVALID", outputIf = false),
3246         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3247         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3248         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3249         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3250     }, formatToHexString = true)
3251     int mPrivateFlags;
3252     int mPrivateFlags2;
3253     int mPrivateFlags3;
3254 
3255     /**
3256      * This view's request for the visibility of the status bar.
3257      * @hide
3258      */
3259     @ViewDebug.ExportedProperty(flagMapping = {
3260         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3261                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3262                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3263         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3264                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3265                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3266         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3267                                 equals = SYSTEM_UI_FLAG_VISIBLE,
3268                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3269     }, formatToHexString = true)
3270     int mSystemUiVisibility;
3271 
3272     /**
3273      * Reference count for transient state.
3274      * @see #setHasTransientState(boolean)
3275      */
3276     int mTransientStateCount = 0;
3277 
3278     /**
3279      * Count of how many windows this view has been attached to.
3280      */
3281     int mWindowAttachCount;
3282 
3283     /**
3284      * The layout parameters associated with this view and used by the parent
3285      * {@link android.view.ViewGroup} to determine how this view should be
3286      * laid out.
3287      * {@hide}
3288      */
3289     protected ViewGroup.LayoutParams mLayoutParams;
3290 
3291     /**
3292      * The view flags hold various views states.
3293      * {@hide}
3294      */
3295     @ViewDebug.ExportedProperty(formatToHexString = true)
3296     int mViewFlags;
3297 
3298     static class TransformationInfo {
3299         /**
3300          * The transform matrix for the View. This transform is calculated internally
3301          * based on the translation, rotation, and scale properties.
3302          *
3303          * Do *not* use this variable directly; instead call getMatrix(), which will
3304          * load the value from the View's RenderNode.
3305          */
3306         private final Matrix mMatrix = new Matrix();
3307 
3308         /**
3309          * The inverse transform matrix for the View. This transform is calculated
3310          * internally based on the translation, rotation, and scale properties.
3311          *
3312          * Do *not* use this variable directly; instead call getInverseMatrix(),
3313          * which will load the value from the View's RenderNode.
3314          */
3315         private Matrix mInverseMatrix;
3316 
3317         /**
3318          * The opacity of the View. This is a value from 0 to 1, where 0 means
3319          * completely transparent and 1 means completely opaque.
3320          */
3321         @ViewDebug.ExportedProperty
3322         float mAlpha = 1f;
3323 
3324         /**
3325          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3326          * property only used by transitions, which is composited with the other alpha
3327          * values to calculate the final visual alpha value.
3328          */
3329         float mTransitionAlpha = 1f;
3330     }
3331 
3332     TransformationInfo mTransformationInfo;
3333 
3334     /**
3335      * Current clip bounds. to which all drawing of this view are constrained.
3336      */
3337     Rect mClipBounds = null;
3338 
3339     private boolean mLastIsOpaque;
3340 
3341     /**
3342      * The distance in pixels from the left edge of this view's parent
3343      * to the left edge of this view.
3344      * {@hide}
3345      */
3346     @ViewDebug.ExportedProperty(category = "layout")
3347     protected int mLeft;
3348     /**
3349      * The distance in pixels from the left edge of this view's parent
3350      * to the right edge of this view.
3351      * {@hide}
3352      */
3353     @ViewDebug.ExportedProperty(category = "layout")
3354     protected int mRight;
3355     /**
3356      * The distance in pixels from the top edge of this view's parent
3357      * to the top edge of this view.
3358      * {@hide}
3359      */
3360     @ViewDebug.ExportedProperty(category = "layout")
3361     protected int mTop;
3362     /**
3363      * The distance in pixels from the top edge of this view's parent
3364      * to the bottom edge of this view.
3365      * {@hide}
3366      */
3367     @ViewDebug.ExportedProperty(category = "layout")
3368     protected int mBottom;
3369 
3370     /**
3371      * The offset, in pixels, by which the content of this view is scrolled
3372      * horizontally.
3373      * {@hide}
3374      */
3375     @ViewDebug.ExportedProperty(category = "scrolling")
3376     protected int mScrollX;
3377     /**
3378      * The offset, in pixels, by which the content of this view is scrolled
3379      * vertically.
3380      * {@hide}
3381      */
3382     @ViewDebug.ExportedProperty(category = "scrolling")
3383     protected int mScrollY;
3384 
3385     /**
3386      * The left padding in pixels, that is the distance in pixels between the
3387      * left edge of this view and the left edge of its content.
3388      * {@hide}
3389      */
3390     @ViewDebug.ExportedProperty(category = "padding")
3391     protected int mPaddingLeft = 0;
3392     /**
3393      * The right padding in pixels, that is the distance in pixels between the
3394      * right edge of this view and the right edge of its content.
3395      * {@hide}
3396      */
3397     @ViewDebug.ExportedProperty(category = "padding")
3398     protected int mPaddingRight = 0;
3399     /**
3400      * The top padding in pixels, that is the distance in pixels between the
3401      * top edge of this view and the top edge of its content.
3402      * {@hide}
3403      */
3404     @ViewDebug.ExportedProperty(category = "padding")
3405     protected int mPaddingTop;
3406     /**
3407      * The bottom padding in pixels, that is the distance in pixels between the
3408      * bottom edge of this view and the bottom edge of its content.
3409      * {@hide}
3410      */
3411     @ViewDebug.ExportedProperty(category = "padding")
3412     protected int mPaddingBottom;
3413 
3414     /**
3415      * The layout insets in pixels, that is the distance in pixels between the
3416      * visible edges of this view its bounds.
3417      */
3418     private Insets mLayoutInsets;
3419 
3420     /**
3421      * Briefly describes the view and is primarily used for accessibility support.
3422      */
3423     private CharSequence mContentDescription;
3424 
3425     /**
3426      * Specifies the id of a view for which this view serves as a label for
3427      * accessibility purposes.
3428      */
3429     private int mLabelForId = View.NO_ID;
3430 
3431     /**
3432      * Predicate for matching labeled view id with its label for
3433      * accessibility purposes.
3434      */
3435     private MatchLabelForPredicate mMatchLabelForPredicate;
3436 
3437     /**
3438      * Specifies a view before which this one is visited in accessibility traversal.
3439      */
3440     private int mAccessibilityTraversalBeforeId = NO_ID;
3441 
3442     /**
3443      * Specifies a view after which this one is visited in accessibility traversal.
3444      */
3445     private int mAccessibilityTraversalAfterId = NO_ID;
3446 
3447     /**
3448      * Predicate for matching a view by its id.
3449      */
3450     private MatchIdPredicate mMatchIdPredicate;
3451 
3452     /**
3453      * Cache the paddingRight set by the user to append to the scrollbar's size.
3454      *
3455      * @hide
3456      */
3457     @ViewDebug.ExportedProperty(category = "padding")
3458     protected int mUserPaddingRight;
3459 
3460     /**
3461      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3462      *
3463      * @hide
3464      */
3465     @ViewDebug.ExportedProperty(category = "padding")
3466     protected int mUserPaddingBottom;
3467 
3468     /**
3469      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3470      *
3471      * @hide
3472      */
3473     @ViewDebug.ExportedProperty(category = "padding")
3474     protected int mUserPaddingLeft;
3475 
3476     /**
3477      * Cache the paddingStart set by the user to append to the scrollbar's size.
3478      *
3479      */
3480     @ViewDebug.ExportedProperty(category = "padding")
3481     int mUserPaddingStart;
3482 
3483     /**
3484      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3485      *
3486      */
3487     @ViewDebug.ExportedProperty(category = "padding")
3488     int mUserPaddingEnd;
3489 
3490     /**
3491      * Cache initial left padding.
3492      *
3493      * @hide
3494      */
3495     int mUserPaddingLeftInitial;
3496 
3497     /**
3498      * Cache initial right padding.
3499      *
3500      * @hide
3501      */
3502     int mUserPaddingRightInitial;
3503 
3504     /**
3505      * Default undefined padding
3506      */
3507     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3508 
3509     /**
3510      * Cache if a left padding has been defined
3511      */
3512     private boolean mLeftPaddingDefined = false;
3513 
3514     /**
3515      * Cache if a right padding has been defined
3516      */
3517     private boolean mRightPaddingDefined = false;
3518 
3519     /**
3520      * @hide
3521      */
3522     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3523     /**
3524      * @hide
3525      */
3526     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3527 
3528     private LongSparseLongArray mMeasureCache;
3529 
3530     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3531     private Drawable mBackground;
3532     private TintInfo mBackgroundTint;
3533 
3534     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3535     private ForegroundInfo mForegroundInfo;
3536 
3537     private Drawable mScrollIndicatorDrawable;
3538 
3539     /**
3540      * RenderNode used for backgrounds.
3541      * <p>
3542      * When non-null and valid, this is expected to contain an up-to-date copy
3543      * of the background drawable. It is cleared on temporary detach, and reset
3544      * on cleanup.
3545      */
3546     private RenderNode mBackgroundRenderNode;
3547 
3548     private int mBackgroundResource;
3549     private boolean mBackgroundSizeChanged;
3550 
3551     private String mTransitionName;
3552 
3553     static class TintInfo {
3554         ColorStateList mTintList;
3555         PorterDuff.Mode mTintMode;
3556         boolean mHasTintMode;
3557         boolean mHasTintList;
3558     }
3559 
3560     private static class ForegroundInfo {
3561         private Drawable mDrawable;
3562         private TintInfo mTintInfo;
3563         private int mGravity = Gravity.FILL;
3564         private boolean mInsidePadding = true;
3565         private boolean mBoundsChanged = true;
3566         private final Rect mSelfBounds = new Rect();
3567         private final Rect mOverlayBounds = new Rect();
3568     }
3569 
3570     static class ListenerInfo {
3571         /**
3572          * Listener used to dispatch focus change events.
3573          * This field should be made private, so it is hidden from the SDK.
3574          * {@hide}
3575          */
3576         protected OnFocusChangeListener mOnFocusChangeListener;
3577 
3578         /**
3579          * Listeners for layout change events.
3580          */
3581         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3582 
3583         protected OnScrollChangeListener mOnScrollChangeListener;
3584 
3585         /**
3586          * Listeners for attach events.
3587          */
3588         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3589 
3590         /**
3591          * Listener used to dispatch click events.
3592          * This field should be made private, so it is hidden from the SDK.
3593          * {@hide}
3594          */
3595         public OnClickListener mOnClickListener;
3596 
3597         /**
3598          * Listener used to dispatch long click events.
3599          * This field should be made private, so it is hidden from the SDK.
3600          * {@hide}
3601          */
3602         protected OnLongClickListener mOnLongClickListener;
3603 
3604         /**
3605          * Listener used to dispatch context click events. This field should be made private, so it
3606          * is hidden from the SDK.
3607          * {@hide}
3608          */
3609         protected OnContextClickListener mOnContextClickListener;
3610 
3611         /**
3612          * Listener used to build the context menu.
3613          * This field should be made private, so it is hidden from the SDK.
3614          * {@hide}
3615          */
3616         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3617 
3618         private OnKeyListener mOnKeyListener;
3619 
3620         private OnTouchListener mOnTouchListener;
3621 
3622         private OnHoverListener mOnHoverListener;
3623 
3624         private OnGenericMotionListener mOnGenericMotionListener;
3625 
3626         private OnDragListener mOnDragListener;
3627 
3628         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3629 
3630         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3631     }
3632 
3633     ListenerInfo mListenerInfo;
3634 
3635     // Temporary values used to hold (x,y) coordinates when delegating from the
3636     // two-arg performLongClick() method to the legacy no-arg version.
3637     private float mLongClickX = Float.NaN;
3638     private float mLongClickY = Float.NaN;
3639 
3640     /**
3641      * The application environment this view lives in.
3642      * This field should be made private, so it is hidden from the SDK.
3643      * {@hide}
3644      */
3645     @ViewDebug.ExportedProperty(deepExport = true)
3646     protected Context mContext;
3647 
3648     private final Resources mResources;
3649 
3650     private ScrollabilityCache mScrollCache;
3651 
3652     private int[] mDrawableState = null;
3653 
3654     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3655 
3656     /**
3657      * Animator that automatically runs based on state changes.
3658      */
3659     private StateListAnimator mStateListAnimator;
3660 
3661     /**
3662      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3663      * the user may specify which view to go to next.
3664      */
3665     private int mNextFocusLeftId = View.NO_ID;
3666 
3667     /**
3668      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3669      * the user may specify which view to go to next.
3670      */
3671     private int mNextFocusRightId = View.NO_ID;
3672 
3673     /**
3674      * When this view has focus and the next focus is {@link #FOCUS_UP},
3675      * the user may specify which view to go to next.
3676      */
3677     private int mNextFocusUpId = View.NO_ID;
3678 
3679     /**
3680      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3681      * the user may specify which view to go to next.
3682      */
3683     private int mNextFocusDownId = View.NO_ID;
3684 
3685     /**
3686      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3687      * the user may specify which view to go to next.
3688      */
3689     int mNextFocusForwardId = View.NO_ID;
3690 
3691     private CheckForLongPress mPendingCheckForLongPress;
3692     private CheckForTap mPendingCheckForTap = null;
3693     private PerformClick mPerformClick;
3694     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3695 
3696     private UnsetPressedState mUnsetPressedState;
3697 
3698     /**
3699      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3700      * up event while a long press is invoked as soon as the long press duration is reached, so
3701      * a long press could be performed before the tap is checked, in which case the tap's action
3702      * should not be invoked.
3703      */
3704     private boolean mHasPerformedLongPress;
3705 
3706     /**
3707      * Whether a context click button is currently pressed down. This is true when the stylus is
3708      * touching the screen and the primary button has been pressed, or if a mouse's right button is
3709      * pressed. This is false once the button is released or if the stylus has been lifted.
3710      */
3711     private boolean mInContextButtonPress;
3712 
3713     /**
3714      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3715      * true after a stylus button press has occured, when the next up event should not be recognized
3716      * as a tap.
3717      */
3718     private boolean mIgnoreNextUpEvent;
3719 
3720     /**
3721      * The minimum height of the view. We'll try our best to have the height
3722      * of this view to at least this amount.
3723      */
3724     @ViewDebug.ExportedProperty(category = "measurement")
3725     private int mMinHeight;
3726 
3727     /**
3728      * The minimum width of the view. We'll try our best to have the width
3729      * of this view to at least this amount.
3730      */
3731     @ViewDebug.ExportedProperty(category = "measurement")
3732     private int mMinWidth;
3733 
3734     /**
3735      * The delegate to handle touch events that are physically in this view
3736      * but should be handled by another view.
3737      */
3738     private TouchDelegate mTouchDelegate = null;
3739 
3740     /**
3741      * Solid color to use as a background when creating the drawing cache. Enables
3742      * the cache to use 16 bit bitmaps instead of 32 bit.
3743      */
3744     private int mDrawingCacheBackgroundColor = 0;
3745 
3746     /**
3747      * Special tree observer used when mAttachInfo is null.
3748      */
3749     private ViewTreeObserver mFloatingTreeObserver;
3750 
3751     /**
3752      * Cache the touch slop from the context that created the view.
3753      */
3754     private int mTouchSlop;
3755 
3756     /**
3757      * Object that handles automatic animation of view properties.
3758      */
3759     private ViewPropertyAnimator mAnimator = null;
3760 
3761     /**
3762      * List of registered FrameMetricsObservers.
3763      */
3764     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3765 
3766     /**
3767      * Flag indicating that a drag can cross window boundaries.  When
3768      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3769      * with this flag set, all visible applications with targetSdkVersion >=
3770      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3771      * in the drag operation and receive the dragged content.
3772      *
3773      * <p>If this is the only flag set, then the drag recipient will only have access to text data
3774      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3775      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3776      */
3777     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3778 
3779     /**
3780      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3781      * request read access to the content URI(s) contained in the {@link ClipData} object.
3782      * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3783      */
3784     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3785 
3786     /**
3787      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3788      * request write access to the content URI(s) contained in the {@link ClipData} object.
3789      * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3790      */
3791     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3792 
3793     /**
3794      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3795      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3796      * reboots until explicitly revoked with
3797      * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3798      * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3799      */
3800     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3801             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3802 
3803     /**
3804      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3805      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3806      * match against the original granted URI.
3807      * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3808      */
3809     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3810             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3811 
3812     /**
3813      * Flag indicating that the drag shadow will be opaque.  When
3814      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3815      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3816      */
3817     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3818 
3819     /**
3820      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3821      */
3822     private float mVerticalScrollFactor;
3823 
3824     /**
3825      * Position of the vertical scroll bar.
3826      */
3827     private int mVerticalScrollbarPosition;
3828 
3829     /**
3830      * Position the scroll bar at the default position as determined by the system.
3831      */
3832     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3833 
3834     /**
3835      * Position the scroll bar along the left edge.
3836      */
3837     public static final int SCROLLBAR_POSITION_LEFT = 1;
3838 
3839     /**
3840      * Position the scroll bar along the right edge.
3841      */
3842     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3843 
3844     /**
3845      * Indicates that the view does not have a layer.
3846      *
3847      * @see #getLayerType()
3848      * @see #setLayerType(int, android.graphics.Paint)
3849      * @see #LAYER_TYPE_SOFTWARE
3850      * @see #LAYER_TYPE_HARDWARE
3851      */
3852     public static final int LAYER_TYPE_NONE = 0;
3853 
3854     /**
3855      * <p>Indicates that the view has a software layer. A software layer is backed
3856      * by a bitmap and causes the view to be rendered using Android's software
3857      * rendering pipeline, even if hardware acceleration is enabled.</p>
3858      *
3859      * <p>Software layers have various usages:</p>
3860      * <p>When the application is not using hardware acceleration, a software layer
3861      * is useful to apply a specific color filter and/or blending mode and/or
3862      * translucency to a view and all its children.</p>
3863      * <p>When the application is using hardware acceleration, a software layer
3864      * is useful to render drawing primitives not supported by the hardware
3865      * accelerated pipeline. It can also be used to cache a complex view tree
3866      * into a texture and reduce the complexity of drawing operations. For instance,
3867      * when animating a complex view tree with a translation, a software layer can
3868      * be used to render the view tree only once.</p>
3869      * <p>Software layers should be avoided when the affected view tree updates
3870      * often. Every update will require to re-render the software layer, which can
3871      * potentially be slow (particularly when hardware acceleration is turned on
3872      * since the layer will have to be uploaded into a hardware texture after every
3873      * update.)</p>
3874      *
3875      * @see #getLayerType()
3876      * @see #setLayerType(int, android.graphics.Paint)
3877      * @see #LAYER_TYPE_NONE
3878      * @see #LAYER_TYPE_HARDWARE
3879      */
3880     public static final int LAYER_TYPE_SOFTWARE = 1;
3881 
3882     /**
3883      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3884      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3885      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3886      * rendering pipeline, but only if hardware acceleration is turned on for the
3887      * view hierarchy. When hardware acceleration is turned off, hardware layers
3888      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3889      *
3890      * <p>A hardware layer is useful to apply a specific color filter and/or
3891      * blending mode and/or translucency to a view and all its children.</p>
3892      * <p>A hardware layer can be used to cache a complex view tree into a
3893      * texture and reduce the complexity of drawing operations. For instance,
3894      * when animating a complex view tree with a translation, a hardware layer can
3895      * be used to render the view tree only once.</p>
3896      * <p>A hardware layer can also be used to increase the rendering quality when
3897      * rotation transformations are applied on a view. It can also be used to
3898      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3899      *
3900      * @see #getLayerType()
3901      * @see #setLayerType(int, android.graphics.Paint)
3902      * @see #LAYER_TYPE_NONE
3903      * @see #LAYER_TYPE_SOFTWARE
3904      */
3905     public static final int LAYER_TYPE_HARDWARE = 2;
3906 
3907     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3908             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3909             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3910             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3911     })
3912     int mLayerType = LAYER_TYPE_NONE;
3913     Paint mLayerPaint;
3914 
3915     /**
3916      * Set to true when drawing cache is enabled and cannot be created.
3917      *
3918      * @hide
3919      */
3920     public boolean mCachingFailed;
3921     private Bitmap mDrawingCache;
3922     private Bitmap mUnscaledDrawingCache;
3923 
3924     /**
3925      * RenderNode holding View properties, potentially holding a DisplayList of View content.
3926      * <p>
3927      * When non-null and valid, this is expected to contain an up-to-date copy
3928      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3929      * cleanup.
3930      */
3931     final RenderNode mRenderNode;
3932 
3933     /**
3934      * Set to true when the view is sending hover accessibility events because it
3935      * is the innermost hovered view.
3936      */
3937     private boolean mSendingHoverAccessibilityEvents;
3938 
3939     /**
3940      * Delegate for injecting accessibility functionality.
3941      */
3942     AccessibilityDelegate mAccessibilityDelegate;
3943 
3944     /**
3945      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3946      * and add/remove objects to/from the overlay directly through the Overlay methods.
3947      */
3948     ViewOverlay mOverlay;
3949 
3950     /**
3951      * The currently active parent view for receiving delegated nested scrolling events.
3952      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3953      * by {@link #stopNestedScroll()} at the same point where we clear
3954      * requestDisallowInterceptTouchEvent.
3955      */
3956     private ViewParent mNestedScrollingParent;
3957 
3958     /**
3959      * Consistency verifier for debugging purposes.
3960      * @hide
3961      */
3962     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3963             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3964                     new InputEventConsistencyVerifier(this, 0) : null;
3965 
3966     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3967 
3968     private int[] mTempNestedScrollConsumed;
3969 
3970     /**
3971      * An overlay is going to draw this View instead of being drawn as part of this
3972      * View's parent. mGhostView is the View in the Overlay that must be invalidated
3973      * when this view is invalidated.
3974      */
3975     GhostView mGhostView;
3976 
3977     /**
3978      * Holds pairs of adjacent attribute data: attribute name followed by its value.
3979      * @hide
3980      */
3981     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3982     public String[] mAttributes;
3983 
3984     /**
3985      * Maps a Resource id to its name.
3986      */
3987     private static SparseArray<String> mAttributeMap;
3988 
3989     /**
3990      * Queue of pending runnables. Used to postpone calls to post() until this
3991      * view is attached and has a handler.
3992      */
3993     private HandlerActionQueue mRunQueue;
3994 
3995     /**
3996      * The pointer icon when the mouse hovers on this view. The default is null.
3997      */
3998     private PointerIcon mPointerIcon;
3999 
4000     /**
4001      * @hide
4002      */
4003     String mStartActivityRequestWho;
4004 
4005     @Nullable
4006     private RoundScrollbarRenderer mRoundScrollbarRenderer;
4007 
4008     /**
4009      * Simple constructor to use when creating a view from code.
4010      *
4011      * @param context The Context the view is running in, through which it can
4012      *        access the current theme, resources, etc.
4013      */
View(Context context)4014     public View(Context context) {
4015         mContext = context;
4016         mResources = context != null ? context.getResources() : null;
4017         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4018         // Set some flags defaults
4019         mPrivateFlags2 =
4020                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4021                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4022                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4023                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4024                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4025                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4026         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4027         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4028         mUserPaddingStart = UNDEFINED_PADDING;
4029         mUserPaddingEnd = UNDEFINED_PADDING;
4030         mRenderNode = RenderNode.create(getClass().getName(), this);
4031 
4032         if (!sCompatibilityDone && context != null) {
4033             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4034 
4035             // Older apps may need this compatibility hack for measurement.
4036             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4037 
4038             // Older apps expect onMeasure() to always be called on a layout pass, regardless
4039             // of whether a layout was requested on that View.
4040             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4041 
4042             Canvas.sCompatibilityRestore = targetSdkVersion < M;
4043 
4044             // In M and newer, our widgets can pass a "hint" value in the size
4045             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4046             // know what the expected parent size is going to be, so e.g. list items can size
4047             // themselves at 1/3 the size of their container. It breaks older apps though,
4048             // specifically apps that use some popular open source libraries.
4049             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4050 
4051             // Old versions of the platform would give different results from
4052             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4053             // modes, so we always need to run an additional EXACTLY pass.
4054             sAlwaysRemeasureExactly = targetSdkVersion <= M;
4055 
4056             // Prior to N, layout params could change without requiring a
4057             // subsequent call to setLayoutParams() and they would usually
4058             // work. Partial layout breaks this assumption.
4059             sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4060 
4061             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4062             // On N+, we throw, but that breaks compatibility with apps that use these methods.
4063             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4064 
4065             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4066             // in apps so we target check it to avoid breaking existing apps.
4067             sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4068 
4069             sCompatibilityDone = true;
4070         }
4071     }
4072 
4073     /**
4074      * Constructor that is called when inflating a view from XML. This is called
4075      * when a view is being constructed from an XML file, supplying attributes
4076      * that were specified in the XML file. This version uses a default style of
4077      * 0, so the only attribute values applied are those in the Context's Theme
4078      * and the given AttributeSet.
4079      *
4080      * <p>
4081      * The method onFinishInflate() will be called after all children have been
4082      * added.
4083      *
4084      * @param context The Context the view is running in, through which it can
4085      *        access the current theme, resources, etc.
4086      * @param attrs The attributes of the XML tag that is inflating the view.
4087      * @see #View(Context, AttributeSet, int)
4088      */
4089     public View(Context context, @Nullable AttributeSet attrs) {
4090         this(context, attrs, 0);
4091     }
4092 
4093     /**
4094      * Perform inflation from XML and apply a class-specific base style from a
4095      * theme attribute. This constructor of View allows subclasses to use their
4096      * own base style when they are inflating. For example, a Button class's
4097      * constructor would call this version of the super class constructor and
4098      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4099      * allows the theme's button style to modify all of the base view attributes
4100      * (in particular its background) as well as the Button class's attributes.
4101      *
4102      * @param context The Context the view is running in, through which it can
4103      *        access the current theme, resources, etc.
4104      * @param attrs The attributes of the XML tag that is inflating the view.
4105      * @param defStyleAttr An attribute in the current theme that contains a
4106      *        reference to a style resource that supplies default values for
4107      *        the view. Can be 0 to not look for defaults.
4108      * @see #View(Context, AttributeSet)
4109      */
4110     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4111         this(context, attrs, defStyleAttr, 0);
4112     }
4113 
4114     /**
4115      * Perform inflation from XML and apply a class-specific base style from a
4116      * theme attribute or style resource. This constructor of View allows
4117      * subclasses to use their own base style when they are inflating.
4118      * <p>
4119      * When determining the final value of a particular attribute, there are
4120      * four inputs that come into play:
4121      * <ol>
4122      * <li>Any attribute values in the given AttributeSet.
4123      * <li>The style resource specified in the AttributeSet (named "style").
4124      * <li>The default style specified by <var>defStyleAttr</var>.
4125      * <li>The default style specified by <var>defStyleRes</var>.
4126      * <li>The base values in this theme.
4127      * </ol>
4128      * <p>
4129      * Each of these inputs is considered in-order, with the first listed taking
4130      * precedence over the following ones. In other words, if in the
4131      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4132      * , then the button's text will <em>always</em> be black, regardless of
4133      * what is specified in any of the styles.
4134      *
4135      * @param context The Context the view is running in, through which it can
4136      *        access the current theme, resources, etc.
4137      * @param attrs The attributes of the XML tag that is inflating the view.
4138      * @param defStyleAttr An attribute in the current theme that contains a
4139      *        reference to a style resource that supplies default values for
4140      *        the view. Can be 0 to not look for defaults.
4141      * @param defStyleRes A resource identifier of a style resource that
4142      *        supplies default values for the view, used only if
4143      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4144      *        to not look for defaults.
4145      * @see #View(Context, AttributeSet, int)
4146      */
4147     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4148         this(context);
4149 
4150         final TypedArray a = context.obtainStyledAttributes(
4151                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4152 
4153         if (mDebugViewAttributes) {
4154             saveAttributeData(attrs, a);
4155         }
4156 
4157         Drawable background = null;
4158 
4159         int leftPadding = -1;
4160         int topPadding = -1;
4161         int rightPadding = -1;
4162         int bottomPadding = -1;
4163         int startPadding = UNDEFINED_PADDING;
4164         int endPadding = UNDEFINED_PADDING;
4165 
4166         int padding = -1;
4167 
4168         int viewFlagValues = 0;
4169         int viewFlagMasks = 0;
4170 
4171         boolean setScrollContainer = false;
4172 
4173         int x = 0;
4174         int y = 0;
4175 
4176         float tx = 0;
4177         float ty = 0;
4178         float tz = 0;
4179         float elevation = 0;
4180         float rotation = 0;
4181         float rotationX = 0;
4182         float rotationY = 0;
4183         float sx = 1f;
4184         float sy = 1f;
4185         boolean transformSet = false;
4186 
4187         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4188         int overScrollMode = mOverScrollMode;
4189         boolean initializeScrollbars = false;
4190         boolean initializeScrollIndicators = false;
4191 
4192         boolean startPaddingDefined = false;
4193         boolean endPaddingDefined = false;
4194         boolean leftPaddingDefined = false;
4195         boolean rightPaddingDefined = false;
4196 
4197         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4198 
4199         final int N = a.getIndexCount();
4200         for (int i = 0; i < N; i++) {
4201             int attr = a.getIndex(i);
4202             switch (attr) {
4203                 case com.android.internal.R.styleable.View_background:
4204                     background = a.getDrawable(attr);
4205                     break;
4206                 case com.android.internal.R.styleable.View_padding:
4207                     padding = a.getDimensionPixelSize(attr, -1);
4208                     mUserPaddingLeftInitial = padding;
4209                     mUserPaddingRightInitial = padding;
4210                     leftPaddingDefined = true;
4211                     rightPaddingDefined = true;
4212                     break;
4213                  case com.android.internal.R.styleable.View_paddingLeft:
4214                     leftPadding = a.getDimensionPixelSize(attr, -1);
4215                     mUserPaddingLeftInitial = leftPadding;
4216                     leftPaddingDefined = true;
4217                     break;
4218                 case com.android.internal.R.styleable.View_paddingTop:
4219                     topPadding = a.getDimensionPixelSize(attr, -1);
4220                     break;
4221                 case com.android.internal.R.styleable.View_paddingRight:
4222                     rightPadding = a.getDimensionPixelSize(attr, -1);
4223                     mUserPaddingRightInitial = rightPadding;
4224                     rightPaddingDefined = true;
4225                     break;
4226                 case com.android.internal.R.styleable.View_paddingBottom:
4227                     bottomPadding = a.getDimensionPixelSize(attr, -1);
4228                     break;
4229                 case com.android.internal.R.styleable.View_paddingStart:
4230                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4231                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4232                     break;
4233                 case com.android.internal.R.styleable.View_paddingEnd:
4234                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4235                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4236                     break;
4237                 case com.android.internal.R.styleable.View_scrollX:
4238                     x = a.getDimensionPixelOffset(attr, 0);
4239                     break;
4240                 case com.android.internal.R.styleable.View_scrollY:
4241                     y = a.getDimensionPixelOffset(attr, 0);
4242                     break;
4243                 case com.android.internal.R.styleable.View_alpha:
4244                     setAlpha(a.getFloat(attr, 1f));
4245                     break;
4246                 case com.android.internal.R.styleable.View_transformPivotX:
4247                     setPivotX(a.getDimension(attr, 0));
4248                     break;
4249                 case com.android.internal.R.styleable.View_transformPivotY:
4250                     setPivotY(a.getDimension(attr, 0));
4251                     break;
4252                 case com.android.internal.R.styleable.View_translationX:
4253                     tx = a.getDimension(attr, 0);
4254                     transformSet = true;
4255                     break;
4256                 case com.android.internal.R.styleable.View_translationY:
4257                     ty = a.getDimension(attr, 0);
4258                     transformSet = true;
4259                     break;
4260                 case com.android.internal.R.styleable.View_translationZ:
4261                     tz = a.getDimension(attr, 0);
4262                     transformSet = true;
4263                     break;
4264                 case com.android.internal.R.styleable.View_elevation:
4265                     elevation = a.getDimension(attr, 0);
4266                     transformSet = true;
4267                     break;
4268                 case com.android.internal.R.styleable.View_rotation:
4269                     rotation = a.getFloat(attr, 0);
4270                     transformSet = true;
4271                     break;
4272                 case com.android.internal.R.styleable.View_rotationX:
4273                     rotationX = a.getFloat(attr, 0);
4274                     transformSet = true;
4275                     break;
4276                 case com.android.internal.R.styleable.View_rotationY:
4277                     rotationY = a.getFloat(attr, 0);
4278                     transformSet = true;
4279                     break;
4280                 case com.android.internal.R.styleable.View_scaleX:
4281                     sx = a.getFloat(attr, 1f);
4282                     transformSet = true;
4283                     break;
4284                 case com.android.internal.R.styleable.View_scaleY:
4285                     sy = a.getFloat(attr, 1f);
4286                     transformSet = true;
4287                     break;
4288                 case com.android.internal.R.styleable.View_id:
4289                     mID = a.getResourceId(attr, NO_ID);
4290                     break;
4291                 case com.android.internal.R.styleable.View_tag:
4292                     mTag = a.getText(attr);
4293                     break;
4294                 case com.android.internal.R.styleable.View_fitsSystemWindows:
4295                     if (a.getBoolean(attr, false)) {
4296                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
4297                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4298                     }
4299                     break;
4300                 case com.android.internal.R.styleable.View_focusable:
4301                     if (a.getBoolean(attr, false)) {
4302                         viewFlagValues |= FOCUSABLE;
4303                         viewFlagMasks |= FOCUSABLE_MASK;
4304                     }
4305                     break;
4306                 case com.android.internal.R.styleable.View_focusableInTouchMode:
4307                     if (a.getBoolean(attr, false)) {
4308                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4309                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4310                     }
4311                     break;
4312                 case com.android.internal.R.styleable.View_clickable:
4313                     if (a.getBoolean(attr, false)) {
4314                         viewFlagValues |= CLICKABLE;
4315                         viewFlagMasks |= CLICKABLE;
4316                     }
4317                     break;
4318                 case com.android.internal.R.styleable.View_longClickable:
4319                     if (a.getBoolean(attr, false)) {
4320                         viewFlagValues |= LONG_CLICKABLE;
4321                         viewFlagMasks |= LONG_CLICKABLE;
4322                     }
4323                     break;
4324                 case com.android.internal.R.styleable.View_contextClickable:
4325                     if (a.getBoolean(attr, false)) {
4326                         viewFlagValues |= CONTEXT_CLICKABLE;
4327                         viewFlagMasks |= CONTEXT_CLICKABLE;
4328                     }
4329                     break;
4330                 case com.android.internal.R.styleable.View_saveEnabled:
4331                     if (!a.getBoolean(attr, true)) {
4332                         viewFlagValues |= SAVE_DISABLED;
4333                         viewFlagMasks |= SAVE_DISABLED_MASK;
4334                     }
4335                     break;
4336                 case com.android.internal.R.styleable.View_duplicateParentState:
4337                     if (a.getBoolean(attr, false)) {
4338                         viewFlagValues |= DUPLICATE_PARENT_STATE;
4339                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
4340                     }
4341                     break;
4342                 case com.android.internal.R.styleable.View_visibility:
4343                     final int visibility = a.getInt(attr, 0);
4344                     if (visibility != 0) {
4345                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
4346                         viewFlagMasks |= VISIBILITY_MASK;
4347                     }
4348                     break;
4349                 case com.android.internal.R.styleable.View_layoutDirection:
4350                     // Clear any layout direction flags (included resolved bits) already set
4351                     mPrivateFlags2 &=
4352                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4353                     // Set the layout direction flags depending on the value of the attribute
4354                     final int layoutDirection = a.getInt(attr, -1);
4355                     final int value = (layoutDirection != -1) ?
4356                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4357                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4358                     break;
4359                 case com.android.internal.R.styleable.View_drawingCacheQuality:
4360                     final int cacheQuality = a.getInt(attr, 0);
4361                     if (cacheQuality != 0) {
4362                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4363                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4364                     }
4365                     break;
4366                 case com.android.internal.R.styleable.View_contentDescription:
4367                     setContentDescription(a.getString(attr));
4368                     break;
4369                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4370                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4371                     break;
4372                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4373                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4374                     break;
4375                 case com.android.internal.R.styleable.View_labelFor:
4376                     setLabelFor(a.getResourceId(attr, NO_ID));
4377                     break;
4378                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4379                     if (!a.getBoolean(attr, true)) {
4380                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4381                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4382                     }
4383                     break;
4384                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4385                     if (!a.getBoolean(attr, true)) {
4386                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4387                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4388                     }
4389                     break;
4390                 case R.styleable.View_scrollbars:
4391                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4392                     if (scrollbars != SCROLLBARS_NONE) {
4393                         viewFlagValues |= scrollbars;
4394                         viewFlagMasks |= SCROLLBARS_MASK;
4395                         initializeScrollbars = true;
4396                     }
4397                     break;
4398                 //noinspection deprecation
4399                 case R.styleable.View_fadingEdge:
4400                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4401                         // Ignore the attribute starting with ICS
4402                         break;
4403                     }
4404                     // With builds < ICS, fall through and apply fading edges
4405                 case R.styleable.View_requiresFadingEdge:
4406                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4407                     if (fadingEdge != FADING_EDGE_NONE) {
4408                         viewFlagValues |= fadingEdge;
4409                         viewFlagMasks |= FADING_EDGE_MASK;
4410                         initializeFadingEdgeInternal(a);
4411                     }
4412                     break;
4413                 case R.styleable.View_scrollbarStyle:
4414                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4415                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4416                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4417                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4418                     }
4419                     break;
4420                 case R.styleable.View_isScrollContainer:
4421                     setScrollContainer = true;
4422                     if (a.getBoolean(attr, false)) {
4423                         setScrollContainer(true);
4424                     }
4425                     break;
4426                 case com.android.internal.R.styleable.View_keepScreenOn:
4427                     if (a.getBoolean(attr, false)) {
4428                         viewFlagValues |= KEEP_SCREEN_ON;
4429                         viewFlagMasks |= KEEP_SCREEN_ON;
4430                     }
4431                     break;
4432                 case R.styleable.View_filterTouchesWhenObscured:
4433                     if (a.getBoolean(attr, false)) {
4434                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4435                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4436                     }
4437                     break;
4438                 case R.styleable.View_nextFocusLeft:
4439                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4440                     break;
4441                 case R.styleable.View_nextFocusRight:
4442                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4443                     break;
4444                 case R.styleable.View_nextFocusUp:
4445                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4446                     break;
4447                 case R.styleable.View_nextFocusDown:
4448                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4449                     break;
4450                 case R.styleable.View_nextFocusForward:
4451                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4452                     break;
4453                 case R.styleable.View_minWidth:
4454                     mMinWidth = a.getDimensionPixelSize(attr, 0);
4455                     break;
4456                 case R.styleable.View_minHeight:
4457                     mMinHeight = a.getDimensionPixelSize(attr, 0);
4458                     break;
4459                 case R.styleable.View_onClick:
4460                     if (context.isRestricted()) {
4461                         throw new IllegalStateException("The android:onClick attribute cannot "
4462                                 + "be used within a restricted context");
4463                     }
4464 
4465                     final String handlerName = a.getString(attr);
4466                     if (handlerName != null) {
4467                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4468                     }
4469                     break;
4470                 case R.styleable.View_overScrollMode:
4471                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4472                     break;
4473                 case R.styleable.View_verticalScrollbarPosition:
4474                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4475                     break;
4476                 case R.styleable.View_layerType:
4477                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4478                     break;
4479                 case R.styleable.View_textDirection:
4480                     // Clear any text direction flag already set
4481                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4482                     // Set the text direction flags depending on the value of the attribute
4483                     final int textDirection = a.getInt(attr, -1);
4484                     if (textDirection != -1) {
4485                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4486                     }
4487                     break;
4488                 case R.styleable.View_textAlignment:
4489                     // Clear any text alignment flag already set
4490                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4491                     // Set the text alignment flag depending on the value of the attribute
4492                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4493                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4494                     break;
4495                 case R.styleable.View_importantForAccessibility:
4496                     setImportantForAccessibility(a.getInt(attr,
4497                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4498                     break;
4499                 case R.styleable.View_accessibilityLiveRegion:
4500                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4501                     break;
4502                 case R.styleable.View_transitionName:
4503                     setTransitionName(a.getString(attr));
4504                     break;
4505                 case R.styleable.View_nestedScrollingEnabled:
4506                     setNestedScrollingEnabled(a.getBoolean(attr, false));
4507                     break;
4508                 case R.styleable.View_stateListAnimator:
4509                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4510                             a.getResourceId(attr, 0)));
4511                     break;
4512                 case R.styleable.View_backgroundTint:
4513                     // This will get applied later during setBackground().
4514                     if (mBackgroundTint == null) {
4515                         mBackgroundTint = new TintInfo();
4516                     }
4517                     mBackgroundTint.mTintList = a.getColorStateList(
4518                             R.styleable.View_backgroundTint);
4519                     mBackgroundTint.mHasTintList = true;
4520                     break;
4521                 case R.styleable.View_backgroundTintMode:
4522                     // This will get applied later during setBackground().
4523                     if (mBackgroundTint == null) {
4524                         mBackgroundTint = new TintInfo();
4525                     }
4526                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4527                             R.styleable.View_backgroundTintMode, -1), null);
4528                     mBackgroundTint.mHasTintMode = true;
4529                     break;
4530                 case R.styleable.View_outlineProvider:
4531                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4532                             PROVIDER_BACKGROUND));
4533                     break;
4534                 case R.styleable.View_foreground:
4535                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4536                         setForeground(a.getDrawable(attr));
4537                     }
4538                     break;
4539                 case R.styleable.View_foregroundGravity:
4540                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4541                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4542                     }
4543                     break;
4544                 case R.styleable.View_foregroundTintMode:
4545                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4546                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4547                     }
4548                     break;
4549                 case R.styleable.View_foregroundTint:
4550                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4551                         setForegroundTintList(a.getColorStateList(attr));
4552                     }
4553                     break;
4554                 case R.styleable.View_foregroundInsidePadding:
4555                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4556                         if (mForegroundInfo == null) {
4557                             mForegroundInfo = new ForegroundInfo();
4558                         }
4559                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4560                                 mForegroundInfo.mInsidePadding);
4561                     }
4562                     break;
4563                 case R.styleable.View_scrollIndicators:
4564                     final int scrollIndicators =
4565                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4566                                     & SCROLL_INDICATORS_PFLAG3_MASK;
4567                     if (scrollIndicators != 0) {
4568                         mPrivateFlags3 |= scrollIndicators;
4569                         initializeScrollIndicators = true;
4570                     }
4571                     break;
4572                 case R.styleable.View_pointerIcon:
4573                     final int resourceId = a.getResourceId(attr, 0);
4574                     if (resourceId != 0) {
4575                         setPointerIcon(PointerIcon.load(
4576                                 context.getResources(), resourceId));
4577                     } else {
4578                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4579                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4580                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4581                         }
4582                     }
4583                     break;
4584                 case R.styleable.View_forceHasOverlappingRendering:
4585                     if (a.peekValue(attr) != null) {
4586                         forceHasOverlappingRendering(a.getBoolean(attr, true));
4587                     }
4588                     break;
4589 
4590             }
4591         }
4592 
4593         setOverScrollMode(overScrollMode);
4594 
4595         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4596         // the resolved layout direction). Those cached values will be used later during padding
4597         // resolution.
4598         mUserPaddingStart = startPadding;
4599         mUserPaddingEnd = endPadding;
4600 
4601         if (background != null) {
4602             setBackground(background);
4603         }
4604 
4605         // setBackground above will record that padding is currently provided by the background.
4606         // If we have padding specified via xml, record that here instead and use it.
4607         mLeftPaddingDefined = leftPaddingDefined;
4608         mRightPaddingDefined = rightPaddingDefined;
4609 
4610         if (padding >= 0) {
4611             leftPadding = padding;
4612             topPadding = padding;
4613             rightPadding = padding;
4614             bottomPadding = padding;
4615             mUserPaddingLeftInitial = padding;
4616             mUserPaddingRightInitial = padding;
4617         }
4618 
4619         if (isRtlCompatibilityMode()) {
4620             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4621             // left / right padding are used if defined (meaning here nothing to do). If they are not
4622             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4623             // start / end and resolve them as left / right (layout direction is not taken into account).
4624             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4625             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4626             // defined.
4627             if (!mLeftPaddingDefined && startPaddingDefined) {
4628                 leftPadding = startPadding;
4629             }
4630             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4631             if (!mRightPaddingDefined && endPaddingDefined) {
4632                 rightPadding = endPadding;
4633             }
4634             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4635         } else {
4636             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4637             // values defined. Otherwise, left /right values are used.
4638             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4639             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4640             // defined.
4641             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4642 
4643             if (mLeftPaddingDefined && !hasRelativePadding) {
4644                 mUserPaddingLeftInitial = leftPadding;
4645             }
4646             if (mRightPaddingDefined && !hasRelativePadding) {
4647                 mUserPaddingRightInitial = rightPadding;
4648             }
4649         }
4650 
4651         internalSetPadding(
4652                 mUserPaddingLeftInitial,
4653                 topPadding >= 0 ? topPadding : mPaddingTop,
4654                 mUserPaddingRightInitial,
4655                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4656 
4657         if (viewFlagMasks != 0) {
4658             setFlags(viewFlagValues, viewFlagMasks);
4659         }
4660 
4661         if (initializeScrollbars) {
4662             initializeScrollbarsInternal(a);
4663         }
4664 
4665         if (initializeScrollIndicators) {
4666             initializeScrollIndicatorsInternal();
4667         }
4668 
4669         a.recycle();
4670 
4671         // Needs to be called after mViewFlags is set
4672         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4673             recomputePadding();
4674         }
4675 
4676         if (x != 0 || y != 0) {
4677             scrollTo(x, y);
4678         }
4679 
4680         if (transformSet) {
4681             setTranslationX(tx);
4682             setTranslationY(ty);
4683             setTranslationZ(tz);
4684             setElevation(elevation);
4685             setRotation(rotation);
4686             setRotationX(rotationX);
4687             setRotationY(rotationY);
4688             setScaleX(sx);
4689             setScaleY(sy);
4690         }
4691 
4692         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4693             setScrollContainer(true);
4694         }
4695 
4696         computeOpaqueFlags();
4697     }
4698 
4699     /**
4700      * An implementation of OnClickListener that attempts to lazily load a
4701      * named click handling method from a parent or ancestor context.
4702      */
4703     private static class DeclaredOnClickListener implements OnClickListener {
4704         private final View mHostView;
4705         private final String mMethodName;
4706 
4707         private Method mResolvedMethod;
4708         private Context mResolvedContext;
4709 
DeclaredOnClickListener(@onNull View hostView, @NonNull String methodName)4710         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4711             mHostView = hostView;
4712             mMethodName = methodName;
4713         }
4714 
4715         @Override
onClick(@onNull View v)4716         public void onClick(@NonNull View v) {
4717             if (mResolvedMethod == null) {
4718                 resolveMethod(mHostView.getContext(), mMethodName);
4719             }
4720 
4721             try {
4722                 mResolvedMethod.invoke(mResolvedContext, v);
4723             } catch (IllegalAccessException e) {
4724                 throw new IllegalStateException(
4725                         "Could not execute non-public method for android:onClick", e);
4726             } catch (InvocationTargetException e) {
4727                 throw new IllegalStateException(
4728                         "Could not execute method for android:onClick", e);
4729             }
4730         }
4731 
4732         @NonNull
resolveMethod(@ullable Context context, @NonNull String name)4733         private void resolveMethod(@Nullable Context context, @NonNull String name) {
4734             while (context != null) {
4735                 try {
4736                     if (!context.isRestricted()) {
4737                         final Method method = context.getClass().getMethod(mMethodName, View.class);
4738                         if (method != null) {
4739                             mResolvedMethod = method;
4740                             mResolvedContext = context;
4741                             return;
4742                         }
4743                     }
4744                 } catch (NoSuchMethodException e) {
4745                     // Failed to find method, keep searching up the hierarchy.
4746                 }
4747 
4748                 if (context instanceof ContextWrapper) {
4749                     context = ((ContextWrapper) context).getBaseContext();
4750                 } else {
4751                     // Can't search up the hierarchy, null out and fail.
4752                     context = null;
4753                 }
4754             }
4755 
4756             final int id = mHostView.getId();
4757             final String idText = id == NO_ID ? "" : " with id '"
4758                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4759             throw new IllegalStateException("Could not find method " + mMethodName
4760                     + "(View) in a parent or ancestor Context for android:onClick "
4761                     + "attribute defined on view " + mHostView.getClass() + idText);
4762         }
4763     }
4764 
4765     /**
4766      * Non-public constructor for use in testing
4767      */
View()4768     View() {
4769         mResources = null;
4770         mRenderNode = RenderNode.create(getClass().getName(), this);
4771     }
4772 
getAttributeMap()4773     private static SparseArray<String> getAttributeMap() {
4774         if (mAttributeMap == null) {
4775             mAttributeMap = new SparseArray<>();
4776         }
4777         return mAttributeMap;
4778     }
4779 
saveAttributeData(@ullable AttributeSet attrs, @NonNull TypedArray t)4780     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4781         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4782         final int indexCount = t.getIndexCount();
4783         final String[] attributes = new String[(attrsCount + indexCount) * 2];
4784 
4785         int i = 0;
4786 
4787         // Store raw XML attributes.
4788         for (int j = 0; j < attrsCount; ++j) {
4789             attributes[i] = attrs.getAttributeName(j);
4790             attributes[i + 1] = attrs.getAttributeValue(j);
4791             i += 2;
4792         }
4793 
4794         // Store resolved styleable attributes.
4795         final Resources res = t.getResources();
4796         final SparseArray<String> attributeMap = getAttributeMap();
4797         for (int j = 0; j < indexCount; ++j) {
4798             final int index = t.getIndex(j);
4799             if (!t.hasValueOrEmpty(index)) {
4800                 // Value is undefined. Skip it.
4801                 continue;
4802             }
4803 
4804             final int resourceId = t.getResourceId(index, 0);
4805             if (resourceId == 0) {
4806                 // Value is not a reference. Skip it.
4807                 continue;
4808             }
4809 
4810             String resourceName = attributeMap.get(resourceId);
4811             if (resourceName == null) {
4812                 try {
4813                     resourceName = res.getResourceName(resourceId);
4814                 } catch (Resources.NotFoundException e) {
4815                     resourceName = "0x" + Integer.toHexString(resourceId);
4816                 }
4817                 attributeMap.put(resourceId, resourceName);
4818             }
4819 
4820             attributes[i] = resourceName;
4821             attributes[i + 1] = t.getString(index);
4822             i += 2;
4823         }
4824 
4825         // Trim to fit contents.
4826         final String[] trimmed = new String[i];
4827         System.arraycopy(attributes, 0, trimmed, 0, i);
4828         mAttributes = trimmed;
4829     }
4830 
toString()4831     public String toString() {
4832         StringBuilder out = new StringBuilder(128);
4833         out.append(getClass().getName());
4834         out.append('{');
4835         out.append(Integer.toHexString(System.identityHashCode(this)));
4836         out.append(' ');
4837         switch (mViewFlags&VISIBILITY_MASK) {
4838             case VISIBLE: out.append('V'); break;
4839             case INVISIBLE: out.append('I'); break;
4840             case GONE: out.append('G'); break;
4841             default: out.append('.'); break;
4842         }
4843         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4844         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4845         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4846         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4847         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4848         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4849         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4850         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4851         out.append(' ');
4852         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4853         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4854         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4855         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4856             out.append('p');
4857         } else {
4858             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4859         }
4860         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4861         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4862         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4863         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4864         out.append(' ');
4865         out.append(mLeft);
4866         out.append(',');
4867         out.append(mTop);
4868         out.append('-');
4869         out.append(mRight);
4870         out.append(',');
4871         out.append(mBottom);
4872         final int id = getId();
4873         if (id != NO_ID) {
4874             out.append(" #");
4875             out.append(Integer.toHexString(id));
4876             final Resources r = mResources;
4877             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4878                 try {
4879                     String pkgname;
4880                     switch (id&0xff000000) {
4881                         case 0x7f000000:
4882                             pkgname="app";
4883                             break;
4884                         case 0x01000000:
4885                             pkgname="android";
4886                             break;
4887                         default:
4888                             pkgname = r.getResourcePackageName(id);
4889                             break;
4890                     }
4891                     String typename = r.getResourceTypeName(id);
4892                     String entryname = r.getResourceEntryName(id);
4893                     out.append(" ");
4894                     out.append(pkgname);
4895                     out.append(":");
4896                     out.append(typename);
4897                     out.append("/");
4898                     out.append(entryname);
4899                 } catch (Resources.NotFoundException e) {
4900                 }
4901             }
4902         }
4903         out.append("}");
4904         return out.toString();
4905     }
4906 
4907     /**
4908      * <p>
4909      * Initializes the fading edges from a given set of styled attributes. This
4910      * method should be called by subclasses that need fading edges and when an
4911      * instance of these subclasses is created programmatically rather than
4912      * being inflated from XML. This method is automatically called when the XML
4913      * is inflated.
4914      * </p>
4915      *
4916      * @param a the styled attributes set to initialize the fading edges from
4917      *
4918      * @removed
4919      */
initializeFadingEdge(TypedArray a)4920     protected void initializeFadingEdge(TypedArray a) {
4921         // This method probably shouldn't have been included in the SDK to begin with.
4922         // It relies on 'a' having been initialized using an attribute filter array that is
4923         // not publicly available to the SDK. The old method has been renamed
4924         // to initializeFadingEdgeInternal and hidden for framework use only;
4925         // this one initializes using defaults to make it safe to call for apps.
4926 
4927         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4928 
4929         initializeFadingEdgeInternal(arr);
4930 
4931         arr.recycle();
4932     }
4933 
4934     /**
4935      * <p>
4936      * Initializes the fading edges from a given set of styled attributes. This
4937      * method should be called by subclasses that need fading edges and when an
4938      * instance of these subclasses is created programmatically rather than
4939      * being inflated from XML. This method is automatically called when the XML
4940      * is inflated.
4941      * </p>
4942      *
4943      * @param a the styled attributes set to initialize the fading edges from
4944      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4945      */
initializeFadingEdgeInternal(TypedArray a)4946     protected void initializeFadingEdgeInternal(TypedArray a) {
4947         initScrollCache();
4948 
4949         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4950                 R.styleable.View_fadingEdgeLength,
4951                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4952     }
4953 
4954     /**
4955      * Returns the size of the vertical faded edges used to indicate that more
4956      * content in this view is visible.
4957      *
4958      * @return The size in pixels of the vertical faded edge or 0 if vertical
4959      *         faded edges are not enabled for this view.
4960      * @attr ref android.R.styleable#View_fadingEdgeLength
4961      */
getVerticalFadingEdgeLength()4962     public int getVerticalFadingEdgeLength() {
4963         if (isVerticalFadingEdgeEnabled()) {
4964             ScrollabilityCache cache = mScrollCache;
4965             if (cache != null) {
4966                 return cache.fadingEdgeLength;
4967             }
4968         }
4969         return 0;
4970     }
4971 
4972     /**
4973      * Set the size of the faded edge used to indicate that more content in this
4974      * view is available.  Will not change whether the fading edge is enabled; use
4975      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4976      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4977      * for the vertical or horizontal fading edges.
4978      *
4979      * @param length The size in pixels of the faded edge used to indicate that more
4980      *        content in this view is visible.
4981      */
setFadingEdgeLength(int length)4982     public void setFadingEdgeLength(int length) {
4983         initScrollCache();
4984         mScrollCache.fadingEdgeLength = length;
4985     }
4986 
4987     /**
4988      * Returns the size of the horizontal faded edges used to indicate that more
4989      * content in this view is visible.
4990      *
4991      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4992      *         faded edges are not enabled for this view.
4993      * @attr ref android.R.styleable#View_fadingEdgeLength
4994      */
getHorizontalFadingEdgeLength()4995     public int getHorizontalFadingEdgeLength() {
4996         if (isHorizontalFadingEdgeEnabled()) {
4997             ScrollabilityCache cache = mScrollCache;
4998             if (cache != null) {
4999                 return cache.fadingEdgeLength;
5000             }
5001         }
5002         return 0;
5003     }
5004 
5005     /**
5006      * Returns the width of the vertical scrollbar.
5007      *
5008      * @return The width in pixels of the vertical scrollbar or 0 if there
5009      *         is no vertical scrollbar.
5010      */
getVerticalScrollbarWidth()5011     public int getVerticalScrollbarWidth() {
5012         ScrollabilityCache cache = mScrollCache;
5013         if (cache != null) {
5014             ScrollBarDrawable scrollBar = cache.scrollBar;
5015             if (scrollBar != null) {
5016                 int size = scrollBar.getSize(true);
5017                 if (size <= 0) {
5018                     size = cache.scrollBarSize;
5019                 }
5020                 return size;
5021             }
5022             return 0;
5023         }
5024         return 0;
5025     }
5026 
5027     /**
5028      * Returns the height of the horizontal scrollbar.
5029      *
5030      * @return The height in pixels of the horizontal scrollbar or 0 if
5031      *         there is no horizontal scrollbar.
5032      */
getHorizontalScrollbarHeight()5033     protected int getHorizontalScrollbarHeight() {
5034         ScrollabilityCache cache = mScrollCache;
5035         if (cache != null) {
5036             ScrollBarDrawable scrollBar = cache.scrollBar;
5037             if (scrollBar != null) {
5038                 int size = scrollBar.getSize(false);
5039                 if (size <= 0) {
5040                     size = cache.scrollBarSize;
5041                 }
5042                 return size;
5043             }
5044             return 0;
5045         }
5046         return 0;
5047     }
5048 
5049     /**
5050      * <p>
5051      * Initializes the scrollbars from a given set of styled attributes. This
5052      * method should be called by subclasses that need scrollbars and when an
5053      * instance of these subclasses is created programmatically rather than
5054      * being inflated from XML. This method is automatically called when the XML
5055      * is inflated.
5056      * </p>
5057      *
5058      * @param a the styled attributes set to initialize the scrollbars from
5059      *
5060      * @removed
5061      */
initializeScrollbars(TypedArray a)5062     protected void initializeScrollbars(TypedArray a) {
5063         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5064         // using the View filter array which is not available to the SDK. As such, internal
5065         // framework usage now uses initializeScrollbarsInternal and we grab a default
5066         // TypedArray with the right filter instead here.
5067         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5068 
5069         initializeScrollbarsInternal(arr);
5070 
5071         // We ignored the method parameter. Recycle the one we actually did use.
5072         arr.recycle();
5073     }
5074 
5075     /**
5076      * <p>
5077      * Initializes the scrollbars from a given set of styled attributes. This
5078      * method should be called by subclasses that need scrollbars and when an
5079      * instance of these subclasses is created programmatically rather than
5080      * being inflated from XML. This method is automatically called when the XML
5081      * is inflated.
5082      * </p>
5083      *
5084      * @param a the styled attributes set to initialize the scrollbars from
5085      * @hide
5086      */
initializeScrollbarsInternal(TypedArray a)5087     protected void initializeScrollbarsInternal(TypedArray a) {
5088         initScrollCache();
5089 
5090         final ScrollabilityCache scrollabilityCache = mScrollCache;
5091 
5092         if (scrollabilityCache.scrollBar == null) {
5093             scrollabilityCache.scrollBar = new ScrollBarDrawable();
5094             scrollabilityCache.scrollBar.setState(getDrawableState());
5095             scrollabilityCache.scrollBar.setCallback(this);
5096         }
5097 
5098         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5099 
5100         if (!fadeScrollbars) {
5101             scrollabilityCache.state = ScrollabilityCache.ON;
5102         }
5103         scrollabilityCache.fadeScrollBars = fadeScrollbars;
5104 
5105 
5106         scrollabilityCache.scrollBarFadeDuration = a.getInt(
5107                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5108                         .getScrollBarFadeDuration());
5109         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5110                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
5111                 ViewConfiguration.getScrollDefaultDelay());
5112 
5113 
5114         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5115                 com.android.internal.R.styleable.View_scrollbarSize,
5116                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
5117 
5118         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5119         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5120 
5121         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5122         if (thumb != null) {
5123             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5124         }
5125 
5126         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5127                 false);
5128         if (alwaysDraw) {
5129             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5130         }
5131 
5132         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5133         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5134 
5135         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5136         if (thumb != null) {
5137             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5138         }
5139 
5140         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5141                 false);
5142         if (alwaysDraw) {
5143             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5144         }
5145 
5146         // Apply layout direction to the new Drawables if needed
5147         final int layoutDirection = getLayoutDirection();
5148         if (track != null) {
5149             track.setLayoutDirection(layoutDirection);
5150         }
5151         if (thumb != null) {
5152             thumb.setLayoutDirection(layoutDirection);
5153         }
5154 
5155         // Re-apply user/background padding so that scrollbar(s) get added
5156         resolvePadding();
5157     }
5158 
initializeScrollIndicatorsInternal()5159     private void initializeScrollIndicatorsInternal() {
5160         // Some day maybe we'll break this into top/left/start/etc. and let the
5161         // client control it. Until then, you can have any scroll indicator you
5162         // want as long as it's a 1dp foreground-colored rectangle.
5163         if (mScrollIndicatorDrawable == null) {
5164             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5165         }
5166     }
5167 
5168     /**
5169      * <p>
5170      * Initalizes the scrollability cache if necessary.
5171      * </p>
5172      */
initScrollCache()5173     private void initScrollCache() {
5174         if (mScrollCache == null) {
5175             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5176         }
5177     }
5178 
getScrollCache()5179     private ScrollabilityCache getScrollCache() {
5180         initScrollCache();
5181         return mScrollCache;
5182     }
5183 
5184     /**
5185      * Set the position of the vertical scroll bar. Should be one of
5186      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5187      * {@link #SCROLLBAR_POSITION_RIGHT}.
5188      *
5189      * @param position Where the vertical scroll bar should be positioned.
5190      */
setVerticalScrollbarPosition(int position)5191     public void setVerticalScrollbarPosition(int position) {
5192         if (mVerticalScrollbarPosition != position) {
5193             mVerticalScrollbarPosition = position;
5194             computeOpaqueFlags();
5195             resolvePadding();
5196         }
5197     }
5198 
5199     /**
5200      * @return The position where the vertical scroll bar will show, if applicable.
5201      * @see #setVerticalScrollbarPosition(int)
5202      */
getVerticalScrollbarPosition()5203     public int getVerticalScrollbarPosition() {
5204         return mVerticalScrollbarPosition;
5205     }
5206 
isOnScrollbar(float x, float y)5207     boolean isOnScrollbar(float x, float y) {
5208         if (mScrollCache == null) {
5209             return false;
5210         }
5211         x += getScrollX();
5212         y += getScrollY();
5213         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5214             final Rect bounds = mScrollCache.mScrollBarBounds;
5215             getVerticalScrollBarBounds(bounds);
5216             if (bounds.contains((int)x, (int)y)) {
5217                 return true;
5218             }
5219         }
5220         if (isHorizontalScrollBarEnabled()) {
5221             final Rect bounds = mScrollCache.mScrollBarBounds;
5222             getHorizontalScrollBarBounds(bounds);
5223             if (bounds.contains((int)x, (int)y)) {
5224                 return true;
5225             }
5226         }
5227         return false;
5228     }
5229 
isOnScrollbarThumb(float x, float y)5230     boolean isOnScrollbarThumb(float x, float y) {
5231         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5232     }
5233 
isOnVerticalScrollbarThumb(float x, float y)5234     private boolean isOnVerticalScrollbarThumb(float x, float y) {
5235         if (mScrollCache == null) {
5236             return false;
5237         }
5238         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5239             x += getScrollX();
5240             y += getScrollY();
5241             final Rect bounds = mScrollCache.mScrollBarBounds;
5242             getVerticalScrollBarBounds(bounds);
5243             final int range = computeVerticalScrollRange();
5244             final int offset = computeVerticalScrollOffset();
5245             final int extent = computeVerticalScrollExtent();
5246             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5247                     extent, range);
5248             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5249                     extent, range, offset);
5250             final int thumbTop = bounds.top + thumbOffset;
5251             if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5252                     && y <= thumbTop + thumbLength) {
5253                 return true;
5254             }
5255         }
5256         return false;
5257     }
5258 
isOnHorizontalScrollbarThumb(float x, float y)5259     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5260         if (mScrollCache == null) {
5261             return false;
5262         }
5263         if (isHorizontalScrollBarEnabled()) {
5264             x += getScrollX();
5265             y += getScrollY();
5266             final Rect bounds = mScrollCache.mScrollBarBounds;
5267             getHorizontalScrollBarBounds(bounds);
5268             final int range = computeHorizontalScrollRange();
5269             final int offset = computeHorizontalScrollOffset();
5270             final int extent = computeHorizontalScrollExtent();
5271             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5272                     extent, range);
5273             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5274                     extent, range, offset);
5275             final int thumbLeft = bounds.left + thumbOffset;
5276             if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5277                     && y <= bounds.bottom) {
5278                 return true;
5279             }
5280         }
5281         return false;
5282     }
5283 
isDraggingScrollBar()5284     boolean isDraggingScrollBar() {
5285         return mScrollCache != null
5286                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5287     }
5288 
5289     /**
5290      * Sets the state of all scroll indicators.
5291      * <p>
5292      * See {@link #setScrollIndicators(int, int)} for usage information.
5293      *
5294      * @param indicators a bitmask of indicators that should be enabled, or
5295      *                   {@code 0} to disable all indicators
5296      * @see #setScrollIndicators(int, int)
5297      * @see #getScrollIndicators()
5298      * @attr ref android.R.styleable#View_scrollIndicators
5299      */
setScrollIndicators(@crollIndicators int indicators)5300     public void setScrollIndicators(@ScrollIndicators int indicators) {
5301         setScrollIndicators(indicators,
5302                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5303     }
5304 
5305     /**
5306      * Sets the state of the scroll indicators specified by the mask. To change
5307      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5308      * <p>
5309      * When a scroll indicator is enabled, it will be displayed if the view
5310      * can scroll in the direction of the indicator.
5311      * <p>
5312      * Multiple indicator types may be enabled or disabled by passing the
5313      * logical OR of the desired types. If multiple types are specified, they
5314      * will all be set to the same enabled state.
5315      * <p>
5316      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5317      *
5318      * @param indicators the indicator direction, or the logical OR of multiple
5319      *             indicator directions. One or more of:
5320      *             <ul>
5321      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5322      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5323      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5324      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5325      *               <li>{@link #SCROLL_INDICATOR_START}</li>
5326      *               <li>{@link #SCROLL_INDICATOR_END}</li>
5327      *             </ul>
5328      * @see #setScrollIndicators(int)
5329      * @see #getScrollIndicators()
5330      * @attr ref android.R.styleable#View_scrollIndicators
5331      */
setScrollIndicators(@crollIndicators int indicators, @ScrollIndicators int mask)5332     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5333         // Shift and sanitize mask.
5334         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5335         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5336 
5337         // Shift and mask indicators.
5338         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5339         indicators &= mask;
5340 
5341         // Merge with non-masked flags.
5342         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5343 
5344         if (mPrivateFlags3 != updatedFlags) {
5345             mPrivateFlags3 = updatedFlags;
5346 
5347             if (indicators != 0) {
5348                 initializeScrollIndicatorsInternal();
5349             }
5350             invalidate();
5351         }
5352     }
5353 
5354     /**
5355      * Returns a bitmask representing the enabled scroll indicators.
5356      * <p>
5357      * For example, if the top and left scroll indicators are enabled and all
5358      * other indicators are disabled, the return value will be
5359      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5360      * <p>
5361      * To check whether the bottom scroll indicator is enabled, use the value
5362      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5363      *
5364      * @return a bitmask representing the enabled scroll indicators
5365      */
5366     @ScrollIndicators
getScrollIndicators()5367     public int getScrollIndicators() {
5368         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5369                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5370     }
5371 
getListenerInfo()5372     ListenerInfo getListenerInfo() {
5373         if (mListenerInfo != null) {
5374             return mListenerInfo;
5375         }
5376         mListenerInfo = new ListenerInfo();
5377         return mListenerInfo;
5378     }
5379 
5380     /**
5381      * Register a callback to be invoked when the scroll X or Y positions of
5382      * this view change.
5383      * <p>
5384      * <b>Note:</b> Some views handle scrolling independently from View and may
5385      * have their own separate listeners for scroll-type events. For example,
5386      * {@link android.widget.ListView ListView} allows clients to register an
5387      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5388      * to listen for changes in list scroll position.
5389      *
5390      * @param l The listener to notify when the scroll X or Y position changes.
5391      * @see android.view.View#getScrollX()
5392      * @see android.view.View#getScrollY()
5393      */
setOnScrollChangeListener(OnScrollChangeListener l)5394     public void setOnScrollChangeListener(OnScrollChangeListener l) {
5395         getListenerInfo().mOnScrollChangeListener = l;
5396     }
5397 
5398     /**
5399      * Register a callback to be invoked when focus of this view changed.
5400      *
5401      * @param l The callback that will run.
5402      */
setOnFocusChangeListener(OnFocusChangeListener l)5403     public void setOnFocusChangeListener(OnFocusChangeListener l) {
5404         getListenerInfo().mOnFocusChangeListener = l;
5405     }
5406 
5407     /**
5408      * Add a listener that will be called when the bounds of the view change due to
5409      * layout processing.
5410      *
5411      * @param listener The listener that will be called when layout bounds change.
5412      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)5413     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5414         ListenerInfo li = getListenerInfo();
5415         if (li.mOnLayoutChangeListeners == null) {
5416             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5417         }
5418         if (!li.mOnLayoutChangeListeners.contains(listener)) {
5419             li.mOnLayoutChangeListeners.add(listener);
5420         }
5421     }
5422 
5423     /**
5424      * Remove a listener for layout changes.
5425      *
5426      * @param listener The listener for layout bounds change.
5427      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)5428     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5429         ListenerInfo li = mListenerInfo;
5430         if (li == null || li.mOnLayoutChangeListeners == null) {
5431             return;
5432         }
5433         li.mOnLayoutChangeListeners.remove(listener);
5434     }
5435 
5436     /**
5437      * Add a listener for attach state changes.
5438      *
5439      * This listener will be called whenever this view is attached or detached
5440      * from a window. Remove the listener using
5441      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5442      *
5443      * @param listener Listener to attach
5444      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5445      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)5446     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5447         ListenerInfo li = getListenerInfo();
5448         if (li.mOnAttachStateChangeListeners == null) {
5449             li.mOnAttachStateChangeListeners
5450                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5451         }
5452         li.mOnAttachStateChangeListeners.add(listener);
5453     }
5454 
5455     /**
5456      * Remove a listener for attach state changes. The listener will receive no further
5457      * notification of window attach/detach events.
5458      *
5459      * @param listener Listener to remove
5460      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5461      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)5462     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5463         ListenerInfo li = mListenerInfo;
5464         if (li == null || li.mOnAttachStateChangeListeners == null) {
5465             return;
5466         }
5467         li.mOnAttachStateChangeListeners.remove(listener);
5468     }
5469 
5470     /**
5471      * Returns the focus-change callback registered for this view.
5472      *
5473      * @return The callback, or null if one is not registered.
5474      */
getOnFocusChangeListener()5475     public OnFocusChangeListener getOnFocusChangeListener() {
5476         ListenerInfo li = mListenerInfo;
5477         return li != null ? li.mOnFocusChangeListener : null;
5478     }
5479 
5480     /**
5481      * Register a callback to be invoked when this view is clicked. If this view is not
5482      * clickable, it becomes clickable.
5483      *
5484      * @param l The callback that will run
5485      *
5486      * @see #setClickable(boolean)
5487      */
setOnClickListener(@ullable OnClickListener l)5488     public void setOnClickListener(@Nullable OnClickListener l) {
5489         if (!isClickable()) {
5490             setClickable(true);
5491         }
5492         getListenerInfo().mOnClickListener = l;
5493     }
5494 
5495     /**
5496      * Return whether this view has an attached OnClickListener.  Returns
5497      * true if there is a listener, false if there is none.
5498      */
hasOnClickListeners()5499     public boolean hasOnClickListeners() {
5500         ListenerInfo li = mListenerInfo;
5501         return (li != null && li.mOnClickListener != null);
5502     }
5503 
5504     /**
5505      * Register a callback to be invoked when this view is clicked and held. If this view is not
5506      * long clickable, it becomes long clickable.
5507      *
5508      * @param l The callback that will run
5509      *
5510      * @see #setLongClickable(boolean)
5511      */
setOnLongClickListener(@ullable OnLongClickListener l)5512     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5513         if (!isLongClickable()) {
5514             setLongClickable(true);
5515         }
5516         getListenerInfo().mOnLongClickListener = l;
5517     }
5518 
5519     /**
5520      * Register a callback to be invoked when this view is context clicked. If the view is not
5521      * context clickable, it becomes context clickable.
5522      *
5523      * @param l The callback that will run
5524      * @see #setContextClickable(boolean)
5525      */
setOnContextClickListener(@ullable OnContextClickListener l)5526     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5527         if (!isContextClickable()) {
5528             setContextClickable(true);
5529         }
5530         getListenerInfo().mOnContextClickListener = l;
5531     }
5532 
5533     /**
5534      * Register a callback to be invoked when the context menu for this view is
5535      * being built. If this view is not long clickable, it becomes long clickable.
5536      *
5537      * @param l The callback that will run
5538      *
5539      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)5540     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5541         if (!isLongClickable()) {
5542             setLongClickable(true);
5543         }
5544         getListenerInfo().mOnCreateContextMenuListener = l;
5545     }
5546 
5547     /**
5548      * Set an observer to collect stats for each frame rendered for this view.
5549      *
5550      * @hide
5551      */
addFrameMetricsListener(Window window, Window.OnFrameMetricsAvailableListener listener, Handler handler)5552     public void addFrameMetricsListener(Window window,
5553             Window.OnFrameMetricsAvailableListener listener,
5554             Handler handler) {
5555         if (mAttachInfo != null) {
5556             if (mAttachInfo.mHardwareRenderer != null) {
5557                 if (mFrameMetricsObservers == null) {
5558                     mFrameMetricsObservers = new ArrayList<>();
5559                 }
5560 
5561                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5562                         handler.getLooper(), listener);
5563                 mFrameMetricsObservers.add(fmo);
5564                 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
5565             } else {
5566                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5567             }
5568         } else {
5569             if (mFrameMetricsObservers == null) {
5570                 mFrameMetricsObservers = new ArrayList<>();
5571             }
5572 
5573             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5574                     handler.getLooper(), listener);
5575             mFrameMetricsObservers.add(fmo);
5576         }
5577     }
5578 
5579     /**
5580      * Remove observer configured to collect frame stats for this view.
5581      *
5582      * @hide
5583      */
removeFrameMetricsListener( Window.OnFrameMetricsAvailableListener listener)5584     public void removeFrameMetricsListener(
5585             Window.OnFrameMetricsAvailableListener listener) {
5586         ThreadedRenderer renderer = getHardwareRenderer();
5587         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5588         if (fmo == null) {
5589             throw new IllegalArgumentException(
5590                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
5591         }
5592 
5593         if (mFrameMetricsObservers != null) {
5594             mFrameMetricsObservers.remove(fmo);
5595             if (renderer != null) {
5596                 renderer.removeFrameMetricsObserver(fmo);
5597             }
5598         }
5599     }
5600 
registerPendingFrameMetricsObservers()5601     private void registerPendingFrameMetricsObservers() {
5602         if (mFrameMetricsObservers != null) {
5603             ThreadedRenderer renderer = getHardwareRenderer();
5604             if (renderer != null) {
5605                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5606                     renderer.addFrameMetricsObserver(fmo);
5607                 }
5608             } else {
5609                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5610             }
5611         }
5612     }
5613 
findFrameMetricsObserver( Window.OnFrameMetricsAvailableListener listener)5614     private FrameMetricsObserver findFrameMetricsObserver(
5615             Window.OnFrameMetricsAvailableListener listener) {
5616         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5617             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5618             if (observer.mListener == listener) {
5619                 return observer;
5620             }
5621         }
5622 
5623         return null;
5624     }
5625 
5626     /**
5627      * Call this view's OnClickListener, if it is defined.  Performs all normal
5628      * actions associated with clicking: reporting accessibility event, playing
5629      * a sound, etc.
5630      *
5631      * @return True there was an assigned OnClickListener that was called, false
5632      *         otherwise is returned.
5633      */
performClick()5634     public boolean performClick() {
5635         final boolean result;
5636         final ListenerInfo li = mListenerInfo;
5637         if (li != null && li.mOnClickListener != null) {
5638             playSoundEffect(SoundEffectConstants.CLICK);
5639             li.mOnClickListener.onClick(this);
5640             result = true;
5641         } else {
5642             result = false;
5643         }
5644 
5645         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5646         return result;
5647     }
5648 
5649     /**
5650      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5651      * this only calls the listener, and does not do any associated clicking
5652      * actions like reporting an accessibility event.
5653      *
5654      * @return True there was an assigned OnClickListener that was called, false
5655      *         otherwise is returned.
5656      */
callOnClick()5657     public boolean callOnClick() {
5658         ListenerInfo li = mListenerInfo;
5659         if (li != null && li.mOnClickListener != null) {
5660             li.mOnClickListener.onClick(this);
5661             return true;
5662         }
5663         return false;
5664     }
5665 
5666     /**
5667      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5668      * context menu if the OnLongClickListener did not consume the event.
5669      *
5670      * @return {@code true} if one of the above receivers consumed the event,
5671      *         {@code false} otherwise
5672      */
performLongClick()5673     public boolean performLongClick() {
5674         return performLongClickInternal(mLongClickX, mLongClickY);
5675     }
5676 
5677     /**
5678      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5679      * context menu if the OnLongClickListener did not consume the event,
5680      * anchoring it to an (x,y) coordinate.
5681      *
5682      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5683      *          to disable anchoring
5684      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5685      *          to disable anchoring
5686      * @return {@code true} if one of the above receivers consumed the event,
5687      *         {@code false} otherwise
5688      */
performLongClick(float x, float y)5689     public boolean performLongClick(float x, float y) {
5690         mLongClickX = x;
5691         mLongClickY = y;
5692         final boolean handled = performLongClick();
5693         mLongClickX = Float.NaN;
5694         mLongClickY = Float.NaN;
5695         return handled;
5696     }
5697 
5698     /**
5699      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5700      * context menu if the OnLongClickListener did not consume the event,
5701      * optionally anchoring it to an (x,y) coordinate.
5702      *
5703      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5704      *          to disable anchoring
5705      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5706      *          to disable anchoring
5707      * @return {@code true} if one of the above receivers consumed the event,
5708      *         {@code false} otherwise
5709      */
performLongClickInternal(float x, float y)5710     private boolean performLongClickInternal(float x, float y) {
5711         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5712 
5713         boolean handled = false;
5714         final ListenerInfo li = mListenerInfo;
5715         if (li != null && li.mOnLongClickListener != null) {
5716             handled = li.mOnLongClickListener.onLongClick(View.this);
5717         }
5718         if (!handled) {
5719             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5720             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5721         }
5722         if (handled) {
5723             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5724         }
5725         return handled;
5726     }
5727 
5728     /**
5729      * Call this view's OnContextClickListener, if it is defined.
5730      *
5731      * @param x the x coordinate of the context click
5732      * @param y the y coordinate of the context click
5733      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5734      *         otherwise.
5735      */
performContextClick(float x, float y)5736     public boolean performContextClick(float x, float y) {
5737         return performContextClick();
5738     }
5739 
5740     /**
5741      * Call this view's OnContextClickListener, if it is defined.
5742      *
5743      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5744      *         otherwise.
5745      */
performContextClick()5746     public boolean performContextClick() {
5747         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5748 
5749         boolean handled = false;
5750         ListenerInfo li = mListenerInfo;
5751         if (li != null && li.mOnContextClickListener != null) {
5752             handled = li.mOnContextClickListener.onContextClick(View.this);
5753         }
5754         if (handled) {
5755             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5756         }
5757         return handled;
5758     }
5759 
5760     /**
5761      * Performs button-related actions during a touch down event.
5762      *
5763      * @param event The event.
5764      * @return True if the down was consumed.
5765      *
5766      * @hide
5767      */
performButtonActionOnTouchDown(MotionEvent event)5768     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5769         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5770             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5771             showContextMenu(event.getX(), event.getY());
5772             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5773             return true;
5774         }
5775         return false;
5776     }
5777 
5778     /**
5779      * Shows the context menu for this view.
5780      *
5781      * @return {@code true} if the context menu was shown, {@code false}
5782      *         otherwise
5783      * @see #showContextMenu(float, float)
5784      */
showContextMenu()5785     public boolean showContextMenu() {
5786         return getParent().showContextMenuForChild(this);
5787     }
5788 
5789     /**
5790      * Shows the context menu for this view anchored to the specified
5791      * view-relative coordinate.
5792      *
5793      * @param x the X coordinate in pixels relative to the view to which the
5794      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5795      * @param y the Y coordinate in pixels relative to the view to which the
5796      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5797      * @return {@code true} if the context menu was shown, {@code false}
5798      *         otherwise
5799      */
showContextMenu(float x, float y)5800     public boolean showContextMenu(float x, float y) {
5801         return getParent().showContextMenuForChild(this, x, y);
5802     }
5803 
5804     /**
5805      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5806      *
5807      * @param callback Callback that will control the lifecycle of the action mode
5808      * @return The new action mode if it is started, null otherwise
5809      *
5810      * @see ActionMode
5811      * @see #startActionMode(android.view.ActionMode.Callback, int)
5812      */
startActionMode(ActionMode.Callback callback)5813     public ActionMode startActionMode(ActionMode.Callback callback) {
5814         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5815     }
5816 
5817     /**
5818      * Start an action mode with the given type.
5819      *
5820      * @param callback Callback that will control the lifecycle of the action mode
5821      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5822      * @return The new action mode if it is started, null otherwise
5823      *
5824      * @see ActionMode
5825      */
startActionMode(ActionMode.Callback callback, int type)5826     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5827         ViewParent parent = getParent();
5828         if (parent == null) return null;
5829         try {
5830             return parent.startActionModeForChild(this, callback, type);
5831         } catch (AbstractMethodError ame) {
5832             // Older implementations of custom views might not implement this.
5833             return parent.startActionModeForChild(this, callback);
5834         }
5835     }
5836 
5837     /**
5838      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5839      * Context, creating a unique View identifier to retrieve the result.
5840      *
5841      * @param intent The Intent to be started.
5842      * @param requestCode The request code to use.
5843      * @hide
5844      */
startActivityForResult(Intent intent, int requestCode)5845     public void startActivityForResult(Intent intent, int requestCode) {
5846         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5847         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5848     }
5849 
5850     /**
5851      * If this View corresponds to the calling who, dispatches the activity result.
5852      * @param who The identifier for the targeted View to receive the result.
5853      * @param requestCode The integer request code originally supplied to
5854      *                    startActivityForResult(), allowing you to identify who this
5855      *                    result came from.
5856      * @param resultCode The integer result code returned by the child activity
5857      *                   through its setResult().
5858      * @param data An Intent, which can return result data to the caller
5859      *               (various data can be attached to Intent "extras").
5860      * @return {@code true} if the activity result was dispatched.
5861      * @hide
5862      */
dispatchActivityResult( String who, int requestCode, int resultCode, Intent data)5863     public boolean dispatchActivityResult(
5864             String who, int requestCode, int resultCode, Intent data) {
5865         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5866             onActivityResult(requestCode, resultCode, data);
5867             mStartActivityRequestWho = null;
5868             return true;
5869         }
5870         return false;
5871     }
5872 
5873     /**
5874      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5875      *
5876      * @param requestCode The integer request code originally supplied to
5877      *                    startActivityForResult(), allowing you to identify who this
5878      *                    result came from.
5879      * @param resultCode The integer result code returned by the child activity
5880      *                   through its setResult().
5881      * @param data An Intent, which can return result data to the caller
5882      *               (various data can be attached to Intent "extras").
5883      * @hide
5884      */
onActivityResult(int requestCode, int resultCode, Intent data)5885     public void onActivityResult(int requestCode, int resultCode, Intent data) {
5886         // Do nothing.
5887     }
5888 
5889     /**
5890      * Register a callback to be invoked when a hardware key is pressed in this view.
5891      * Key presses in software input methods will generally not trigger the methods of
5892      * this listener.
5893      * @param l the key listener to attach to this view
5894      */
setOnKeyListener(OnKeyListener l)5895     public void setOnKeyListener(OnKeyListener l) {
5896         getListenerInfo().mOnKeyListener = l;
5897     }
5898 
5899     /**
5900      * Register a callback to be invoked when a touch event is sent to this view.
5901      * @param l the touch listener to attach to this view
5902      */
setOnTouchListener(OnTouchListener l)5903     public void setOnTouchListener(OnTouchListener l) {
5904         getListenerInfo().mOnTouchListener = l;
5905     }
5906 
5907     /**
5908      * Register a callback to be invoked when a generic motion event is sent to this view.
5909      * @param l the generic motion listener to attach to this view
5910      */
setOnGenericMotionListener(OnGenericMotionListener l)5911     public void setOnGenericMotionListener(OnGenericMotionListener l) {
5912         getListenerInfo().mOnGenericMotionListener = l;
5913     }
5914 
5915     /**
5916      * Register a callback to be invoked when a hover event is sent to this view.
5917      * @param l the hover listener to attach to this view
5918      */
setOnHoverListener(OnHoverListener l)5919     public void setOnHoverListener(OnHoverListener l) {
5920         getListenerInfo().mOnHoverListener = l;
5921     }
5922 
5923     /**
5924      * Register a drag event listener callback object for this View. The parameter is
5925      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5926      * View, the system calls the
5927      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5928      * @param l An implementation of {@link android.view.View.OnDragListener}.
5929      */
setOnDragListener(OnDragListener l)5930     public void setOnDragListener(OnDragListener l) {
5931         getListenerInfo().mOnDragListener = l;
5932     }
5933 
5934     /**
5935      * Give this view focus. This will cause
5936      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5937      *
5938      * Note: this does not check whether this {@link View} should get focus, it just
5939      * gives it focus no matter what.  It should only be called internally by framework
5940      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5941      *
5942      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5943      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5944      *        focus moved when requestFocus() is called. It may not always
5945      *        apply, in which case use the default View.FOCUS_DOWN.
5946      * @param previouslyFocusedRect The rectangle of the view that had focus
5947      *        prior in this View's coordinate system.
5948      */
handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)5949     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5950         if (DBG) {
5951             System.out.println(this + " requestFocus()");
5952         }
5953 
5954         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5955             mPrivateFlags |= PFLAG_FOCUSED;
5956 
5957             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5958 
5959             if (mParent != null) {
5960                 mParent.requestChildFocus(this, this);
5961             }
5962 
5963             if (mAttachInfo != null) {
5964                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5965             }
5966 
5967             onFocusChanged(true, direction, previouslyFocusedRect);
5968             refreshDrawableState();
5969         }
5970     }
5971 
5972     /**
5973      * Sets this view's preference for reveal behavior when it gains focus.
5974      *
5975      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
5976      * this view would prefer to be brought fully into view when it gains focus.
5977      * For example, a text field that a user is meant to type into. Other views such
5978      * as scrolling containers may prefer to opt-out of this behavior.</p>
5979      *
5980      * <p>The default value for views is true, though subclasses may change this
5981      * based on their preferred behavior.</p>
5982      *
5983      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
5984      *
5985      * @see #getRevealOnFocusHint()
5986      */
setRevealOnFocusHint(boolean revealOnFocus)5987     public final void setRevealOnFocusHint(boolean revealOnFocus) {
5988         if (revealOnFocus) {
5989             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
5990         } else {
5991             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
5992         }
5993     }
5994 
5995     /**
5996      * Returns this view's preference for reveal behavior when it gains focus.
5997      *
5998      * <p>When this method returns true for a child view requesting focus, ancestor
5999      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6000      * should make a best effort to make the newly focused child fully visible to the user.
6001      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6002      * other properties affecting visibility to the user as part of the focus change.</p>
6003      *
6004      * @return true if this view would prefer to become fully visible when it gains focus,
6005      *         false if it would prefer not to disrupt scroll positioning
6006      *
6007      * @see #setRevealOnFocusHint(boolean)
6008      */
getRevealOnFocusHint()6009     public final boolean getRevealOnFocusHint() {
6010         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6011     }
6012 
6013     /**
6014      * Populates <code>outRect</code> with the hotspot bounds. By default,
6015      * the hotspot bounds are identical to the screen bounds.
6016      *
6017      * @param outRect rect to populate with hotspot bounds
6018      * @hide Only for internal use by views and widgets.
6019      */
getHotspotBounds(Rect outRect)6020     public void getHotspotBounds(Rect outRect) {
6021         final Drawable background = getBackground();
6022         if (background != null) {
6023             background.getHotspotBounds(outRect);
6024         } else {
6025             getBoundsOnScreen(outRect);
6026         }
6027     }
6028 
6029     /**
6030      * Request that a rectangle of this view be visible on the screen,
6031      * scrolling if necessary just enough.
6032      *
6033      * <p>A View should call this if it maintains some notion of which part
6034      * of its content is interesting.  For example, a text editing view
6035      * should call this when its cursor moves.
6036      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6037      * It should not be affected by which part of the View is currently visible or its scroll
6038      * position.
6039      *
6040      * @param rectangle The rectangle in the View's content coordinate space
6041      * @return Whether any parent scrolled.
6042      */
requestRectangleOnScreen(Rect rectangle)6043     public boolean requestRectangleOnScreen(Rect rectangle) {
6044         return requestRectangleOnScreen(rectangle, false);
6045     }
6046 
6047     /**
6048      * Request that a rectangle of this view be visible on the screen,
6049      * scrolling if necessary just enough.
6050      *
6051      * <p>A View should call this if it maintains some notion of which part
6052      * of its content is interesting.  For example, a text editing view
6053      * should call this when its cursor moves.
6054      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6055      * It should not be affected by which part of the View is currently visible or its scroll
6056      * position.
6057      * <p>When <code>immediate</code> is set to true, scrolling will not be
6058      * animated.
6059      *
6060      * @param rectangle The rectangle in the View's content coordinate space
6061      * @param immediate True to forbid animated scrolling, false otherwise
6062      * @return Whether any parent scrolled.
6063      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)6064     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6065         if (mParent == null) {
6066             return false;
6067         }
6068 
6069         View child = this;
6070 
6071         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6072         position.set(rectangle);
6073 
6074         ViewParent parent = mParent;
6075         boolean scrolled = false;
6076         while (parent != null) {
6077             rectangle.set((int) position.left, (int) position.top,
6078                     (int) position.right, (int) position.bottom);
6079 
6080             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6081 
6082             if (!(parent instanceof View)) {
6083                 break;
6084             }
6085 
6086             // move it from child's content coordinate space to parent's content coordinate space
6087             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6088 
6089             child = (View) parent;
6090             parent = child.getParent();
6091         }
6092 
6093         return scrolled;
6094     }
6095 
6096     /**
6097      * Called when this view wants to give up focus. If focus is cleared
6098      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6099      * <p>
6100      * <strong>Note:</strong> When a View clears focus the framework is trying
6101      * to give focus to the first focusable View from the top. Hence, if this
6102      * View is the first from the top that can take focus, then all callbacks
6103      * related to clearing focus will be invoked after which the framework will
6104      * give focus to this view.
6105      * </p>
6106      */
clearFocus()6107     public void clearFocus() {
6108         if (DBG) {
6109             System.out.println(this + " clearFocus()");
6110         }
6111 
6112         clearFocusInternal(null, true, true);
6113     }
6114 
6115     /**
6116      * Clears focus from the view, optionally propagating the change up through
6117      * the parent hierarchy and requesting that the root view place new focus.
6118      *
6119      * @param propagate whether to propagate the change up through the parent
6120      *            hierarchy
6121      * @param refocus when propagate is true, specifies whether to request the
6122      *            root view place new focus
6123      */
clearFocusInternal(View focused, boolean propagate, boolean refocus)6124     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6125         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6126             mPrivateFlags &= ~PFLAG_FOCUSED;
6127 
6128             if (propagate && mParent != null) {
6129                 mParent.clearChildFocus(this);
6130             }
6131 
6132             onFocusChanged(false, 0, null);
6133             refreshDrawableState();
6134 
6135             if (propagate && (!refocus || !rootViewRequestFocus())) {
6136                 notifyGlobalFocusCleared(this);
6137             }
6138         }
6139     }
6140 
notifyGlobalFocusCleared(View oldFocus)6141     void notifyGlobalFocusCleared(View oldFocus) {
6142         if (oldFocus != null && mAttachInfo != null) {
6143             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6144         }
6145     }
6146 
rootViewRequestFocus()6147     boolean rootViewRequestFocus() {
6148         final View root = getRootView();
6149         return root != null && root.requestFocus();
6150     }
6151 
6152     /**
6153      * Called internally by the view system when a new view is getting focus.
6154      * This is what clears the old focus.
6155      * <p>
6156      * <b>NOTE:</b> The parent view's focused child must be updated manually
6157      * after calling this method. Otherwise, the view hierarchy may be left in
6158      * an inconstent state.
6159      */
unFocus(View focused)6160     void unFocus(View focused) {
6161         if (DBG) {
6162             System.out.println(this + " unFocus()");
6163         }
6164 
6165         clearFocusInternal(focused, false, false);
6166     }
6167 
6168     /**
6169      * Returns true if this view has focus itself, or is the ancestor of the
6170      * view that has focus.
6171      *
6172      * @return True if this view has or contains focus, false otherwise.
6173      */
6174     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()6175     public boolean hasFocus() {
6176         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6177     }
6178 
6179     /**
6180      * Returns true if this view is focusable or if it contains a reachable View
6181      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6182      * is a View whose parents do not block descendants focus.
6183      *
6184      * Only {@link #VISIBLE} views are considered focusable.
6185      *
6186      * @return True if the view is focusable or if the view contains a focusable
6187      *         View, false otherwise.
6188      *
6189      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6190      * @see ViewGroup#getTouchscreenBlocksFocus()
6191      */
hasFocusable()6192     public boolean hasFocusable() {
6193         if (!isFocusableInTouchMode()) {
6194             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6195                 final ViewGroup g = (ViewGroup) p;
6196                 if (g.shouldBlockFocusForTouchscreen()) {
6197                     return false;
6198                 }
6199             }
6200         }
6201         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6202     }
6203 
6204     /**
6205      * Called by the view system when the focus state of this view changes.
6206      * When the focus change event is caused by directional navigation, direction
6207      * and previouslyFocusedRect provide insight into where the focus is coming from.
6208      * When overriding, be sure to call up through to the super class so that
6209      * the standard focus handling will occur.
6210      *
6211      * @param gainFocus True if the View has focus; false otherwise.
6212      * @param direction The direction focus has moved when requestFocus()
6213      *                  is called to give this view focus. Values are
6214      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6215      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6216      *                  It may not always apply, in which case use the default.
6217      * @param previouslyFocusedRect The rectangle, in this view's coordinate
6218      *        system, of the previously focused view.  If applicable, this will be
6219      *        passed in as finer grained information about where the focus is coming
6220      *        from (in addition to direction).  Will be <code>null</code> otherwise.
6221      */
6222     @CallSuper
onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)6223     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6224             @Nullable Rect previouslyFocusedRect) {
6225         if (gainFocus) {
6226             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6227         } else {
6228             notifyViewAccessibilityStateChangedIfNeeded(
6229                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6230         }
6231 
6232         InputMethodManager imm = InputMethodManager.peekInstance();
6233         if (!gainFocus) {
6234             if (isPressed()) {
6235                 setPressed(false);
6236             }
6237             if (imm != null && mAttachInfo != null
6238                     && mAttachInfo.mHasWindowFocus) {
6239                 imm.focusOut(this);
6240             }
6241             onFocusLost();
6242         } else if (imm != null && mAttachInfo != null
6243                 && mAttachInfo.mHasWindowFocus) {
6244             imm.focusIn(this);
6245         }
6246 
6247         invalidate(true);
6248         ListenerInfo li = mListenerInfo;
6249         if (li != null && li.mOnFocusChangeListener != null) {
6250             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6251         }
6252 
6253         if (mAttachInfo != null) {
6254             mAttachInfo.mKeyDispatchState.reset(this);
6255         }
6256     }
6257 
6258     /**
6259      * Sends an accessibility event of the given type. If accessibility is
6260      * not enabled this method has no effect. The default implementation calls
6261      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6262      * to populate information about the event source (this View), then calls
6263      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6264      * populate the text content of the event source including its descendants,
6265      * and last calls
6266      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6267      * on its parent to request sending of the event to interested parties.
6268      * <p>
6269      * If an {@link AccessibilityDelegate} has been specified via calling
6270      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6271      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6272      * responsible for handling this call.
6273      * </p>
6274      *
6275      * @param eventType The type of the event to send, as defined by several types from
6276      * {@link android.view.accessibility.AccessibilityEvent}, such as
6277      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6278      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6279      *
6280      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6281      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6282      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6283      * @see AccessibilityDelegate
6284      */
sendAccessibilityEvent(int eventType)6285     public void sendAccessibilityEvent(int eventType) {
6286         if (mAccessibilityDelegate != null) {
6287             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6288         } else {
6289             sendAccessibilityEventInternal(eventType);
6290         }
6291     }
6292 
6293     /**
6294      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6295      * {@link AccessibilityEvent} to make an announcement which is related to some
6296      * sort of a context change for which none of the events representing UI transitions
6297      * is a good fit. For example, announcing a new page in a book. If accessibility
6298      * is not enabled this method does nothing.
6299      *
6300      * @param text The announcement text.
6301      */
announceForAccessibility(CharSequence text)6302     public void announceForAccessibility(CharSequence text) {
6303         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6304             AccessibilityEvent event = AccessibilityEvent.obtain(
6305                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
6306             onInitializeAccessibilityEvent(event);
6307             event.getText().add(text);
6308             event.setContentDescription(null);
6309             mParent.requestSendAccessibilityEvent(this, event);
6310         }
6311     }
6312 
6313     /**
6314      * @see #sendAccessibilityEvent(int)
6315      *
6316      * Note: Called from the default {@link AccessibilityDelegate}.
6317      *
6318      * @hide
6319      */
sendAccessibilityEventInternal(int eventType)6320     public void sendAccessibilityEventInternal(int eventType) {
6321         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6322             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6323         }
6324     }
6325 
6326     /**
6327      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6328      * takes as an argument an empty {@link AccessibilityEvent} and does not
6329      * perform a check whether accessibility is enabled.
6330      * <p>
6331      * If an {@link AccessibilityDelegate} has been specified via calling
6332      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6333      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6334      * is responsible for handling this call.
6335      * </p>
6336      *
6337      * @param event The event to send.
6338      *
6339      * @see #sendAccessibilityEvent(int)
6340      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)6341     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6342         if (mAccessibilityDelegate != null) {
6343             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6344         } else {
6345             sendAccessibilityEventUncheckedInternal(event);
6346         }
6347     }
6348 
6349     /**
6350      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6351      *
6352      * Note: Called from the default {@link AccessibilityDelegate}.
6353      *
6354      * @hide
6355      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)6356     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6357         if (!isShown()) {
6358             return;
6359         }
6360         onInitializeAccessibilityEvent(event);
6361         // Only a subset of accessibility events populates text content.
6362         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6363             dispatchPopulateAccessibilityEvent(event);
6364         }
6365         // In the beginning we called #isShown(), so we know that getParent() is not null.
6366         getParent().requestSendAccessibilityEvent(this, event);
6367     }
6368 
6369     /**
6370      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6371      * to its children for adding their text content to the event. Note that the
6372      * event text is populated in a separate dispatch path since we add to the
6373      * event not only the text of the source but also the text of all its descendants.
6374      * A typical implementation will call
6375      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6376      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6377      * on each child. Override this method if custom population of the event text
6378      * content is required.
6379      * <p>
6380      * If an {@link AccessibilityDelegate} has been specified via calling
6381      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6382      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6383      * is responsible for handling this call.
6384      * </p>
6385      * <p>
6386      * <em>Note:</em> Accessibility events of certain types are not dispatched for
6387      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6388      * </p>
6389      *
6390      * @param event The event.
6391      *
6392      * @return True if the event population was completed.
6393      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)6394     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6395         if (mAccessibilityDelegate != null) {
6396             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6397         } else {
6398             return dispatchPopulateAccessibilityEventInternal(event);
6399         }
6400     }
6401 
6402     /**
6403      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6404      *
6405      * Note: Called from the default {@link AccessibilityDelegate}.
6406      *
6407      * @hide
6408      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)6409     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6410         onPopulateAccessibilityEvent(event);
6411         return false;
6412     }
6413 
6414     /**
6415      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6416      * giving a chance to this View to populate the accessibility event with its
6417      * text content. While this method is free to modify event
6418      * attributes other than text content, doing so should normally be performed in
6419      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6420      * <p>
6421      * Example: Adding formatted date string to an accessibility event in addition
6422      *          to the text added by the super implementation:
6423      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6424      *     super.onPopulateAccessibilityEvent(event);
6425      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6426      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6427      *         mCurrentDate.getTimeInMillis(), flags);
6428      *     event.getText().add(selectedDateUtterance);
6429      * }</pre>
6430      * <p>
6431      * If an {@link AccessibilityDelegate} has been specified via calling
6432      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6433      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6434      * is responsible for handling this call.
6435      * </p>
6436      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6437      * information to the event, in case the default implementation has basic information to add.
6438      * </p>
6439      *
6440      * @param event The accessibility event which to populate.
6441      *
6442      * @see #sendAccessibilityEvent(int)
6443      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6444      */
6445     @CallSuper
onPopulateAccessibilityEvent(AccessibilityEvent event)6446     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6447         if (mAccessibilityDelegate != null) {
6448             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6449         } else {
6450             onPopulateAccessibilityEventInternal(event);
6451         }
6452     }
6453 
6454     /**
6455      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6456      *
6457      * Note: Called from the default {@link AccessibilityDelegate}.
6458      *
6459      * @hide
6460      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)6461     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6462     }
6463 
6464     /**
6465      * Initializes an {@link AccessibilityEvent} with information about
6466      * this View which is the event source. In other words, the source of
6467      * an accessibility event is the view whose state change triggered firing
6468      * the event.
6469      * <p>
6470      * Example: Setting the password property of an event in addition
6471      *          to properties set by the super implementation:
6472      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6473      *     super.onInitializeAccessibilityEvent(event);
6474      *     event.setPassword(true);
6475      * }</pre>
6476      * <p>
6477      * If an {@link AccessibilityDelegate} has been specified via calling
6478      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6479      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6480      * is responsible for handling this call.
6481      * </p>
6482      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6483      * information to the event, in case the default implementation has basic information to add.
6484      * </p>
6485      * @param event The event to initialize.
6486      *
6487      * @see #sendAccessibilityEvent(int)
6488      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6489      */
6490     @CallSuper
onInitializeAccessibilityEvent(AccessibilityEvent event)6491     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6492         if (mAccessibilityDelegate != null) {
6493             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6494         } else {
6495             onInitializeAccessibilityEventInternal(event);
6496         }
6497     }
6498 
6499     /**
6500      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6501      *
6502      * Note: Called from the default {@link AccessibilityDelegate}.
6503      *
6504      * @hide
6505      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)6506     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6507         event.setSource(this);
6508         event.setClassName(getAccessibilityClassName());
6509         event.setPackageName(getContext().getPackageName());
6510         event.setEnabled(isEnabled());
6511         event.setContentDescription(mContentDescription);
6512 
6513         switch (event.getEventType()) {
6514             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6515                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
6516                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6517                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6518                 event.setItemCount(focusablesTempList.size());
6519                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6520                 if (mAttachInfo != null) {
6521                     focusablesTempList.clear();
6522                 }
6523             } break;
6524             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6525                 CharSequence text = getIterableTextForAccessibility();
6526                 if (text != null && text.length() > 0) {
6527                     event.setFromIndex(getAccessibilitySelectionStart());
6528                     event.setToIndex(getAccessibilitySelectionEnd());
6529                     event.setItemCount(text.length());
6530                 }
6531             } break;
6532         }
6533     }
6534 
6535     /**
6536      * Returns an {@link AccessibilityNodeInfo} representing this view from the
6537      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6538      * This method is responsible for obtaining an accessibility node info from a
6539      * pool of reusable instances and calling
6540      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6541      * initialize the former.
6542      * <p>
6543      * Note: The client is responsible for recycling the obtained instance by calling
6544      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6545      * </p>
6546      *
6547      * @return A populated {@link AccessibilityNodeInfo}.
6548      *
6549      * @see AccessibilityNodeInfo
6550      */
createAccessibilityNodeInfo()6551     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6552         if (mAccessibilityDelegate != null) {
6553             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6554         } else {
6555             return createAccessibilityNodeInfoInternal();
6556         }
6557     }
6558 
6559     /**
6560      * @see #createAccessibilityNodeInfo()
6561      *
6562      * @hide
6563      */
createAccessibilityNodeInfoInternal()6564     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6565         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6566         if (provider != null) {
6567             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6568         } else {
6569             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6570             onInitializeAccessibilityNodeInfo(info);
6571             return info;
6572         }
6573     }
6574 
6575     /**
6576      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6577      * The base implementation sets:
6578      * <ul>
6579      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6580      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6581      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6582      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6583      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6584      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6585      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6586      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6587      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6588      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6589      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6590      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6591      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6592      * </ul>
6593      * <p>
6594      * Subclasses should override this method, call the super implementation,
6595      * and set additional attributes.
6596      * </p>
6597      * <p>
6598      * If an {@link AccessibilityDelegate} has been specified via calling
6599      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6600      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6601      * is responsible for handling this call.
6602      * </p>
6603      *
6604      * @param info The instance to initialize.
6605      */
6606     @CallSuper
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)6607     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6608         if (mAccessibilityDelegate != null) {
6609             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6610         } else {
6611             onInitializeAccessibilityNodeInfoInternal(info);
6612         }
6613     }
6614 
6615     /**
6616      * Gets the location of this view in screen coordinates.
6617      *
6618      * @param outRect The output location
6619      * @hide
6620      */
getBoundsOnScreen(Rect outRect)6621     public void getBoundsOnScreen(Rect outRect) {
6622         getBoundsOnScreen(outRect, false);
6623     }
6624 
6625     /**
6626      * Gets the location of this view in screen coordinates.
6627      *
6628      * @param outRect The output location
6629      * @param clipToParent Whether to clip child bounds to the parent ones.
6630      * @hide
6631      */
getBoundsOnScreen(Rect outRect, boolean clipToParent)6632     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6633         if (mAttachInfo == null) {
6634             return;
6635         }
6636 
6637         RectF position = mAttachInfo.mTmpTransformRect;
6638         position.set(0, 0, mRight - mLeft, mBottom - mTop);
6639 
6640         if (!hasIdentityMatrix()) {
6641             getMatrix().mapRect(position);
6642         }
6643 
6644         position.offset(mLeft, mTop);
6645 
6646         ViewParent parent = mParent;
6647         while (parent instanceof View) {
6648             View parentView = (View) parent;
6649 
6650             position.offset(-parentView.mScrollX, -parentView.mScrollY);
6651 
6652             if (clipToParent) {
6653                 position.left = Math.max(position.left, 0);
6654                 position.top = Math.max(position.top, 0);
6655                 position.right = Math.min(position.right, parentView.getWidth());
6656                 position.bottom = Math.min(position.bottom, parentView.getHeight());
6657             }
6658 
6659             if (!parentView.hasIdentityMatrix()) {
6660                 parentView.getMatrix().mapRect(position);
6661             }
6662 
6663             position.offset(parentView.mLeft, parentView.mTop);
6664 
6665             parent = parentView.mParent;
6666         }
6667 
6668         if (parent instanceof ViewRootImpl) {
6669             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6670             position.offset(0, -viewRootImpl.mCurScrollY);
6671         }
6672 
6673         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6674 
6675         outRect.set(Math.round(position.left), Math.round(position.top),
6676                 Math.round(position.right), Math.round(position.bottom));
6677     }
6678 
6679     /**
6680      * Return the class name of this object to be used for accessibility purposes.
6681      * Subclasses should only override this if they are implementing something that
6682      * should be seen as a completely new class of view when used by accessibility,
6683      * unrelated to the class it is deriving from.  This is used to fill in
6684      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6685      */
getAccessibilityClassName()6686     public CharSequence getAccessibilityClassName() {
6687         return View.class.getName();
6688     }
6689 
6690     /**
6691      * Called when assist structure is being retrieved from a view as part of
6692      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6693      * @param structure Fill in with structured view data.  The default implementation
6694      * fills in all data that can be inferred from the view itself.
6695      */
onProvideStructure(ViewStructure structure)6696     public void onProvideStructure(ViewStructure structure) {
6697         final int id = mID;
6698         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6699                 && (id&0x0000ffff) != 0) {
6700             String pkg, type, entry;
6701             try {
6702                 final Resources res = getResources();
6703                 entry = res.getResourceEntryName(id);
6704                 type = res.getResourceTypeName(id);
6705                 pkg = res.getResourcePackageName(id);
6706             } catch (Resources.NotFoundException e) {
6707                 entry = type = pkg = null;
6708             }
6709             structure.setId(id, pkg, type, entry);
6710         } else {
6711             structure.setId(id, null, null, null);
6712         }
6713         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6714         if (!hasIdentityMatrix()) {
6715             structure.setTransformation(getMatrix());
6716         }
6717         structure.setElevation(getZ());
6718         structure.setVisibility(getVisibility());
6719         structure.setEnabled(isEnabled());
6720         if (isClickable()) {
6721             structure.setClickable(true);
6722         }
6723         if (isFocusable()) {
6724             structure.setFocusable(true);
6725         }
6726         if (isFocused()) {
6727             structure.setFocused(true);
6728         }
6729         if (isAccessibilityFocused()) {
6730             structure.setAccessibilityFocused(true);
6731         }
6732         if (isSelected()) {
6733             structure.setSelected(true);
6734         }
6735         if (isActivated()) {
6736             structure.setActivated(true);
6737         }
6738         if (isLongClickable()) {
6739             structure.setLongClickable(true);
6740         }
6741         if (this instanceof Checkable) {
6742             structure.setCheckable(true);
6743             if (((Checkable)this).isChecked()) {
6744                 structure.setChecked(true);
6745             }
6746         }
6747         if (isContextClickable()) {
6748             structure.setContextClickable(true);
6749         }
6750         structure.setClassName(getAccessibilityClassName().toString());
6751         structure.setContentDescription(getContentDescription());
6752     }
6753 
6754     /**
6755      * Called when assist structure is being retrieved from a view as part of
6756      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6757      * generate additional virtual structure under this view.  The defaullt implementation
6758      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6759      * view's virtual accessibility nodes, if any.  You can override this for a more
6760      * optimal implementation providing this data.
6761      */
onProvideVirtualStructure(ViewStructure structure)6762     public void onProvideVirtualStructure(ViewStructure structure) {
6763         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6764         if (provider != null) {
6765             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6766             structure.setChildCount(1);
6767             ViewStructure root = structure.newChild(0);
6768             populateVirtualStructure(root, provider, info);
6769             info.recycle();
6770         }
6771     }
6772 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info)6773     private void populateVirtualStructure(ViewStructure structure,
6774             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6775         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6776                 null, null, null);
6777         Rect rect = structure.getTempRect();
6778         info.getBoundsInParent(rect);
6779         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6780         structure.setVisibility(VISIBLE);
6781         structure.setEnabled(info.isEnabled());
6782         if (info.isClickable()) {
6783             structure.setClickable(true);
6784         }
6785         if (info.isFocusable()) {
6786             structure.setFocusable(true);
6787         }
6788         if (info.isFocused()) {
6789             structure.setFocused(true);
6790         }
6791         if (info.isAccessibilityFocused()) {
6792             structure.setAccessibilityFocused(true);
6793         }
6794         if (info.isSelected()) {
6795             structure.setSelected(true);
6796         }
6797         if (info.isLongClickable()) {
6798             structure.setLongClickable(true);
6799         }
6800         if (info.isCheckable()) {
6801             structure.setCheckable(true);
6802             if (info.isChecked()) {
6803                 structure.setChecked(true);
6804             }
6805         }
6806         if (info.isContextClickable()) {
6807             structure.setContextClickable(true);
6808         }
6809         CharSequence cname = info.getClassName();
6810         structure.setClassName(cname != null ? cname.toString() : null);
6811         structure.setContentDescription(info.getContentDescription());
6812         if (info.getText() != null || info.getError() != null) {
6813             structure.setText(info.getText(), info.getTextSelectionStart(),
6814                     info.getTextSelectionEnd());
6815         }
6816         final int NCHILDREN = info.getChildCount();
6817         if (NCHILDREN > 0) {
6818             structure.setChildCount(NCHILDREN);
6819             for (int i=0; i<NCHILDREN; i++) {
6820                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6821                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6822                 ViewStructure child = structure.newChild(i);
6823                 populateVirtualStructure(child, provider, cinfo);
6824                 cinfo.recycle();
6825             }
6826         }
6827     }
6828 
6829     /**
6830      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6831      * implementation calls {@link #onProvideStructure} and
6832      * {@link #onProvideVirtualStructure}.
6833      */
dispatchProvideStructure(ViewStructure structure)6834     public void dispatchProvideStructure(ViewStructure structure) {
6835         if (!isAssistBlocked()) {
6836             onProvideStructure(structure);
6837             onProvideVirtualStructure(structure);
6838         } else {
6839             structure.setClassName(getAccessibilityClassName().toString());
6840             structure.setAssistBlocked(true);
6841         }
6842     }
6843 
6844     /**
6845      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6846      *
6847      * Note: Called from the default {@link AccessibilityDelegate}.
6848      *
6849      * @hide
6850      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)6851     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6852         if (mAttachInfo == null) {
6853             return;
6854         }
6855 
6856         Rect bounds = mAttachInfo.mTmpInvalRect;
6857 
6858         getDrawingRect(bounds);
6859         info.setBoundsInParent(bounds);
6860 
6861         getBoundsOnScreen(bounds, true);
6862         info.setBoundsInScreen(bounds);
6863 
6864         ViewParent parent = getParentForAccessibility();
6865         if (parent instanceof View) {
6866             info.setParent((View) parent);
6867         }
6868 
6869         if (mID != View.NO_ID) {
6870             View rootView = getRootView();
6871             if (rootView == null) {
6872                 rootView = this;
6873             }
6874 
6875             View label = rootView.findLabelForView(this, mID);
6876             if (label != null) {
6877                 info.setLabeledBy(label);
6878             }
6879 
6880             if ((mAttachInfo.mAccessibilityFetchFlags
6881                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6882                     && Resources.resourceHasPackage(mID)) {
6883                 try {
6884                     String viewId = getResources().getResourceName(mID);
6885                     info.setViewIdResourceName(viewId);
6886                 } catch (Resources.NotFoundException nfe) {
6887                     /* ignore */
6888                 }
6889             }
6890         }
6891 
6892         if (mLabelForId != View.NO_ID) {
6893             View rootView = getRootView();
6894             if (rootView == null) {
6895                 rootView = this;
6896             }
6897             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6898             if (labeled != null) {
6899                 info.setLabelFor(labeled);
6900             }
6901         }
6902 
6903         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6904             View rootView = getRootView();
6905             if (rootView == null) {
6906                 rootView = this;
6907             }
6908             View next = rootView.findViewInsideOutShouldExist(this,
6909                     mAccessibilityTraversalBeforeId);
6910             if (next != null && next.includeForAccessibility()) {
6911                 info.setTraversalBefore(next);
6912             }
6913         }
6914 
6915         if (mAccessibilityTraversalAfterId != View.NO_ID) {
6916             View rootView = getRootView();
6917             if (rootView == null) {
6918                 rootView = this;
6919             }
6920             View next = rootView.findViewInsideOutShouldExist(this,
6921                     mAccessibilityTraversalAfterId);
6922             if (next != null && next.includeForAccessibility()) {
6923                 info.setTraversalAfter(next);
6924             }
6925         }
6926 
6927         info.setVisibleToUser(isVisibleToUser());
6928 
6929         if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6930                 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6931             info.setImportantForAccessibility(isImportantForAccessibility());
6932         } else {
6933             info.setImportantForAccessibility(true);
6934         }
6935 
6936         info.setPackageName(mContext.getPackageName());
6937         info.setClassName(getAccessibilityClassName());
6938         info.setContentDescription(getContentDescription());
6939 
6940         info.setEnabled(isEnabled());
6941         info.setClickable(isClickable());
6942         info.setFocusable(isFocusable());
6943         info.setFocused(isFocused());
6944         info.setAccessibilityFocused(isAccessibilityFocused());
6945         info.setSelected(isSelected());
6946         info.setLongClickable(isLongClickable());
6947         info.setContextClickable(isContextClickable());
6948         info.setLiveRegion(getAccessibilityLiveRegion());
6949 
6950         // TODO: These make sense only if we are in an AdapterView but all
6951         // views can be selected. Maybe from accessibility perspective
6952         // we should report as selectable view in an AdapterView.
6953         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6954         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6955 
6956         if (isFocusable()) {
6957             if (isFocused()) {
6958                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6959             } else {
6960                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6961             }
6962         }
6963 
6964         if (!isAccessibilityFocused()) {
6965             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6966         } else {
6967             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6968         }
6969 
6970         if (isClickable() && isEnabled()) {
6971             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6972         }
6973 
6974         if (isLongClickable() && isEnabled()) {
6975             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6976         }
6977 
6978         if (isContextClickable() && isEnabled()) {
6979             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6980         }
6981 
6982         CharSequence text = getIterableTextForAccessibility();
6983         if (text != null && text.length() > 0) {
6984             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6985 
6986             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6987             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6988             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6989             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6990                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6991                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6992         }
6993 
6994         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6995         populateAccessibilityNodeInfoDrawingOrderInParent(info);
6996     }
6997 
6998     /**
6999      * Determine the order in which this view will be drawn relative to its siblings for a11y
7000      *
7001      * @param info The info whose drawing order should be populated
7002      */
populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)7003     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7004         /*
7005          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7006          * drawing order may not be well-defined, and some Views with custom drawing order may
7007          * not be initialized sufficiently to respond properly getChildDrawingOrder.
7008          */
7009         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7010             info.setDrawingOrder(0);
7011             return;
7012         }
7013         int drawingOrderInParent = 1;
7014         // Iterate up the hierarchy if parents are not important for a11y
7015         View viewAtDrawingLevel = this;
7016         final ViewParent parent = getParentForAccessibility();
7017         while (viewAtDrawingLevel != parent) {
7018             final ViewParent currentParent = viewAtDrawingLevel.getParent();
7019             if (!(currentParent instanceof ViewGroup)) {
7020                 // Should only happen for the Decor
7021                 drawingOrderInParent = 0;
7022                 break;
7023             } else {
7024                 final ViewGroup parentGroup = (ViewGroup) currentParent;
7025                 final int childCount = parentGroup.getChildCount();
7026                 if (childCount > 1) {
7027                     List<View> preorderedList = parentGroup.buildOrderedChildList();
7028                     if (preorderedList != null) {
7029                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7030                         for (int i = 0; i < childDrawIndex; i++) {
7031                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7032                         }
7033                     } else {
7034                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7035                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7036                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7037                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
7038                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7039                         if (childDrawIndex != 0) {
7040                             for (int i = 0; i < numChildrenToIterate; i++) {
7041                                 final int otherDrawIndex = (customOrder ?
7042                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
7043                                 if (otherDrawIndex < childDrawIndex) {
7044                                     drawingOrderInParent +=
7045                                             numViewsForAccessibility(parentGroup.getChildAt(i));
7046                                 }
7047                             }
7048                         }
7049                     }
7050                 }
7051             }
7052             viewAtDrawingLevel = (View) currentParent;
7053         }
7054         info.setDrawingOrder(drawingOrderInParent);
7055     }
7056 
numViewsForAccessibility(View view)7057     private static int numViewsForAccessibility(View view) {
7058         if (view != null) {
7059             if (view.includeForAccessibility()) {
7060                 return 1;
7061             } else if (view instanceof ViewGroup) {
7062                 return ((ViewGroup) view).getNumChildrenForAccessibility();
7063             }
7064         }
7065         return 0;
7066     }
7067 
findLabelForView(View view, int labeledId)7068     private View findLabelForView(View view, int labeledId) {
7069         if (mMatchLabelForPredicate == null) {
7070             mMatchLabelForPredicate = new MatchLabelForPredicate();
7071         }
7072         mMatchLabelForPredicate.mLabeledId = labeledId;
7073         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7074     }
7075 
7076     /**
7077      * Computes whether this view is visible to the user. Such a view is
7078      * attached, visible, all its predecessors are visible, it is not clipped
7079      * entirely by its predecessors, and has an alpha greater than zero.
7080      *
7081      * @return Whether the view is visible on the screen.
7082      *
7083      * @hide
7084      */
isVisibleToUser()7085     protected boolean isVisibleToUser() {
7086         return isVisibleToUser(null);
7087     }
7088 
7089     /**
7090      * Computes whether the given portion of this view is visible to the user.
7091      * Such a view is attached, visible, all its predecessors are visible,
7092      * has an alpha greater than zero, and the specified portion is not
7093      * clipped entirely by its predecessors.
7094      *
7095      * @param boundInView the portion of the view to test; coordinates should be relative; may be
7096      *                    <code>null</code>, and the entire view will be tested in this case.
7097      *                    When <code>true</code> is returned by the function, the actual visible
7098      *                    region will be stored in this parameter; that is, if boundInView is fully
7099      *                    contained within the view, no modification will be made, otherwise regions
7100      *                    outside of the visible area of the view will be clipped.
7101      *
7102      * @return Whether the specified portion of the view is visible on the screen.
7103      *
7104      * @hide
7105      */
isVisibleToUser(Rect boundInView)7106     protected boolean isVisibleToUser(Rect boundInView) {
7107         if (mAttachInfo != null) {
7108             // Attached to invisible window means this view is not visible.
7109             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7110                 return false;
7111             }
7112             // An invisible predecessor or one with alpha zero means
7113             // that this view is not visible to the user.
7114             Object current = this;
7115             while (current instanceof View) {
7116                 View view = (View) current;
7117                 // We have attach info so this view is attached and there is no
7118                 // need to check whether we reach to ViewRootImpl on the way up.
7119                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7120                         view.getVisibility() != VISIBLE) {
7121                     return false;
7122                 }
7123                 current = view.mParent;
7124             }
7125             // Check if the view is entirely covered by its predecessors.
7126             Rect visibleRect = mAttachInfo.mTmpInvalRect;
7127             Point offset = mAttachInfo.mPoint;
7128             if (!getGlobalVisibleRect(visibleRect, offset)) {
7129                 return false;
7130             }
7131             // Check if the visible portion intersects the rectangle of interest.
7132             if (boundInView != null) {
7133                 visibleRect.offset(-offset.x, -offset.y);
7134                 return boundInView.intersect(visibleRect);
7135             }
7136             return true;
7137         }
7138         return false;
7139     }
7140 
7141     /**
7142      * Returns the delegate for implementing accessibility support via
7143      * composition. For more details see {@link AccessibilityDelegate}.
7144      *
7145      * @return The delegate, or null if none set.
7146      *
7147      * @hide
7148      */
getAccessibilityDelegate()7149     public AccessibilityDelegate getAccessibilityDelegate() {
7150         return mAccessibilityDelegate;
7151     }
7152 
7153     /**
7154      * Sets a delegate for implementing accessibility support via composition
7155      * (as opposed to inheritance). For more details, see
7156      * {@link AccessibilityDelegate}.
7157      * <p>
7158      * <strong>Note:</strong> On platform versions prior to
7159      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7160      * views in the {@code android.widget.*} package are called <i>before</i>
7161      * host methods. This prevents certain properties such as class name from
7162      * being modified by overriding
7163      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7164      * as any changes will be overwritten by the host class.
7165      * <p>
7166      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7167      * methods are called <i>after</i> host methods, which all properties to be
7168      * modified without being overwritten by the host class.
7169      *
7170      * @param delegate the object to which accessibility method calls should be
7171      *                 delegated
7172      * @see AccessibilityDelegate
7173      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)7174     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7175         mAccessibilityDelegate = delegate;
7176     }
7177 
7178     /**
7179      * Gets the provider for managing a virtual view hierarchy rooted at this View
7180      * and reported to {@link android.accessibilityservice.AccessibilityService}s
7181      * that explore the window content.
7182      * <p>
7183      * If this method returns an instance, this instance is responsible for managing
7184      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7185      * View including the one representing the View itself. Similarly the returned
7186      * instance is responsible for performing accessibility actions on any virtual
7187      * view or the root view itself.
7188      * </p>
7189      * <p>
7190      * If an {@link AccessibilityDelegate} has been specified via calling
7191      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7192      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7193      * is responsible for handling this call.
7194      * </p>
7195      *
7196      * @return The provider.
7197      *
7198      * @see AccessibilityNodeProvider
7199      */
getAccessibilityNodeProvider()7200     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7201         if (mAccessibilityDelegate != null) {
7202             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7203         } else {
7204             return null;
7205         }
7206     }
7207 
7208     /**
7209      * Gets the unique identifier of this view on the screen for accessibility purposes.
7210      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7211      *
7212      * @return The view accessibility id.
7213      *
7214      * @hide
7215      */
getAccessibilityViewId()7216     public int getAccessibilityViewId() {
7217         if (mAccessibilityViewId == NO_ID) {
7218             mAccessibilityViewId = sNextAccessibilityViewId++;
7219         }
7220         return mAccessibilityViewId;
7221     }
7222 
7223     /**
7224      * Gets the unique identifier of the window in which this View reseides.
7225      *
7226      * @return The window accessibility id.
7227      *
7228      * @hide
7229      */
getAccessibilityWindowId()7230     public int getAccessibilityWindowId() {
7231         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7232                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7233     }
7234 
7235     /**
7236      * Returns the {@link View}'s content description.
7237      * <p>
7238      * <strong>Note:</strong> Do not override this method, as it will have no
7239      * effect on the content description presented to accessibility services.
7240      * You must call {@link #setContentDescription(CharSequence)} to modify the
7241      * content description.
7242      *
7243      * @return the content description
7244      * @see #setContentDescription(CharSequence)
7245      * @attr ref android.R.styleable#View_contentDescription
7246      */
7247     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()7248     public CharSequence getContentDescription() {
7249         return mContentDescription;
7250     }
7251 
7252     /**
7253      * Sets the {@link View}'s content description.
7254      * <p>
7255      * A content description briefly describes the view and is primarily used
7256      * for accessibility support to determine how a view should be presented to
7257      * the user. In the case of a view with no textual representation, such as
7258      * {@link android.widget.ImageButton}, a useful content description
7259      * explains what the view does. For example, an image button with a phone
7260      * icon that is used to place a call may use "Call" as its content
7261      * description. An image of a floppy disk that is used to save a file may
7262      * use "Save".
7263      *
7264      * @param contentDescription The content description.
7265      * @see #getContentDescription()
7266      * @attr ref android.R.styleable#View_contentDescription
7267      */
7268     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)7269     public void setContentDescription(CharSequence contentDescription) {
7270         if (mContentDescription == null) {
7271             if (contentDescription == null) {
7272                 return;
7273             }
7274         } else if (mContentDescription.equals(contentDescription)) {
7275             return;
7276         }
7277         mContentDescription = contentDescription;
7278         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7279         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7280             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7281             notifySubtreeAccessibilityStateChangedIfNeeded();
7282         } else {
7283             notifyViewAccessibilityStateChangedIfNeeded(
7284                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7285         }
7286     }
7287 
7288     /**
7289      * Sets the id of a view before which this one is visited in accessibility traversal.
7290      * A screen-reader must visit the content of this view before the content of the one
7291      * it precedes. For example, if view B is set to be before view A, then a screen-reader
7292      * will traverse the entire content of B before traversing the entire content of A,
7293      * regardles of what traversal strategy it is using.
7294      * <p>
7295      * Views that do not have specified before/after relationships are traversed in order
7296      * determined by the screen-reader.
7297      * </p>
7298      * <p>
7299      * Setting that this view is before a view that is not important for accessibility
7300      * or if this view is not important for accessibility will have no effect as the
7301      * screen-reader is not aware of unimportant views.
7302      * </p>
7303      *
7304      * @param beforeId The id of a view this one precedes in accessibility traversal.
7305      *
7306      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7307      *
7308      * @see #setImportantForAccessibility(int)
7309      */
7310     @RemotableViewMethod
setAccessibilityTraversalBefore(int beforeId)7311     public void setAccessibilityTraversalBefore(int beforeId) {
7312         if (mAccessibilityTraversalBeforeId == beforeId) {
7313             return;
7314         }
7315         mAccessibilityTraversalBeforeId = beforeId;
7316         notifyViewAccessibilityStateChangedIfNeeded(
7317                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7318     }
7319 
7320     /**
7321      * Gets the id of a view before which this one is visited in accessibility traversal.
7322      *
7323      * @return The id of a view this one precedes in accessibility traversal if
7324      *         specified, otherwise {@link #NO_ID}.
7325      *
7326      * @see #setAccessibilityTraversalBefore(int)
7327      */
getAccessibilityTraversalBefore()7328     public int getAccessibilityTraversalBefore() {
7329         return mAccessibilityTraversalBeforeId;
7330     }
7331 
7332     /**
7333      * Sets the id of a view after which this one is visited in accessibility traversal.
7334      * A screen-reader must visit the content of the other view before the content of this
7335      * one. For example, if view B is set to be after view A, then a screen-reader
7336      * will traverse the entire content of A before traversing the entire content of B,
7337      * regardles of what traversal strategy it is using.
7338      * <p>
7339      * Views that do not have specified before/after relationships are traversed in order
7340      * determined by the screen-reader.
7341      * </p>
7342      * <p>
7343      * Setting that this view is after a view that is not important for accessibility
7344      * or if this view is not important for accessibility will have no effect as the
7345      * screen-reader is not aware of unimportant views.
7346      * </p>
7347      *
7348      * @param afterId The id of a view this one succedees in accessibility traversal.
7349      *
7350      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7351      *
7352      * @see #setImportantForAccessibility(int)
7353      */
7354     @RemotableViewMethod
setAccessibilityTraversalAfter(int afterId)7355     public void setAccessibilityTraversalAfter(int afterId) {
7356         if (mAccessibilityTraversalAfterId == afterId) {
7357             return;
7358         }
7359         mAccessibilityTraversalAfterId = afterId;
7360         notifyViewAccessibilityStateChangedIfNeeded(
7361                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7362     }
7363 
7364     /**
7365      * Gets the id of a view after which this one is visited in accessibility traversal.
7366      *
7367      * @return The id of a view this one succeedes in accessibility traversal if
7368      *         specified, otherwise {@link #NO_ID}.
7369      *
7370      * @see #setAccessibilityTraversalAfter(int)
7371      */
getAccessibilityTraversalAfter()7372     public int getAccessibilityTraversalAfter() {
7373         return mAccessibilityTraversalAfterId;
7374     }
7375 
7376     /**
7377      * Gets the id of a view for which this view serves as a label for
7378      * accessibility purposes.
7379      *
7380      * @return The labeled view id.
7381      */
7382     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()7383     public int getLabelFor() {
7384         return mLabelForId;
7385     }
7386 
7387     /**
7388      * Sets the id of a view for which this view serves as a label for
7389      * accessibility purposes.
7390      *
7391      * @param id The labeled view id.
7392      */
7393     @RemotableViewMethod
setLabelFor(@dRes int id)7394     public void setLabelFor(@IdRes int id) {
7395         if (mLabelForId == id) {
7396             return;
7397         }
7398         mLabelForId = id;
7399         if (mLabelForId != View.NO_ID
7400                 && mID == View.NO_ID) {
7401             mID = generateViewId();
7402         }
7403         notifyViewAccessibilityStateChangedIfNeeded(
7404                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7405     }
7406 
7407     /**
7408      * Invoked whenever this view loses focus, either by losing window focus or by losing
7409      * focus within its window. This method can be used to clear any state tied to the
7410      * focus. For instance, if a button is held pressed with the trackball and the window
7411      * loses focus, this method can be used to cancel the press.
7412      *
7413      * Subclasses of View overriding this method should always call super.onFocusLost().
7414      *
7415      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7416      * @see #onWindowFocusChanged(boolean)
7417      *
7418      * @hide pending API council approval
7419      */
7420     @CallSuper
onFocusLost()7421     protected void onFocusLost() {
7422         resetPressedState();
7423     }
7424 
resetPressedState()7425     private void resetPressedState() {
7426         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7427             return;
7428         }
7429 
7430         if (isPressed()) {
7431             setPressed(false);
7432 
7433             if (!mHasPerformedLongPress) {
7434                 removeLongPressCallback();
7435             }
7436         }
7437     }
7438 
7439     /**
7440      * Returns true if this view has focus
7441      *
7442      * @return True if this view has focus, false otherwise.
7443      */
7444     @ViewDebug.ExportedProperty(category = "focus")
isFocused()7445     public boolean isFocused() {
7446         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7447     }
7448 
7449     /**
7450      * Find the view in the hierarchy rooted at this view that currently has
7451      * focus.
7452      *
7453      * @return The view that currently has focus, or null if no focused view can
7454      *         be found.
7455      */
findFocus()7456     public View findFocus() {
7457         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7458     }
7459 
7460     /**
7461      * Indicates whether this view is one of the set of scrollable containers in
7462      * its window.
7463      *
7464      * @return whether this view is one of the set of scrollable containers in
7465      * its window
7466      *
7467      * @attr ref android.R.styleable#View_isScrollContainer
7468      */
isScrollContainer()7469     public boolean isScrollContainer() {
7470         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7471     }
7472 
7473     /**
7474      * Change whether this view is one of the set of scrollable containers in
7475      * its window.  This will be used to determine whether the window can
7476      * resize or must pan when a soft input area is open -- scrollable
7477      * containers allow the window to use resize mode since the container
7478      * will appropriately shrink.
7479      *
7480      * @attr ref android.R.styleable#View_isScrollContainer
7481      */
setScrollContainer(boolean isScrollContainer)7482     public void setScrollContainer(boolean isScrollContainer) {
7483         if (isScrollContainer) {
7484             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7485                 mAttachInfo.mScrollContainers.add(this);
7486                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7487             }
7488             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7489         } else {
7490             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7491                 mAttachInfo.mScrollContainers.remove(this);
7492             }
7493             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7494         }
7495     }
7496 
7497     /**
7498      * Returns the quality of the drawing cache.
7499      *
7500      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7501      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7502      *
7503      * @see #setDrawingCacheQuality(int)
7504      * @see #setDrawingCacheEnabled(boolean)
7505      * @see #isDrawingCacheEnabled()
7506      *
7507      * @attr ref android.R.styleable#View_drawingCacheQuality
7508      */
7509     @DrawingCacheQuality
getDrawingCacheQuality()7510     public int getDrawingCacheQuality() {
7511         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7512     }
7513 
7514     /**
7515      * Set the drawing cache quality of this view. This value is used only when the
7516      * drawing cache is enabled
7517      *
7518      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7519      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7520      *
7521      * @see #getDrawingCacheQuality()
7522      * @see #setDrawingCacheEnabled(boolean)
7523      * @see #isDrawingCacheEnabled()
7524      *
7525      * @attr ref android.R.styleable#View_drawingCacheQuality
7526      */
setDrawingCacheQuality(@rawingCacheQuality int quality)7527     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7528         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7529     }
7530 
7531     /**
7532      * Returns whether the screen should remain on, corresponding to the current
7533      * value of {@link #KEEP_SCREEN_ON}.
7534      *
7535      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7536      *
7537      * @see #setKeepScreenOn(boolean)
7538      *
7539      * @attr ref android.R.styleable#View_keepScreenOn
7540      */
getKeepScreenOn()7541     public boolean getKeepScreenOn() {
7542         return (mViewFlags & KEEP_SCREEN_ON) != 0;
7543     }
7544 
7545     /**
7546      * Controls whether the screen should remain on, modifying the
7547      * value of {@link #KEEP_SCREEN_ON}.
7548      *
7549      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7550      *
7551      * @see #getKeepScreenOn()
7552      *
7553      * @attr ref android.R.styleable#View_keepScreenOn
7554      */
setKeepScreenOn(boolean keepScreenOn)7555     public void setKeepScreenOn(boolean keepScreenOn) {
7556         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7557     }
7558 
7559     /**
7560      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7561      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7562      *
7563      * @attr ref android.R.styleable#View_nextFocusLeft
7564      */
getNextFocusLeftId()7565     public int getNextFocusLeftId() {
7566         return mNextFocusLeftId;
7567     }
7568 
7569     /**
7570      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7571      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7572      * decide automatically.
7573      *
7574      * @attr ref android.R.styleable#View_nextFocusLeft
7575      */
setNextFocusLeftId(int nextFocusLeftId)7576     public void setNextFocusLeftId(int nextFocusLeftId) {
7577         mNextFocusLeftId = nextFocusLeftId;
7578     }
7579 
7580     /**
7581      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7582      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7583      *
7584      * @attr ref android.R.styleable#View_nextFocusRight
7585      */
getNextFocusRightId()7586     public int getNextFocusRightId() {
7587         return mNextFocusRightId;
7588     }
7589 
7590     /**
7591      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7592      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7593      * decide automatically.
7594      *
7595      * @attr ref android.R.styleable#View_nextFocusRight
7596      */
setNextFocusRightId(int nextFocusRightId)7597     public void setNextFocusRightId(int nextFocusRightId) {
7598         mNextFocusRightId = nextFocusRightId;
7599     }
7600 
7601     /**
7602      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7603      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7604      *
7605      * @attr ref android.R.styleable#View_nextFocusUp
7606      */
getNextFocusUpId()7607     public int getNextFocusUpId() {
7608         return mNextFocusUpId;
7609     }
7610 
7611     /**
7612      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7613      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7614      * decide automatically.
7615      *
7616      * @attr ref android.R.styleable#View_nextFocusUp
7617      */
setNextFocusUpId(int nextFocusUpId)7618     public void setNextFocusUpId(int nextFocusUpId) {
7619         mNextFocusUpId = nextFocusUpId;
7620     }
7621 
7622     /**
7623      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7624      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7625      *
7626      * @attr ref android.R.styleable#View_nextFocusDown
7627      */
getNextFocusDownId()7628     public int getNextFocusDownId() {
7629         return mNextFocusDownId;
7630     }
7631 
7632     /**
7633      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7634      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7635      * decide automatically.
7636      *
7637      * @attr ref android.R.styleable#View_nextFocusDown
7638      */
setNextFocusDownId(int nextFocusDownId)7639     public void setNextFocusDownId(int nextFocusDownId) {
7640         mNextFocusDownId = nextFocusDownId;
7641     }
7642 
7643     /**
7644      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7645      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7646      *
7647      * @attr ref android.R.styleable#View_nextFocusForward
7648      */
getNextFocusForwardId()7649     public int getNextFocusForwardId() {
7650         return mNextFocusForwardId;
7651     }
7652 
7653     /**
7654      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7655      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7656      * decide automatically.
7657      *
7658      * @attr ref android.R.styleable#View_nextFocusForward
7659      */
setNextFocusForwardId(int nextFocusForwardId)7660     public void setNextFocusForwardId(int nextFocusForwardId) {
7661         mNextFocusForwardId = nextFocusForwardId;
7662     }
7663 
7664     /**
7665      * Returns the visibility of this view and all of its ancestors
7666      *
7667      * @return True if this view and all of its ancestors are {@link #VISIBLE}
7668      */
isShown()7669     public boolean isShown() {
7670         View current = this;
7671         //noinspection ConstantConditions
7672         do {
7673             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7674                 return false;
7675             }
7676             ViewParent parent = current.mParent;
7677             if (parent == null) {
7678                 return false; // We are not attached to the view root
7679             }
7680             if (!(parent instanceof View)) {
7681                 return true;
7682             }
7683             current = (View) parent;
7684         } while (current != null);
7685 
7686         return false;
7687     }
7688 
7689     /**
7690      * Called by the view hierarchy when the content insets for a window have
7691      * changed, to allow it to adjust its content to fit within those windows.
7692      * The content insets tell you the space that the status bar, input method,
7693      * and other system windows infringe on the application's window.
7694      *
7695      * <p>You do not normally need to deal with this function, since the default
7696      * window decoration given to applications takes care of applying it to the
7697      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7698      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7699      * and your content can be placed under those system elements.  You can then
7700      * use this method within your view hierarchy if you have parts of your UI
7701      * which you would like to ensure are not being covered.
7702      *
7703      * <p>The default implementation of this method simply applies the content
7704      * insets to the view's padding, consuming that content (modifying the
7705      * insets to be 0), and returning true.  This behavior is off by default, but can
7706      * be enabled through {@link #setFitsSystemWindows(boolean)}.
7707      *
7708      * <p>This function's traversal down the hierarchy is depth-first.  The same content
7709      * insets object is propagated down the hierarchy, so any changes made to it will
7710      * be seen by all following views (including potentially ones above in
7711      * the hierarchy since this is a depth-first traversal).  The first view
7712      * that returns true will abort the entire traversal.
7713      *
7714      * <p>The default implementation works well for a situation where it is
7715      * used with a container that covers the entire window, allowing it to
7716      * apply the appropriate insets to its content on all edges.  If you need
7717      * a more complicated layout (such as two different views fitting system
7718      * windows, one on the top of the window, and one on the bottom),
7719      * you can override the method and handle the insets however you would like.
7720      * Note that the insets provided by the framework are always relative to the
7721      * far edges of the window, not accounting for the location of the called view
7722      * within that window.  (In fact when this method is called you do not yet know
7723      * where the layout will place the view, as it is done before layout happens.)
7724      *
7725      * <p>Note: unlike many View methods, there is no dispatch phase to this
7726      * call.  If you are overriding it in a ViewGroup and want to allow the
7727      * call to continue to your children, you must be sure to call the super
7728      * implementation.
7729      *
7730      * <p>Here is a sample layout that makes use of fitting system windows
7731      * to have controls for a video view placed inside of the window decorations
7732      * that it hides and shows.  This can be used with code like the second
7733      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7734      *
7735      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7736      *
7737      * @param insets Current content insets of the window.  Prior to
7738      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7739      * the insets or else you and Android will be unhappy.
7740      *
7741      * @return {@code true} if this view applied the insets and it should not
7742      * continue propagating further down the hierarchy, {@code false} otherwise.
7743      * @see #getFitsSystemWindows()
7744      * @see #setFitsSystemWindows(boolean)
7745      * @see #setSystemUiVisibility(int)
7746      *
7747      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7748      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7749      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7750      * to implement handling their own insets.
7751      */
fitSystemWindows(Rect insets)7752     protected boolean fitSystemWindows(Rect insets) {
7753         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7754             if (insets == null) {
7755                 // Null insets by definition have already been consumed.
7756                 // This call cannot apply insets since there are none to apply,
7757                 // so return false.
7758                 return false;
7759             }
7760             // If we're not in the process of dispatching the newer apply insets call,
7761             // that means we're not in the compatibility path. Dispatch into the newer
7762             // apply insets path and take things from there.
7763             try {
7764                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7765                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7766             } finally {
7767                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7768             }
7769         } else {
7770             // We're being called from the newer apply insets path.
7771             // Perform the standard fallback behavior.
7772             return fitSystemWindowsInt(insets);
7773         }
7774     }
7775 
fitSystemWindowsInt(Rect insets)7776     private boolean fitSystemWindowsInt(Rect insets) {
7777         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7778             mUserPaddingStart = UNDEFINED_PADDING;
7779             mUserPaddingEnd = UNDEFINED_PADDING;
7780             Rect localInsets = sThreadLocal.get();
7781             if (localInsets == null) {
7782                 localInsets = new Rect();
7783                 sThreadLocal.set(localInsets);
7784             }
7785             boolean res = computeFitSystemWindows(insets, localInsets);
7786             mUserPaddingLeftInitial = localInsets.left;
7787             mUserPaddingRightInitial = localInsets.right;
7788             internalSetPadding(localInsets.left, localInsets.top,
7789                     localInsets.right, localInsets.bottom);
7790             return res;
7791         }
7792         return false;
7793     }
7794 
7795     /**
7796      * Called when the view should apply {@link WindowInsets} according to its internal policy.
7797      *
7798      * <p>This method should be overridden by views that wish to apply a policy different from or
7799      * in addition to the default behavior. Clients that wish to force a view subtree
7800      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7801      *
7802      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7803      * it will be called during dispatch instead of this method. The listener may optionally
7804      * call this method from its own implementation if it wishes to apply the view's default
7805      * insets policy in addition to its own.</p>
7806      *
7807      * <p>Implementations of this method should either return the insets parameter unchanged
7808      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7809      * that this view applied itself. This allows new inset types added in future platform
7810      * versions to pass through existing implementations unchanged without being erroneously
7811      * consumed.</p>
7812      *
7813      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7814      * property is set then the view will consume the system window insets and apply them
7815      * as padding for the view.</p>
7816      *
7817      * @param insets Insets to apply
7818      * @return The supplied insets with any applied insets consumed
7819      */
onApplyWindowInsets(WindowInsets insets)7820     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7821         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7822             // We weren't called from within a direct call to fitSystemWindows,
7823             // call into it as a fallback in case we're in a class that overrides it
7824             // and has logic to perform.
7825             if (fitSystemWindows(insets.getSystemWindowInsets())) {
7826                 return insets.consumeSystemWindowInsets();
7827             }
7828         } else {
7829             // We were called from within a direct call to fitSystemWindows.
7830             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7831                 return insets.consumeSystemWindowInsets();
7832             }
7833         }
7834         return insets;
7835     }
7836 
7837     /**
7838      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7839      * window insets to this view. The listener's
7840      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7841      * method will be called instead of the view's
7842      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7843      *
7844      * @param listener Listener to set
7845      *
7846      * @see #onApplyWindowInsets(WindowInsets)
7847      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)7848     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7849         getListenerInfo().mOnApplyWindowInsetsListener = listener;
7850     }
7851 
7852     /**
7853      * Request to apply the given window insets to this view or another view in its subtree.
7854      *
7855      * <p>This method should be called by clients wishing to apply insets corresponding to areas
7856      * obscured by window decorations or overlays. This can include the status and navigation bars,
7857      * action bars, input methods and more. New inset categories may be added in the future.
7858      * The method returns the insets provided minus any that were applied by this view or its
7859      * children.</p>
7860      *
7861      * <p>Clients wishing to provide custom behavior should override the
7862      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7863      * {@link OnApplyWindowInsetsListener} via the
7864      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7865      * method.</p>
7866      *
7867      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7868      * </p>
7869      *
7870      * @param insets Insets to apply
7871      * @return The provided insets minus the insets that were consumed
7872      */
dispatchApplyWindowInsets(WindowInsets insets)7873     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7874         try {
7875             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7876             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7877                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7878             } else {
7879                 return onApplyWindowInsets(insets);
7880             }
7881         } finally {
7882             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7883         }
7884     }
7885 
7886     /**
7887      * Compute the view's coordinate within the surface.
7888      *
7889      * <p>Computes the coordinates of this view in its surface. The argument
7890      * must be an array of two integers. After the method returns, the array
7891      * contains the x and y location in that order.</p>
7892      * @hide
7893      * @param location an array of two integers in which to hold the coordinates
7894      */
getLocationInSurface(@ize2) int[] location)7895     public void getLocationInSurface(@Size(2) int[] location) {
7896         getLocationInWindow(location);
7897         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7898             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7899             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7900         }
7901     }
7902 
7903     /**
7904      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7905      * only available if the view is attached.
7906      *
7907      * @return WindowInsets from the top of the view hierarchy or null if View is detached
7908      */
getRootWindowInsets()7909     public WindowInsets getRootWindowInsets() {
7910         if (mAttachInfo != null) {
7911             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7912         }
7913         return null;
7914     }
7915 
7916     /**
7917      * @hide Compute the insets that should be consumed by this view and the ones
7918      * that should propagate to those under it.
7919      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)7920     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7921         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7922                 || mAttachInfo == null
7923                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7924                         && !mAttachInfo.mOverscanRequested)) {
7925             outLocalInsets.set(inoutInsets);
7926             inoutInsets.set(0, 0, 0, 0);
7927             return true;
7928         } else {
7929             // The application wants to take care of fitting system window for
7930             // the content...  however we still need to take care of any overscan here.
7931             final Rect overscan = mAttachInfo.mOverscanInsets;
7932             outLocalInsets.set(overscan);
7933             inoutInsets.left -= overscan.left;
7934             inoutInsets.top -= overscan.top;
7935             inoutInsets.right -= overscan.right;
7936             inoutInsets.bottom -= overscan.bottom;
7937             return false;
7938         }
7939     }
7940 
7941     /**
7942      * Compute insets that should be consumed by this view and the ones that should propagate
7943      * to those under it.
7944      *
7945      * @param in Insets currently being processed by this View, likely received as a parameter
7946      *           to {@link #onApplyWindowInsets(WindowInsets)}.
7947      * @param outLocalInsets A Rect that will receive the insets that should be consumed
7948      *                       by this view
7949      * @return Insets that should be passed along to views under this one
7950      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)7951     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7952         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7953                 || mAttachInfo == null
7954                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7955             outLocalInsets.set(in.getSystemWindowInsets());
7956             return in.consumeSystemWindowInsets();
7957         } else {
7958             outLocalInsets.set(0, 0, 0, 0);
7959             return in;
7960         }
7961     }
7962 
7963     /**
7964      * Sets whether or not this view should account for system screen decorations
7965      * such as the status bar and inset its content; that is, controlling whether
7966      * the default implementation of {@link #fitSystemWindows(Rect)} will be
7967      * executed.  See that method for more details.
7968      *
7969      * <p>Note that if you are providing your own implementation of
7970      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7971      * flag to true -- your implementation will be overriding the default
7972      * implementation that checks this flag.
7973      *
7974      * @param fitSystemWindows If true, then the default implementation of
7975      * {@link #fitSystemWindows(Rect)} will be executed.
7976      *
7977      * @attr ref android.R.styleable#View_fitsSystemWindows
7978      * @see #getFitsSystemWindows()
7979      * @see #fitSystemWindows(Rect)
7980      * @see #setSystemUiVisibility(int)
7981      */
setFitsSystemWindows(boolean fitSystemWindows)7982     public void setFitsSystemWindows(boolean fitSystemWindows) {
7983         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7984     }
7985 
7986     /**
7987      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7988      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7989      * will be executed.
7990      *
7991      * @return {@code true} if the default implementation of
7992      * {@link #fitSystemWindows(Rect)} will be executed.
7993      *
7994      * @attr ref android.R.styleable#View_fitsSystemWindows
7995      * @see #setFitsSystemWindows(boolean)
7996      * @see #fitSystemWindows(Rect)
7997      * @see #setSystemUiVisibility(int)
7998      */
7999     @ViewDebug.ExportedProperty
getFitsSystemWindows()8000     public boolean getFitsSystemWindows() {
8001         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8002     }
8003 
8004     /** @hide */
fitsSystemWindows()8005     public boolean fitsSystemWindows() {
8006         return getFitsSystemWindows();
8007     }
8008 
8009     /**
8010      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8011      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8012      */
requestFitSystemWindows()8013     public void requestFitSystemWindows() {
8014         if (mParent != null) {
8015             mParent.requestFitSystemWindows();
8016         }
8017     }
8018 
8019     /**
8020      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8021      */
requestApplyInsets()8022     public void requestApplyInsets() {
8023         requestFitSystemWindows();
8024     }
8025 
8026     /**
8027      * For use by PhoneWindow to make its own system window fitting optional.
8028      * @hide
8029      */
makeOptionalFitsSystemWindows()8030     public void makeOptionalFitsSystemWindows() {
8031         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8032     }
8033 
8034     /**
8035      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8036      * treat them as such.
8037      * @hide
8038      */
getOutsets(Rect outOutsetRect)8039     public void getOutsets(Rect outOutsetRect) {
8040         if (mAttachInfo != null) {
8041             outOutsetRect.set(mAttachInfo.mOutsets);
8042         } else {
8043             outOutsetRect.setEmpty();
8044         }
8045     }
8046 
8047     /**
8048      * Returns the visibility status for this view.
8049      *
8050      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8051      * @attr ref android.R.styleable#View_visibility
8052      */
8053     @ViewDebug.ExportedProperty(mapping = {
8054         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8055         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8056         @ViewDebug.IntToString(from = GONE,      to = "GONE")
8057     })
8058     @Visibility
getVisibility()8059     public int getVisibility() {
8060         return mViewFlags & VISIBILITY_MASK;
8061     }
8062 
8063     /**
8064      * Set the enabled state of this view.
8065      *
8066      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8067      * @attr ref android.R.styleable#View_visibility
8068      */
8069     @RemotableViewMethod
setVisibility(@isibility int visibility)8070     public void setVisibility(@Visibility int visibility) {
8071         setFlags(visibility, VISIBILITY_MASK);
8072     }
8073 
8074     /**
8075      * Returns the enabled status for this view. The interpretation of the
8076      * enabled state varies by subclass.
8077      *
8078      * @return True if this view is enabled, false otherwise.
8079      */
8080     @ViewDebug.ExportedProperty
isEnabled()8081     public boolean isEnabled() {
8082         return (mViewFlags & ENABLED_MASK) == ENABLED;
8083     }
8084 
8085     /**
8086      * Set the enabled state of this view. The interpretation of the enabled
8087      * state varies by subclass.
8088      *
8089      * @param enabled True if this view is enabled, false otherwise.
8090      */
8091     @RemotableViewMethod
setEnabled(boolean enabled)8092     public void setEnabled(boolean enabled) {
8093         if (enabled == isEnabled()) return;
8094 
8095         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8096 
8097         /*
8098          * The View most likely has to change its appearance, so refresh
8099          * the drawable state.
8100          */
8101         refreshDrawableState();
8102 
8103         // Invalidate too, since the default behavior for views is to be
8104         // be drawn at 50% alpha rather than to change the drawable.
8105         invalidate(true);
8106 
8107         if (!enabled) {
8108             cancelPendingInputEvents();
8109         }
8110     }
8111 
8112     /**
8113      * Set whether this view can receive the focus.
8114      *
8115      * Setting this to false will also ensure that this view is not focusable
8116      * in touch mode.
8117      *
8118      * @param focusable If true, this view can receive the focus.
8119      *
8120      * @see #setFocusableInTouchMode(boolean)
8121      * @attr ref android.R.styleable#View_focusable
8122      */
setFocusable(boolean focusable)8123     public void setFocusable(boolean focusable) {
8124         if (!focusable) {
8125             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8126         }
8127         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8128     }
8129 
8130     /**
8131      * Set whether this view can receive focus while in touch mode.
8132      *
8133      * Setting this to true will also ensure that this view is focusable.
8134      *
8135      * @param focusableInTouchMode If true, this view can receive the focus while
8136      *   in touch mode.
8137      *
8138      * @see #setFocusable(boolean)
8139      * @attr ref android.R.styleable#View_focusableInTouchMode
8140      */
setFocusableInTouchMode(boolean focusableInTouchMode)8141     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8142         // Focusable in touch mode should always be set before the focusable flag
8143         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8144         // which, in touch mode, will not successfully request focus on this view
8145         // because the focusable in touch mode flag is not set
8146         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8147         if (focusableInTouchMode) {
8148             setFlags(FOCUSABLE, FOCUSABLE_MASK);
8149         }
8150     }
8151 
8152     /**
8153      * Set whether this view should have sound effects enabled for events such as
8154      * clicking and touching.
8155      *
8156      * <p>You may wish to disable sound effects for a view if you already play sounds,
8157      * for instance, a dial key that plays dtmf tones.
8158      *
8159      * @param soundEffectsEnabled whether sound effects are enabled for this view.
8160      * @see #isSoundEffectsEnabled()
8161      * @see #playSoundEffect(int)
8162      * @attr ref android.R.styleable#View_soundEffectsEnabled
8163      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)8164     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8165         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8166     }
8167 
8168     /**
8169      * @return whether this view should have sound effects enabled for events such as
8170      *     clicking and touching.
8171      *
8172      * @see #setSoundEffectsEnabled(boolean)
8173      * @see #playSoundEffect(int)
8174      * @attr ref android.R.styleable#View_soundEffectsEnabled
8175      */
8176     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()8177     public boolean isSoundEffectsEnabled() {
8178         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8179     }
8180 
8181     /**
8182      * Set whether this view should have haptic feedback for events such as
8183      * long presses.
8184      *
8185      * <p>You may wish to disable haptic feedback if your view already controls
8186      * its own haptic feedback.
8187      *
8188      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8189      * @see #isHapticFeedbackEnabled()
8190      * @see #performHapticFeedback(int)
8191      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8192      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)8193     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8194         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8195     }
8196 
8197     /**
8198      * @return whether this view should have haptic feedback enabled for events
8199      * long presses.
8200      *
8201      * @see #setHapticFeedbackEnabled(boolean)
8202      * @see #performHapticFeedback(int)
8203      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8204      */
8205     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()8206     public boolean isHapticFeedbackEnabled() {
8207         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8208     }
8209 
8210     /**
8211      * Returns the layout direction for this view.
8212      *
8213      * @return One of {@link #LAYOUT_DIRECTION_LTR},
8214      *   {@link #LAYOUT_DIRECTION_RTL},
8215      *   {@link #LAYOUT_DIRECTION_INHERIT} or
8216      *   {@link #LAYOUT_DIRECTION_LOCALE}.
8217      *
8218      * @attr ref android.R.styleable#View_layoutDirection
8219      *
8220      * @hide
8221      */
8222     @ViewDebug.ExportedProperty(category = "layout", mapping = {
8223         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8224         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8225         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8226         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8227     })
8228     @LayoutDir
getRawLayoutDirection()8229     public int getRawLayoutDirection() {
8230         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8231     }
8232 
8233     /**
8234      * Set the layout direction for this view. This will propagate a reset of layout direction
8235      * resolution to the view's children and resolve layout direction for this view.
8236      *
8237      * @param layoutDirection the layout direction to set. Should be one of:
8238      *
8239      * {@link #LAYOUT_DIRECTION_LTR},
8240      * {@link #LAYOUT_DIRECTION_RTL},
8241      * {@link #LAYOUT_DIRECTION_INHERIT},
8242      * {@link #LAYOUT_DIRECTION_LOCALE}.
8243      *
8244      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8245      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8246      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8247      *
8248      * @attr ref android.R.styleable#View_layoutDirection
8249      */
8250     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)8251     public void setLayoutDirection(@LayoutDir int layoutDirection) {
8252         if (getRawLayoutDirection() != layoutDirection) {
8253             // Reset the current layout direction and the resolved one
8254             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8255             resetRtlProperties();
8256             // Set the new layout direction (filtered)
8257             mPrivateFlags2 |=
8258                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8259             // We need to resolve all RTL properties as they all depend on layout direction
8260             resolveRtlPropertiesIfNeeded();
8261             requestLayout();
8262             invalidate(true);
8263         }
8264     }
8265 
8266     /**
8267      * Returns the resolved layout direction for this view.
8268      *
8269      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8270      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8271      *
8272      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8273      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8274      *
8275      * @attr ref android.R.styleable#View_layoutDirection
8276      */
8277     @ViewDebug.ExportedProperty(category = "layout", mapping = {
8278         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8279         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8280     })
8281     @ResolvedLayoutDir
getLayoutDirection()8282     public int getLayoutDirection() {
8283         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8284         if (targetSdkVersion < JELLY_BEAN_MR1) {
8285             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8286             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8287         }
8288         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8289                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8290     }
8291 
8292     /**
8293      * Indicates whether or not this view's layout is right-to-left. This is resolved from
8294      * layout attribute and/or the inherited value from the parent
8295      *
8296      * @return true if the layout is right-to-left.
8297      *
8298      * @hide
8299      */
8300     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()8301     public boolean isLayoutRtl() {
8302         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8303     }
8304 
8305     /**
8306      * Indicates whether the view is currently tracking transient state that the
8307      * app should not need to concern itself with saving and restoring, but that
8308      * the framework should take special note to preserve when possible.
8309      *
8310      * <p>A view with transient state cannot be trivially rebound from an external
8311      * data source, such as an adapter binding item views in a list. This may be
8312      * because the view is performing an animation, tracking user selection
8313      * of content, or similar.</p>
8314      *
8315      * @return true if the view has transient state
8316      */
8317     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()8318     public boolean hasTransientState() {
8319         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8320     }
8321 
8322     /**
8323      * Set whether this view is currently tracking transient state that the
8324      * framework should attempt to preserve when possible. This flag is reference counted,
8325      * so every call to setHasTransientState(true) should be paired with a later call
8326      * to setHasTransientState(false).
8327      *
8328      * <p>A view with transient state cannot be trivially rebound from an external
8329      * data source, such as an adapter binding item views in a list. This may be
8330      * because the view is performing an animation, tracking user selection
8331      * of content, or similar.</p>
8332      *
8333      * @param hasTransientState true if this view has transient state
8334      */
setHasTransientState(boolean hasTransientState)8335     public void setHasTransientState(boolean hasTransientState) {
8336         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8337                 mTransientStateCount - 1;
8338         if (mTransientStateCount < 0) {
8339             mTransientStateCount = 0;
8340             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8341                     "unmatched pair of setHasTransientState calls");
8342         } else if ((hasTransientState && mTransientStateCount == 1) ||
8343                 (!hasTransientState && mTransientStateCount == 0)) {
8344             // update flag if we've just incremented up from 0 or decremented down to 0
8345             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8346                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8347             if (mParent != null) {
8348                 try {
8349                     mParent.childHasTransientStateChanged(this, hasTransientState);
8350                 } catch (AbstractMethodError e) {
8351                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8352                             " does not fully implement ViewParent", e);
8353                 }
8354             }
8355         }
8356     }
8357 
8358     /**
8359      * Returns true if this view is currently attached to a window.
8360      */
isAttachedToWindow()8361     public boolean isAttachedToWindow() {
8362         return mAttachInfo != null;
8363     }
8364 
8365     /**
8366      * Returns true if this view has been through at least one layout since it
8367      * was last attached to or detached from a window.
8368      */
isLaidOut()8369     public boolean isLaidOut() {
8370         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8371     }
8372 
8373     /**
8374      * If this view doesn't do any drawing on its own, set this flag to
8375      * allow further optimizations. By default, this flag is not set on
8376      * View, but could be set on some View subclasses such as ViewGroup.
8377      *
8378      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8379      * you should clear this flag.
8380      *
8381      * @param willNotDraw whether or not this View draw on its own
8382      */
setWillNotDraw(boolean willNotDraw)8383     public void setWillNotDraw(boolean willNotDraw) {
8384         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8385     }
8386 
8387     /**
8388      * Returns whether or not this View draws on its own.
8389      *
8390      * @return true if this view has nothing to draw, false otherwise
8391      */
8392     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()8393     public boolean willNotDraw() {
8394         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8395     }
8396 
8397     /**
8398      * When a View's drawing cache is enabled, drawing is redirected to an
8399      * offscreen bitmap. Some views, like an ImageView, must be able to
8400      * bypass this mechanism if they already draw a single bitmap, to avoid
8401      * unnecessary usage of the memory.
8402      *
8403      * @param willNotCacheDrawing true if this view does not cache its
8404      *        drawing, false otherwise
8405      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)8406     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8407         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8408     }
8409 
8410     /**
8411      * Returns whether or not this View can cache its drawing or not.
8412      *
8413      * @return true if this view does not cache its drawing, false otherwise
8414      */
8415     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()8416     public boolean willNotCacheDrawing() {
8417         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8418     }
8419 
8420     /**
8421      * Indicates whether this view reacts to click events or not.
8422      *
8423      * @return true if the view is clickable, false otherwise
8424      *
8425      * @see #setClickable(boolean)
8426      * @attr ref android.R.styleable#View_clickable
8427      */
8428     @ViewDebug.ExportedProperty
isClickable()8429     public boolean isClickable() {
8430         return (mViewFlags & CLICKABLE) == CLICKABLE;
8431     }
8432 
8433     /**
8434      * Enables or disables click events for this view. When a view
8435      * is clickable it will change its state to "pressed" on every click.
8436      * Subclasses should set the view clickable to visually react to
8437      * user's clicks.
8438      *
8439      * @param clickable true to make the view clickable, false otherwise
8440      *
8441      * @see #isClickable()
8442      * @attr ref android.R.styleable#View_clickable
8443      */
setClickable(boolean clickable)8444     public void setClickable(boolean clickable) {
8445         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8446     }
8447 
8448     /**
8449      * Indicates whether this view reacts to long click events or not.
8450      *
8451      * @return true if the view is long clickable, false otherwise
8452      *
8453      * @see #setLongClickable(boolean)
8454      * @attr ref android.R.styleable#View_longClickable
8455      */
isLongClickable()8456     public boolean isLongClickable() {
8457         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8458     }
8459 
8460     /**
8461      * Enables or disables long click events for this view. When a view is long
8462      * clickable it reacts to the user holding down the button for a longer
8463      * duration than a tap. This event can either launch the listener or a
8464      * context menu.
8465      *
8466      * @param longClickable true to make the view long clickable, false otherwise
8467      * @see #isLongClickable()
8468      * @attr ref android.R.styleable#View_longClickable
8469      */
setLongClickable(boolean longClickable)8470     public void setLongClickable(boolean longClickable) {
8471         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8472     }
8473 
8474     /**
8475      * Indicates whether this view reacts to context clicks or not.
8476      *
8477      * @return true if the view is context clickable, false otherwise
8478      * @see #setContextClickable(boolean)
8479      * @attr ref android.R.styleable#View_contextClickable
8480      */
isContextClickable()8481     public boolean isContextClickable() {
8482         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8483     }
8484 
8485     /**
8486      * Enables or disables context clicking for this view. This event can launch the listener.
8487      *
8488      * @param contextClickable true to make the view react to a context click, false otherwise
8489      * @see #isContextClickable()
8490      * @attr ref android.R.styleable#View_contextClickable
8491      */
setContextClickable(boolean contextClickable)8492     public void setContextClickable(boolean contextClickable) {
8493         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8494     }
8495 
8496     /**
8497      * Sets the pressed state for this view and provides a touch coordinate for
8498      * animation hinting.
8499      *
8500      * @param pressed Pass true to set the View's internal state to "pressed",
8501      *            or false to reverts the View's internal state from a
8502      *            previously set "pressed" state.
8503      * @param x The x coordinate of the touch that caused the press
8504      * @param y The y coordinate of the touch that caused the press
8505      */
setPressed(boolean pressed, float x, float y)8506     private void setPressed(boolean pressed, float x, float y) {
8507         if (pressed) {
8508             drawableHotspotChanged(x, y);
8509         }
8510 
8511         setPressed(pressed);
8512     }
8513 
8514     /**
8515      * Sets the pressed state for this view.
8516      *
8517      * @see #isClickable()
8518      * @see #setClickable(boolean)
8519      *
8520      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8521      *        the View's internal state from a previously set "pressed" state.
8522      */
setPressed(boolean pressed)8523     public void setPressed(boolean pressed) {
8524         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8525 
8526         if (pressed) {
8527             mPrivateFlags |= PFLAG_PRESSED;
8528         } else {
8529             mPrivateFlags &= ~PFLAG_PRESSED;
8530         }
8531 
8532         if (needsRefresh) {
8533             refreshDrawableState();
8534         }
8535         dispatchSetPressed(pressed);
8536     }
8537 
8538     /**
8539      * Dispatch setPressed to all of this View's children.
8540      *
8541      * @see #setPressed(boolean)
8542      *
8543      * @param pressed The new pressed state
8544      */
dispatchSetPressed(boolean pressed)8545     protected void dispatchSetPressed(boolean pressed) {
8546     }
8547 
8548     /**
8549      * Indicates whether the view is currently in pressed state. Unless
8550      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8551      * the pressed state.
8552      *
8553      * @see #setPressed(boolean)
8554      * @see #isClickable()
8555      * @see #setClickable(boolean)
8556      *
8557      * @return true if the view is currently pressed, false otherwise
8558      */
8559     @ViewDebug.ExportedProperty
isPressed()8560     public boolean isPressed() {
8561         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8562     }
8563 
8564     /**
8565      * @hide
8566      * Indicates whether this view will participate in data collection through
8567      * {@link ViewStructure}.  If true, it will not provide any data
8568      * for itself or its children.  If false, the normal data collection will be allowed.
8569      *
8570      * @return Returns false if assist data collection is not blocked, else true.
8571      *
8572      * @see #setAssistBlocked(boolean)
8573      * @attr ref android.R.styleable#View_assistBlocked
8574      */
isAssistBlocked()8575     public boolean isAssistBlocked() {
8576         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8577     }
8578 
8579     /**
8580      * @hide
8581      * Controls whether assist data collection from this view and its children is enabled
8582      * (that is, whether {@link #onProvideStructure} and
8583      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8584      * allowing normal assist collection.  Setting this to false will disable assist collection.
8585      *
8586      * @param enabled Set to true to <em>disable</em> assist data collection, or false
8587      * (the default) to allow it.
8588      *
8589      * @see #isAssistBlocked()
8590      * @see #onProvideStructure
8591      * @see #onProvideVirtualStructure
8592      * @attr ref android.R.styleable#View_assistBlocked
8593      */
setAssistBlocked(boolean enabled)8594     public void setAssistBlocked(boolean enabled) {
8595         if (enabled) {
8596             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8597         } else {
8598             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8599         }
8600     }
8601 
8602     /**
8603      * Indicates whether this view will save its state (that is,
8604      * whether its {@link #onSaveInstanceState} method will be called).
8605      *
8606      * @return Returns true if the view state saving is enabled, else false.
8607      *
8608      * @see #setSaveEnabled(boolean)
8609      * @attr ref android.R.styleable#View_saveEnabled
8610      */
isSaveEnabled()8611     public boolean isSaveEnabled() {
8612         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8613     }
8614 
8615     /**
8616      * Controls whether the saving of this view's state is
8617      * enabled (that is, whether its {@link #onSaveInstanceState} method
8618      * will be called).  Note that even if freezing is enabled, the
8619      * view still must have an id assigned to it (via {@link #setId(int)})
8620      * for its state to be saved.  This flag can only disable the
8621      * saving of this view; any child views may still have their state saved.
8622      *
8623      * @param enabled Set to false to <em>disable</em> state saving, or true
8624      * (the default) to allow it.
8625      *
8626      * @see #isSaveEnabled()
8627      * @see #setId(int)
8628      * @see #onSaveInstanceState()
8629      * @attr ref android.R.styleable#View_saveEnabled
8630      */
setSaveEnabled(boolean enabled)8631     public void setSaveEnabled(boolean enabled) {
8632         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8633     }
8634 
8635     /**
8636      * Gets whether the framework should discard touches when the view's
8637      * window is obscured by another visible window.
8638      * Refer to the {@link View} security documentation for more details.
8639      *
8640      * @return True if touch filtering is enabled.
8641      *
8642      * @see #setFilterTouchesWhenObscured(boolean)
8643      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8644      */
8645     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()8646     public boolean getFilterTouchesWhenObscured() {
8647         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8648     }
8649 
8650     /**
8651      * Sets whether the framework should discard touches when the view's
8652      * window is obscured by another visible window.
8653      * Refer to the {@link View} security documentation for more details.
8654      *
8655      * @param enabled True if touch filtering should be enabled.
8656      *
8657      * @see #getFilterTouchesWhenObscured
8658      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8659      */
setFilterTouchesWhenObscured(boolean enabled)8660     public void setFilterTouchesWhenObscured(boolean enabled) {
8661         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8662                 FILTER_TOUCHES_WHEN_OBSCURED);
8663     }
8664 
8665     /**
8666      * Indicates whether the entire hierarchy under this view will save its
8667      * state when a state saving traversal occurs from its parent.  The default
8668      * is true; if false, these views will not be saved unless
8669      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8670      *
8671      * @return Returns true if the view state saving from parent is enabled, else false.
8672      *
8673      * @see #setSaveFromParentEnabled(boolean)
8674      */
isSaveFromParentEnabled()8675     public boolean isSaveFromParentEnabled() {
8676         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8677     }
8678 
8679     /**
8680      * Controls whether the entire hierarchy under this view will save its
8681      * state when a state saving traversal occurs from its parent.  The default
8682      * is true; if false, these views will not be saved unless
8683      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8684      *
8685      * @param enabled Set to false to <em>disable</em> state saving, or true
8686      * (the default) to allow it.
8687      *
8688      * @see #isSaveFromParentEnabled()
8689      * @see #setId(int)
8690      * @see #onSaveInstanceState()
8691      */
setSaveFromParentEnabled(boolean enabled)8692     public void setSaveFromParentEnabled(boolean enabled) {
8693         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8694     }
8695 
8696 
8697     /**
8698      * Returns whether this View is able to take focus.
8699      *
8700      * @return True if this view can take focus, or false otherwise.
8701      * @attr ref android.R.styleable#View_focusable
8702      */
8703     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()8704     public final boolean isFocusable() {
8705         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8706     }
8707 
8708     /**
8709      * When a view is focusable, it may not want to take focus when in touch mode.
8710      * For example, a button would like focus when the user is navigating via a D-pad
8711      * so that the user can click on it, but once the user starts touching the screen,
8712      * the button shouldn't take focus
8713      * @return Whether the view is focusable in touch mode.
8714      * @attr ref android.R.styleable#View_focusableInTouchMode
8715      */
8716     @ViewDebug.ExportedProperty
isFocusableInTouchMode()8717     public final boolean isFocusableInTouchMode() {
8718         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8719     }
8720 
8721     /**
8722      * Find the nearest view in the specified direction that can take focus.
8723      * This does not actually give focus to that view.
8724      *
8725      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8726      *
8727      * @return The nearest focusable in the specified direction, or null if none
8728      *         can be found.
8729      */
focusSearch(@ocusRealDirection int direction)8730     public View focusSearch(@FocusRealDirection int direction) {
8731         if (mParent != null) {
8732             return mParent.focusSearch(this, direction);
8733         } else {
8734             return null;
8735         }
8736     }
8737 
8738     /**
8739      * This method is the last chance for the focused view and its ancestors to
8740      * respond to an arrow key. This is called when the focused view did not
8741      * consume the key internally, nor could the view system find a new view in
8742      * the requested direction to give focus to.
8743      *
8744      * @param focused The currently focused view.
8745      * @param direction The direction focus wants to move. One of FOCUS_UP,
8746      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8747      * @return True if the this view consumed this unhandled move.
8748      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)8749     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8750         return false;
8751     }
8752 
8753     /**
8754      * If a user manually specified the next view id for a particular direction,
8755      * use the root to look up the view.
8756      * @param root The root view of the hierarchy containing this view.
8757      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8758      * or FOCUS_BACKWARD.
8759      * @return The user specified next view, or null if there is none.
8760      */
findUserSetNextFocus(View root, @FocusDirection int direction)8761     View findUserSetNextFocus(View root, @FocusDirection int direction) {
8762         switch (direction) {
8763             case FOCUS_LEFT:
8764                 if (mNextFocusLeftId == View.NO_ID) return null;
8765                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8766             case FOCUS_RIGHT:
8767                 if (mNextFocusRightId == View.NO_ID) return null;
8768                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
8769             case FOCUS_UP:
8770                 if (mNextFocusUpId == View.NO_ID) return null;
8771                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
8772             case FOCUS_DOWN:
8773                 if (mNextFocusDownId == View.NO_ID) return null;
8774                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
8775             case FOCUS_FORWARD:
8776                 if (mNextFocusForwardId == View.NO_ID) return null;
8777                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8778             case FOCUS_BACKWARD: {
8779                 if (mID == View.NO_ID) return null;
8780                 final int id = mID;
8781                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8782                     @Override
8783                     public boolean apply(View t) {
8784                         return t.mNextFocusForwardId == id;
8785                     }
8786                 });
8787             }
8788         }
8789         return null;
8790     }
8791 
findViewInsideOutShouldExist(View root, int id)8792     private View findViewInsideOutShouldExist(View root, int id) {
8793         if (mMatchIdPredicate == null) {
8794             mMatchIdPredicate = new MatchIdPredicate();
8795         }
8796         mMatchIdPredicate.mId = id;
8797         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8798         if (result == null) {
8799             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8800         }
8801         return result;
8802     }
8803 
8804     /**
8805      * Find and return all focusable views that are descendants of this view,
8806      * possibly including this view if it is focusable itself.
8807      *
8808      * @param direction The direction of the focus
8809      * @return A list of focusable views
8810      */
getFocusables(@ocusDirection int direction)8811     public ArrayList<View> getFocusables(@FocusDirection int direction) {
8812         ArrayList<View> result = new ArrayList<View>(24);
8813         addFocusables(result, direction);
8814         return result;
8815     }
8816 
8817     /**
8818      * Add any focusable views that are descendants of this view (possibly
8819      * including this view if it is focusable itself) to views.  If we are in touch mode,
8820      * only add views that are also focusable in touch mode.
8821      *
8822      * @param views Focusable views found so far
8823      * @param direction The direction of the focus
8824      */
addFocusables(ArrayList<View> views, @FocusDirection int direction)8825     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8826         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8827     }
8828 
8829     /**
8830      * Adds any focusable views that are descendants of this view (possibly
8831      * including this view if it is focusable itself) to views. This method
8832      * adds all focusable views regardless if we are in touch mode or
8833      * only views focusable in touch mode if we are in touch mode or
8834      * only views that can take accessibility focus if accessibility is enabled
8835      * depending on the focusable mode parameter.
8836      *
8837      * @param views Focusable views found so far or null if all we are interested is
8838      *        the number of focusables.
8839      * @param direction The direction of the focus.
8840      * @param focusableMode The type of focusables to be added.
8841      *
8842      * @see #FOCUSABLES_ALL
8843      * @see #FOCUSABLES_TOUCH_MODE
8844      */
addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)8845     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8846             @FocusableMode int focusableMode) {
8847         if (views == null) {
8848             return;
8849         }
8850         if (!isFocusable()) {
8851             return;
8852         }
8853         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8854                 && !isFocusableInTouchMode()) {
8855             return;
8856         }
8857         views.add(this);
8858     }
8859 
8860     /**
8861      * Finds the Views that contain given text. The containment is case insensitive.
8862      * The search is performed by either the text that the View renders or the content
8863      * description that describes the view for accessibility purposes and the view does
8864      * not render or both. Clients can specify how the search is to be performed via
8865      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8866      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8867      *
8868      * @param outViews The output list of matching Views.
8869      * @param searched The text to match against.
8870      *
8871      * @see #FIND_VIEWS_WITH_TEXT
8872      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8873      * @see #setContentDescription(CharSequence)
8874      */
findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)8875     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8876             @FindViewFlags int flags) {
8877         if (getAccessibilityNodeProvider() != null) {
8878             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8879                 outViews.add(this);
8880             }
8881         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8882                 && (searched != null && searched.length() > 0)
8883                 && (mContentDescription != null && mContentDescription.length() > 0)) {
8884             String searchedLowerCase = searched.toString().toLowerCase();
8885             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8886             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8887                 outViews.add(this);
8888             }
8889         }
8890     }
8891 
8892     /**
8893      * Find and return all touchable views that are descendants of this view,
8894      * possibly including this view if it is touchable itself.
8895      *
8896      * @return A list of touchable views
8897      */
getTouchables()8898     public ArrayList<View> getTouchables() {
8899         ArrayList<View> result = new ArrayList<View>();
8900         addTouchables(result);
8901         return result;
8902     }
8903 
8904     /**
8905      * Add any touchable views that are descendants of this view (possibly
8906      * including this view if it is touchable itself) to views.
8907      *
8908      * @param views Touchable views found so far
8909      */
addTouchables(ArrayList<View> views)8910     public void addTouchables(ArrayList<View> views) {
8911         final int viewFlags = mViewFlags;
8912 
8913         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8914                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8915                 && (viewFlags & ENABLED_MASK) == ENABLED) {
8916             views.add(this);
8917         }
8918     }
8919 
8920     /**
8921      * Returns whether this View is accessibility focused.
8922      *
8923      * @return True if this View is accessibility focused.
8924      */
isAccessibilityFocused()8925     public boolean isAccessibilityFocused() {
8926         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8927     }
8928 
8929     /**
8930      * Call this to try to give accessibility focus to this view.
8931      *
8932      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8933      * returns false or the view is no visible or the view already has accessibility
8934      * focus.
8935      *
8936      * See also {@link #focusSearch(int)}, which is what you call to say that you
8937      * have focus, and you want your parent to look for the next one.
8938      *
8939      * @return Whether this view actually took accessibility focus.
8940      *
8941      * @hide
8942      */
requestAccessibilityFocus()8943     public boolean requestAccessibilityFocus() {
8944         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8945         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8946             return false;
8947         }
8948         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8949             return false;
8950         }
8951         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8952             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8953             ViewRootImpl viewRootImpl = getViewRootImpl();
8954             if (viewRootImpl != null) {
8955                 viewRootImpl.setAccessibilityFocus(this, null);
8956             }
8957             invalidate();
8958             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8959             return true;
8960         }
8961         return false;
8962     }
8963 
8964     /**
8965      * Call this to try to clear accessibility focus of this view.
8966      *
8967      * See also {@link #focusSearch(int)}, which is what you call to say that you
8968      * have focus, and you want your parent to look for the next one.
8969      *
8970      * @hide
8971      */
clearAccessibilityFocus()8972     public void clearAccessibilityFocus() {
8973         clearAccessibilityFocusNoCallbacks(0);
8974 
8975         // Clear the global reference of accessibility focus if this view or
8976         // any of its descendants had accessibility focus. This will NOT send
8977         // an event or update internal state if focus is cleared from a
8978         // descendant view, which may leave views in inconsistent states.
8979         final ViewRootImpl viewRootImpl = getViewRootImpl();
8980         if (viewRootImpl != null) {
8981             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8982             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8983                 viewRootImpl.setAccessibilityFocus(null, null);
8984             }
8985         }
8986     }
8987 
sendAccessibilityHoverEvent(int eventType)8988     private void sendAccessibilityHoverEvent(int eventType) {
8989         // Since we are not delivering to a client accessibility events from not
8990         // important views (unless the clinet request that) we need to fire the
8991         // event from the deepest view exposed to the client. As a consequence if
8992         // the user crosses a not exposed view the client will see enter and exit
8993         // of the exposed predecessor followed by and enter and exit of that same
8994         // predecessor when entering and exiting the not exposed descendant. This
8995         // is fine since the client has a clear idea which view is hovered at the
8996         // price of a couple more events being sent. This is a simple and
8997         // working solution.
8998         View source = this;
8999         while (true) {
9000             if (source.includeForAccessibility()) {
9001                 source.sendAccessibilityEvent(eventType);
9002                 return;
9003             }
9004             ViewParent parent = source.getParent();
9005             if (parent instanceof View) {
9006                 source = (View) parent;
9007             } else {
9008                 return;
9009             }
9010         }
9011     }
9012 
9013     /**
9014      * Clears accessibility focus without calling any callback methods
9015      * normally invoked in {@link #clearAccessibilityFocus()}. This method
9016      * is used separately from that one for clearing accessibility focus when
9017      * giving this focus to another view.
9018      *
9019      * @param action The action, if any, that led to focus being cleared. Set to
9020      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9021      * the window.
9022      */
clearAccessibilityFocusNoCallbacks(int action)9023     void clearAccessibilityFocusNoCallbacks(int action) {
9024         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9025             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9026             invalidate();
9027             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9028                 AccessibilityEvent event = AccessibilityEvent.obtain(
9029                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9030                 event.setAction(action);
9031                 if (mAccessibilityDelegate != null) {
9032                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9033                 } else {
9034                     sendAccessibilityEventUnchecked(event);
9035                 }
9036             }
9037         }
9038     }
9039 
9040     /**
9041      * Call this to try to give focus to a specific view or to one of its
9042      * descendants.
9043      *
9044      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9045      * false), or if it is focusable and it is not focusable in touch mode
9046      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9047      *
9048      * See also {@link #focusSearch(int)}, which is what you call to say that you
9049      * have focus, and you want your parent to look for the next one.
9050      *
9051      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9052      * {@link #FOCUS_DOWN} and <code>null</code>.
9053      *
9054      * @return Whether this view or one of its descendants actually took focus.
9055      */
requestFocus()9056     public final boolean requestFocus() {
9057         return requestFocus(View.FOCUS_DOWN);
9058     }
9059 
9060     /**
9061      * Call this to try to give focus to a specific view or to one of its
9062      * descendants and give it a hint about what direction focus is heading.
9063      *
9064      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9065      * false), or if it is focusable and it is not focusable in touch mode
9066      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9067      *
9068      * See also {@link #focusSearch(int)}, which is what you call to say that you
9069      * have focus, and you want your parent to look for the next one.
9070      *
9071      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9072      * <code>null</code> set for the previously focused rectangle.
9073      *
9074      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9075      * @return Whether this view or one of its descendants actually took focus.
9076      */
requestFocus(int direction)9077     public final boolean requestFocus(int direction) {
9078         return requestFocus(direction, null);
9079     }
9080 
9081     /**
9082      * Call this to try to give focus to a specific view or to one of its descendants
9083      * and give it hints about the direction and a specific rectangle that the focus
9084      * is coming from.  The rectangle can help give larger views a finer grained hint
9085      * about where focus is coming from, and therefore, where to show selection, or
9086      * forward focus change internally.
9087      *
9088      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9089      * false), or if it is focusable and it is not focusable in touch mode
9090      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9091      *
9092      * A View will not take focus if it is not visible.
9093      *
9094      * A View will not take focus if one of its parents has
9095      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9096      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9097      *
9098      * See also {@link #focusSearch(int)}, which is what you call to say that you
9099      * have focus, and you want your parent to look for the next one.
9100      *
9101      * You may wish to override this method if your custom {@link View} has an internal
9102      * {@link View} that it wishes to forward the request to.
9103      *
9104      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9105      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9106      *        to give a finer grained hint about where focus is coming from.  May be null
9107      *        if there is no hint.
9108      * @return Whether this view or one of its descendants actually took focus.
9109      */
requestFocus(int direction, Rect previouslyFocusedRect)9110     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9111         return requestFocusNoSearch(direction, previouslyFocusedRect);
9112     }
9113 
requestFocusNoSearch(int direction, Rect previouslyFocusedRect)9114     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9115         // need to be focusable
9116         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9117                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9118             return false;
9119         }
9120 
9121         // need to be focusable in touch mode if in touch mode
9122         if (isInTouchMode() &&
9123             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9124                return false;
9125         }
9126 
9127         // need to not have any parents blocking us
9128         if (hasAncestorThatBlocksDescendantFocus()) {
9129             return false;
9130         }
9131 
9132         handleFocusGainInternal(direction, previouslyFocusedRect);
9133         return true;
9134     }
9135 
9136     /**
9137      * Call this to try to give focus to a specific view or to one of its descendants. This is a
9138      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9139      * touch mode to request focus when they are touched.
9140      *
9141      * @return Whether this view or one of its descendants actually took focus.
9142      *
9143      * @see #isInTouchMode()
9144      *
9145      */
requestFocusFromTouch()9146     public final boolean requestFocusFromTouch() {
9147         // Leave touch mode if we need to
9148         if (isInTouchMode()) {
9149             ViewRootImpl viewRoot = getViewRootImpl();
9150             if (viewRoot != null) {
9151                 viewRoot.ensureTouchMode(false);
9152             }
9153         }
9154         return requestFocus(View.FOCUS_DOWN);
9155     }
9156 
9157     /**
9158      * @return Whether any ancestor of this view blocks descendant focus.
9159      */
hasAncestorThatBlocksDescendantFocus()9160     private boolean hasAncestorThatBlocksDescendantFocus() {
9161         final boolean focusableInTouchMode = isFocusableInTouchMode();
9162         ViewParent ancestor = mParent;
9163         while (ancestor instanceof ViewGroup) {
9164             final ViewGroup vgAncestor = (ViewGroup) ancestor;
9165             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9166                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9167                 return true;
9168             } else {
9169                 ancestor = vgAncestor.getParent();
9170             }
9171         }
9172         return false;
9173     }
9174 
9175     /**
9176      * Gets the mode for determining whether this View is important for accessibility
9177      * which is if it fires accessibility events and if it is reported to
9178      * accessibility services that query the screen.
9179      *
9180      * @return The mode for determining whether a View is important for accessibility.
9181      *
9182      * @attr ref android.R.styleable#View_importantForAccessibility
9183      *
9184      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9185      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9186      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9187      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9188      */
9189     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9190             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9191             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9192             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9193             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9194                     to = "noHideDescendants")
9195         })
getImportantForAccessibility()9196     public int getImportantForAccessibility() {
9197         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9198                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9199     }
9200 
9201     /**
9202      * Sets the live region mode for this view. This indicates to accessibility
9203      * services whether they should automatically notify the user about changes
9204      * to the view's content description or text, or to the content descriptions
9205      * or text of the view's children (where applicable).
9206      * <p>
9207      * For example, in a login screen with a TextView that displays an "incorrect
9208      * password" notification, that view should be marked as a live region with
9209      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9210      * <p>
9211      * To disable change notifications for this view, use
9212      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9213      * mode for most views.
9214      * <p>
9215      * To indicate that the user should be notified of changes, use
9216      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9217      * <p>
9218      * If the view's changes should interrupt ongoing speech and notify the user
9219      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9220      *
9221      * @param mode The live region mode for this view, one of:
9222      *        <ul>
9223      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9224      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9225      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9226      *        </ul>
9227      * @attr ref android.R.styleable#View_accessibilityLiveRegion
9228      */
setAccessibilityLiveRegion(int mode)9229     public void setAccessibilityLiveRegion(int mode) {
9230         if (mode != getAccessibilityLiveRegion()) {
9231             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9232             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9233                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9234             notifyViewAccessibilityStateChangedIfNeeded(
9235                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9236         }
9237     }
9238 
9239     /**
9240      * Gets the live region mode for this View.
9241      *
9242      * @return The live region mode for the view.
9243      *
9244      * @attr ref android.R.styleable#View_accessibilityLiveRegion
9245      *
9246      * @see #setAccessibilityLiveRegion(int)
9247      */
getAccessibilityLiveRegion()9248     public int getAccessibilityLiveRegion() {
9249         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9250                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9251     }
9252 
9253     /**
9254      * Sets how to determine whether this view is important for accessibility
9255      * which is if it fires accessibility events and if it is reported to
9256      * accessibility services that query the screen.
9257      *
9258      * @param mode How to determine whether this view is important for accessibility.
9259      *
9260      * @attr ref android.R.styleable#View_importantForAccessibility
9261      *
9262      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9263      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9264      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9265      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9266      */
setImportantForAccessibility(int mode)9267     public void setImportantForAccessibility(int mode) {
9268         final int oldMode = getImportantForAccessibility();
9269         if (mode != oldMode) {
9270             final boolean hideDescendants =
9271                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9272 
9273             // If this node or its descendants are no longer important, try to
9274             // clear accessibility focus.
9275             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9276                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
9277                 if (focusHost != null) {
9278                     focusHost.clearAccessibilityFocus();
9279                 }
9280             }
9281 
9282             // If we're moving between AUTO and another state, we might not need
9283             // to send a subtree changed notification. We'll store the computed
9284             // importance, since we'll need to check it later to make sure.
9285             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9286                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9287             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9288             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9289             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9290                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9291             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9292                 notifySubtreeAccessibilityStateChangedIfNeeded();
9293             } else {
9294                 notifyViewAccessibilityStateChangedIfNeeded(
9295                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9296             }
9297         }
9298     }
9299 
9300     /**
9301      * Returns the view within this view's hierarchy that is hosting
9302      * accessibility focus.
9303      *
9304      * @param searchDescendants whether to search for focus in descendant views
9305      * @return the view hosting accessibility focus, or {@code null}
9306      */
findAccessibilityFocusHost(boolean searchDescendants)9307     private View findAccessibilityFocusHost(boolean searchDescendants) {
9308         if (isAccessibilityFocusedViewOrHost()) {
9309             return this;
9310         }
9311 
9312         if (searchDescendants) {
9313             final ViewRootImpl viewRoot = getViewRootImpl();
9314             if (viewRoot != null) {
9315                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
9316                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9317                     return focusHost;
9318                 }
9319             }
9320         }
9321 
9322         return null;
9323     }
9324 
9325     /**
9326      * Computes whether this view should be exposed for accessibility. In
9327      * general, views that are interactive or provide information are exposed
9328      * while views that serve only as containers are hidden.
9329      * <p>
9330      * If an ancestor of this view has importance
9331      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9332      * returns <code>false</code>.
9333      * <p>
9334      * Otherwise, the value is computed according to the view's
9335      * {@link #getImportantForAccessibility()} value:
9336      * <ol>
9337      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9338      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9339      * </code>
9340      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9341      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9342      * view satisfies any of the following:
9343      * <ul>
9344      * <li>Is actionable, e.g. {@link #isClickable()},
9345      * {@link #isLongClickable()}, or {@link #isFocusable()}
9346      * <li>Has an {@link AccessibilityDelegate}
9347      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9348      * {@link OnKeyListener}, etc.
9349      * <li>Is an accessibility live region, e.g.
9350      * {@link #getAccessibilityLiveRegion()} is not
9351      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9352      * </ul>
9353      * </ol>
9354      *
9355      * @return Whether the view is exposed for accessibility.
9356      * @see #setImportantForAccessibility(int)
9357      * @see #getImportantForAccessibility()
9358      */
isImportantForAccessibility()9359     public boolean isImportantForAccessibility() {
9360         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9361                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9362         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9363                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9364             return false;
9365         }
9366 
9367         // Check parent mode to ensure we're not hidden.
9368         ViewParent parent = mParent;
9369         while (parent instanceof View) {
9370             if (((View) parent).getImportantForAccessibility()
9371                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9372                 return false;
9373             }
9374             parent = parent.getParent();
9375         }
9376 
9377         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9378                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9379                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9380     }
9381 
9382     /**
9383      * Gets the parent for accessibility purposes. Note that the parent for
9384      * accessibility is not necessary the immediate parent. It is the first
9385      * predecessor that is important for accessibility.
9386      *
9387      * @return The parent for accessibility purposes.
9388      */
getParentForAccessibility()9389     public ViewParent getParentForAccessibility() {
9390         if (mParent instanceof View) {
9391             View parentView = (View) mParent;
9392             if (parentView.includeForAccessibility()) {
9393                 return mParent;
9394             } else {
9395                 return mParent.getParentForAccessibility();
9396             }
9397         }
9398         return null;
9399     }
9400 
9401     /**
9402      * Adds the children of this View relevant for accessibility to the given list
9403      * as output. Since some Views are not important for accessibility the added
9404      * child views are not necessarily direct children of this view, rather they are
9405      * the first level of descendants important for accessibility.
9406      *
9407      * @param outChildren The output list that will receive children for accessibility.
9408      */
addChildrenForAccessibility(ArrayList<View> outChildren)9409     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9410 
9411     }
9412 
9413     /**
9414      * Whether to regard this view for accessibility. A view is regarded for
9415      * accessibility if it is important for accessibility or the querying
9416      * accessibility service has explicitly requested that view not
9417      * important for accessibility are regarded.
9418      *
9419      * @return Whether to regard the view for accessibility.
9420      *
9421      * @hide
9422      */
includeForAccessibility()9423     public boolean includeForAccessibility() {
9424         if (mAttachInfo != null) {
9425             return (mAttachInfo.mAccessibilityFetchFlags
9426                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9427                     || isImportantForAccessibility();
9428         }
9429         return false;
9430     }
9431 
9432     /**
9433      * Returns whether the View is considered actionable from
9434      * accessibility perspective. Such view are important for
9435      * accessibility.
9436      *
9437      * @return True if the view is actionable for accessibility.
9438      *
9439      * @hide
9440      */
isActionableForAccessibility()9441     public boolean isActionableForAccessibility() {
9442         return (isClickable() || isLongClickable() || isFocusable());
9443     }
9444 
9445     /**
9446      * Returns whether the View has registered callbacks which makes it
9447      * important for accessibility.
9448      *
9449      * @return True if the view is actionable for accessibility.
9450      */
hasListenersForAccessibility()9451     private boolean hasListenersForAccessibility() {
9452         ListenerInfo info = getListenerInfo();
9453         return mTouchDelegate != null || info.mOnKeyListener != null
9454                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9455                 || info.mOnHoverListener != null || info.mOnDragListener != null;
9456     }
9457 
9458     /**
9459      * Notifies that the accessibility state of this view changed. The change
9460      * is local to this view and does not represent structural changes such
9461      * as children and parent. For example, the view became focusable. The
9462      * notification is at at most once every
9463      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9464      * to avoid unnecessary load to the system. Also once a view has a pending
9465      * notification this method is a NOP until the notification has been sent.
9466      *
9467      * @hide
9468      */
notifyViewAccessibilityStateChangedIfNeeded(int changeType)9469     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9470         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9471             return;
9472         }
9473         if (mSendViewStateChangedAccessibilityEvent == null) {
9474             mSendViewStateChangedAccessibilityEvent =
9475                     new SendViewStateChangedAccessibilityEvent();
9476         }
9477         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9478     }
9479 
9480     /**
9481      * Notifies that the accessibility state of this view changed. The change
9482      * is *not* local to this view and does represent structural changes such
9483      * as children and parent. For example, the view size changed. The
9484      * notification is at at most once every
9485      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9486      * to avoid unnecessary load to the system. Also once a view has a pending
9487      * notification this method is a NOP until the notification has been sent.
9488      *
9489      * @hide
9490      */
notifySubtreeAccessibilityStateChangedIfNeeded()9491     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9492         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9493             return;
9494         }
9495         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9496             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9497             if (mParent != null) {
9498                 try {
9499                     mParent.notifySubtreeAccessibilityStateChanged(
9500                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9501                 } catch (AbstractMethodError e) {
9502                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9503                             " does not fully implement ViewParent", e);
9504                 }
9505             }
9506         }
9507     }
9508 
9509     /**
9510      * Change the visibility of the View without triggering any other changes. This is
9511      * important for transitions, where visibility changes should not adjust focus or
9512      * trigger a new layout. This is only used when the visibility has already been changed
9513      * and we need a transient value during an animation. When the animation completes,
9514      * the original visibility value is always restored.
9515      *
9516      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9517      * @hide
9518      */
setTransitionVisibility(@isibility int visibility)9519     public void setTransitionVisibility(@Visibility int visibility) {
9520         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9521     }
9522 
9523     /**
9524      * Reset the flag indicating the accessibility state of the subtree rooted
9525      * at this view changed.
9526      */
resetSubtreeAccessibilityStateChanged()9527     void resetSubtreeAccessibilityStateChanged() {
9528         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9529     }
9530 
9531     /**
9532      * Report an accessibility action to this view's parents for delegated processing.
9533      *
9534      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9535      * call this method to delegate an accessibility action to a supporting parent. If the parent
9536      * returns true from its
9537      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9538      * method this method will return true to signify that the action was consumed.</p>
9539      *
9540      * <p>This method is useful for implementing nested scrolling child views. If
9541      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9542      * a custom view implementation may invoke this method to allow a parent to consume the
9543      * scroll first. If this method returns true the custom view should skip its own scrolling
9544      * behavior.</p>
9545      *
9546      * @param action Accessibility action to delegate
9547      * @param arguments Optional action arguments
9548      * @return true if the action was consumed by a parent
9549      */
dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments)9550     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9551         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9552             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9553                 return true;
9554             }
9555         }
9556         return false;
9557     }
9558 
9559     /**
9560      * Performs the specified accessibility action on the view. For
9561      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9562      * <p>
9563      * If an {@link AccessibilityDelegate} has been specified via calling
9564      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9565      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9566      * is responsible for handling this call.
9567      * </p>
9568      *
9569      * <p>The default implementation will delegate
9570      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9571      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9572      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9573      *
9574      * @param action The action to perform.
9575      * @param arguments Optional action arguments.
9576      * @return Whether the action was performed.
9577      */
performAccessibilityAction(int action, Bundle arguments)9578     public boolean performAccessibilityAction(int action, Bundle arguments) {
9579       if (mAccessibilityDelegate != null) {
9580           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9581       } else {
9582           return performAccessibilityActionInternal(action, arguments);
9583       }
9584     }
9585 
9586    /**
9587     * @see #performAccessibilityAction(int, Bundle)
9588     *
9589     * Note: Called from the default {@link AccessibilityDelegate}.
9590     *
9591     * @hide
9592     */
performAccessibilityActionInternal(int action, Bundle arguments)9593     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9594         if (isNestedScrollingEnabled()
9595                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9596                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9597                 || action == R.id.accessibilityActionScrollUp
9598                 || action == R.id.accessibilityActionScrollLeft
9599                 || action == R.id.accessibilityActionScrollDown
9600                 || action == R.id.accessibilityActionScrollRight)) {
9601             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9602                 return true;
9603             }
9604         }
9605 
9606         switch (action) {
9607             case AccessibilityNodeInfo.ACTION_CLICK: {
9608                 if (isClickable()) {
9609                     performClick();
9610                     return true;
9611                 }
9612             } break;
9613             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9614                 if (isLongClickable()) {
9615                     performLongClick();
9616                     return true;
9617                 }
9618             } break;
9619             case AccessibilityNodeInfo.ACTION_FOCUS: {
9620                 if (!hasFocus()) {
9621                     // Get out of touch mode since accessibility
9622                     // wants to move focus around.
9623                     getViewRootImpl().ensureTouchMode(false);
9624                     return requestFocus();
9625                 }
9626             } break;
9627             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9628                 if (hasFocus()) {
9629                     clearFocus();
9630                     return !isFocused();
9631                 }
9632             } break;
9633             case AccessibilityNodeInfo.ACTION_SELECT: {
9634                 if (!isSelected()) {
9635                     setSelected(true);
9636                     return isSelected();
9637                 }
9638             } break;
9639             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9640                 if (isSelected()) {
9641                     setSelected(false);
9642                     return !isSelected();
9643                 }
9644             } break;
9645             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9646                 if (!isAccessibilityFocused()) {
9647                     return requestAccessibilityFocus();
9648                 }
9649             } break;
9650             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9651                 if (isAccessibilityFocused()) {
9652                     clearAccessibilityFocus();
9653                     return true;
9654                 }
9655             } break;
9656             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9657                 if (arguments != null) {
9658                     final int granularity = arguments.getInt(
9659                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9660                     final boolean extendSelection = arguments.getBoolean(
9661                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9662                     return traverseAtGranularity(granularity, true, extendSelection);
9663                 }
9664             } break;
9665             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9666                 if (arguments != null) {
9667                     final int granularity = arguments.getInt(
9668                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9669                     final boolean extendSelection = arguments.getBoolean(
9670                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9671                     return traverseAtGranularity(granularity, false, extendSelection);
9672                 }
9673             } break;
9674             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9675                 CharSequence text = getIterableTextForAccessibility();
9676                 if (text == null) {
9677                     return false;
9678                 }
9679                 final int start = (arguments != null) ? arguments.getInt(
9680                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9681                 final int end = (arguments != null) ? arguments.getInt(
9682                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9683                 // Only cursor position can be specified (selection length == 0)
9684                 if ((getAccessibilitySelectionStart() != start
9685                         || getAccessibilitySelectionEnd() != end)
9686                         && (start == end)) {
9687                     setAccessibilitySelection(start, end);
9688                     notifyViewAccessibilityStateChangedIfNeeded(
9689                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9690                     return true;
9691                 }
9692             } break;
9693             case R.id.accessibilityActionShowOnScreen: {
9694                 if (mAttachInfo != null) {
9695                     final Rect r = mAttachInfo.mTmpInvalRect;
9696                     getDrawingRect(r);
9697                     return requestRectangleOnScreen(r, true);
9698                 }
9699             } break;
9700             case R.id.accessibilityActionContextClick: {
9701                 if (isContextClickable()) {
9702                     performContextClick();
9703                     return true;
9704                 }
9705             } break;
9706         }
9707         return false;
9708     }
9709 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)9710     private boolean traverseAtGranularity(int granularity, boolean forward,
9711             boolean extendSelection) {
9712         CharSequence text = getIterableTextForAccessibility();
9713         if (text == null || text.length() == 0) {
9714             return false;
9715         }
9716         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9717         if (iterator == null) {
9718             return false;
9719         }
9720         int current = getAccessibilitySelectionEnd();
9721         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9722             current = forward ? 0 : text.length();
9723         }
9724         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9725         if (range == null) {
9726             return false;
9727         }
9728         final int segmentStart = range[0];
9729         final int segmentEnd = range[1];
9730         int selectionStart;
9731         int selectionEnd;
9732         if (extendSelection && isAccessibilitySelectionExtendable()) {
9733             selectionStart = getAccessibilitySelectionStart();
9734             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9735                 selectionStart = forward ? segmentStart : segmentEnd;
9736             }
9737             selectionEnd = forward ? segmentEnd : segmentStart;
9738         } else {
9739             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9740         }
9741         setAccessibilitySelection(selectionStart, selectionEnd);
9742         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9743                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9744         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9745         return true;
9746     }
9747 
9748     /**
9749      * Gets the text reported for accessibility purposes.
9750      *
9751      * @return The accessibility text.
9752      *
9753      * @hide
9754      */
getIterableTextForAccessibility()9755     public CharSequence getIterableTextForAccessibility() {
9756         return getContentDescription();
9757     }
9758 
9759     /**
9760      * Gets whether accessibility selection can be extended.
9761      *
9762      * @return If selection is extensible.
9763      *
9764      * @hide
9765      */
isAccessibilitySelectionExtendable()9766     public boolean isAccessibilitySelectionExtendable() {
9767         return false;
9768     }
9769 
9770     /**
9771      * @hide
9772      */
getAccessibilitySelectionStart()9773     public int getAccessibilitySelectionStart() {
9774         return mAccessibilityCursorPosition;
9775     }
9776 
9777     /**
9778      * @hide
9779      */
getAccessibilitySelectionEnd()9780     public int getAccessibilitySelectionEnd() {
9781         return getAccessibilitySelectionStart();
9782     }
9783 
9784     /**
9785      * @hide
9786      */
setAccessibilitySelection(int start, int end)9787     public void setAccessibilitySelection(int start, int end) {
9788         if (start ==  end && end == mAccessibilityCursorPosition) {
9789             return;
9790         }
9791         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9792             mAccessibilityCursorPosition = start;
9793         } else {
9794             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9795         }
9796         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9797     }
9798 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)9799     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9800             int fromIndex, int toIndex) {
9801         if (mParent == null) {
9802             return;
9803         }
9804         AccessibilityEvent event = AccessibilityEvent.obtain(
9805                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9806         onInitializeAccessibilityEvent(event);
9807         onPopulateAccessibilityEvent(event);
9808         event.setFromIndex(fromIndex);
9809         event.setToIndex(toIndex);
9810         event.setAction(action);
9811         event.setMovementGranularity(granularity);
9812         mParent.requestSendAccessibilityEvent(this, event);
9813     }
9814 
9815     /**
9816      * @hide
9817      */
getIteratorForGranularity(int granularity)9818     public TextSegmentIterator getIteratorForGranularity(int granularity) {
9819         switch (granularity) {
9820             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9821                 CharSequence text = getIterableTextForAccessibility();
9822                 if (text != null && text.length() > 0) {
9823                     CharacterTextSegmentIterator iterator =
9824                         CharacterTextSegmentIterator.getInstance(
9825                                 mContext.getResources().getConfiguration().locale);
9826                     iterator.initialize(text.toString());
9827                     return iterator;
9828                 }
9829             } break;
9830             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9831                 CharSequence text = getIterableTextForAccessibility();
9832                 if (text != null && text.length() > 0) {
9833                     WordTextSegmentIterator iterator =
9834                         WordTextSegmentIterator.getInstance(
9835                                 mContext.getResources().getConfiguration().locale);
9836                     iterator.initialize(text.toString());
9837                     return iterator;
9838                 }
9839             } break;
9840             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9841                 CharSequence text = getIterableTextForAccessibility();
9842                 if (text != null && text.length() > 0) {
9843                     ParagraphTextSegmentIterator iterator =
9844                         ParagraphTextSegmentIterator.getInstance();
9845                     iterator.initialize(text.toString());
9846                     return iterator;
9847                 }
9848             } break;
9849         }
9850         return null;
9851     }
9852 
9853     /**
9854      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
9855      * and {@link #onFinishTemporaryDetach()}.
9856      *
9857      * <p>This method always returns {@code true} when called directly or indirectly from
9858      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
9859      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
9860      * <ul>
9861      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
9862      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
9863      * </ul>
9864      * </p>
9865      *
9866      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9867      * and {@link #onFinishTemporaryDetach()}.
9868      */
isTemporarilyDetached()9869     public final boolean isTemporarilyDetached() {
9870         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9871     }
9872 
9873     /**
9874      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9875      * a container View.
9876      */
9877     @CallSuper
dispatchStartTemporaryDetach()9878     public void dispatchStartTemporaryDetach() {
9879         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9880         onStartTemporaryDetach();
9881     }
9882 
9883     /**
9884      * This is called when a container is going to temporarily detach a child, with
9885      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9886      * It will either be followed by {@link #onFinishTemporaryDetach()} or
9887      * {@link #onDetachedFromWindow()} when the container is done.
9888      */
onStartTemporaryDetach()9889     public void onStartTemporaryDetach() {
9890         removeUnsetPressCallback();
9891         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9892     }
9893 
9894     /**
9895      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9896      * a container View.
9897      */
9898     @CallSuper
dispatchFinishTemporaryDetach()9899     public void dispatchFinishTemporaryDetach() {
9900         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9901         onFinishTemporaryDetach();
9902         if (hasWindowFocus() && hasFocus()) {
9903             InputMethodManager.getInstance().focusIn(this);
9904         }
9905     }
9906 
9907     /**
9908      * Called after {@link #onStartTemporaryDetach} when the container is done
9909      * changing the view.
9910      */
onFinishTemporaryDetach()9911     public void onFinishTemporaryDetach() {
9912     }
9913 
9914     /**
9915      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9916      * for this view's window.  Returns null if the view is not currently attached
9917      * to the window.  Normally you will not need to use this directly, but
9918      * just use the standard high-level event callbacks like
9919      * {@link #onKeyDown(int, KeyEvent)}.
9920      */
getKeyDispatcherState()9921     public KeyEvent.DispatcherState getKeyDispatcherState() {
9922         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9923     }
9924 
9925     /**
9926      * Dispatch a key event before it is processed by any input method
9927      * associated with the view hierarchy.  This can be used to intercept
9928      * key events in special situations before the IME consumes them; a
9929      * typical example would be handling the BACK key to update the application's
9930      * UI instead of allowing the IME to see it and close itself.
9931      *
9932      * @param event The key event to be dispatched.
9933      * @return True if the event was handled, false otherwise.
9934      */
dispatchKeyEventPreIme(KeyEvent event)9935     public boolean dispatchKeyEventPreIme(KeyEvent event) {
9936         return onKeyPreIme(event.getKeyCode(), event);
9937     }
9938 
9939     /**
9940      * Dispatch a key event to the next view on the focus path. This path runs
9941      * from the top of the view tree down to the currently focused view. If this
9942      * view has focus, it will dispatch to itself. Otherwise it will dispatch
9943      * the next node down the focus path. This method also fires any key
9944      * listeners.
9945      *
9946      * @param event The key event to be dispatched.
9947      * @return True if the event was handled, false otherwise.
9948      */
dispatchKeyEvent(KeyEvent event)9949     public boolean dispatchKeyEvent(KeyEvent event) {
9950         if (mInputEventConsistencyVerifier != null) {
9951             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9952         }
9953 
9954         // Give any attached key listener a first crack at the event.
9955         //noinspection SimplifiableIfStatement
9956         ListenerInfo li = mListenerInfo;
9957         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9958                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9959             return true;
9960         }
9961 
9962         if (event.dispatch(this, mAttachInfo != null
9963                 ? mAttachInfo.mKeyDispatchState : null, this)) {
9964             return true;
9965         }
9966 
9967         if (mInputEventConsistencyVerifier != null) {
9968             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9969         }
9970         return false;
9971     }
9972 
9973     /**
9974      * Dispatches a key shortcut event.
9975      *
9976      * @param event The key event to be dispatched.
9977      * @return True if the event was handled by the view, false otherwise.
9978      */
dispatchKeyShortcutEvent(KeyEvent event)9979     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9980         return onKeyShortcut(event.getKeyCode(), event);
9981     }
9982 
9983     /**
9984      * Pass the touch screen motion event down to the target view, or this
9985      * view if it is the target.
9986      *
9987      * @param event The motion event to be dispatched.
9988      * @return True if the event was handled by the view, false otherwise.
9989      */
dispatchTouchEvent(MotionEvent event)9990     public boolean dispatchTouchEvent(MotionEvent event) {
9991         // If the event should be handled by accessibility focus first.
9992         if (event.isTargetAccessibilityFocus()) {
9993             // We don't have focus or no virtual descendant has it, do not handle the event.
9994             if (!isAccessibilityFocusedViewOrHost()) {
9995                 return false;
9996             }
9997             // We have focus and got the event, then use normal event dispatch.
9998             event.setTargetAccessibilityFocus(false);
9999         }
10000 
10001         boolean result = false;
10002 
10003         if (mInputEventConsistencyVerifier != null) {
10004             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10005         }
10006 
10007         final int actionMasked = event.getActionMasked();
10008         if (actionMasked == MotionEvent.ACTION_DOWN) {
10009             // Defensive cleanup for new gesture
10010             stopNestedScroll();
10011         }
10012 
10013         if (onFilterTouchEventForSecurity(event)) {
10014             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10015                 result = true;
10016             }
10017             //noinspection SimplifiableIfStatement
10018             ListenerInfo li = mListenerInfo;
10019             if (li != null && li.mOnTouchListener != null
10020                     && (mViewFlags & ENABLED_MASK) == ENABLED
10021                     && li.mOnTouchListener.onTouch(this, event)) {
10022                 result = true;
10023             }
10024 
10025             if (!result && onTouchEvent(event)) {
10026                 result = true;
10027             }
10028         }
10029 
10030         if (!result && mInputEventConsistencyVerifier != null) {
10031             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10032         }
10033 
10034         // Clean up after nested scrolls if this is the end of a gesture;
10035         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10036         // of the gesture.
10037         if (actionMasked == MotionEvent.ACTION_UP ||
10038                 actionMasked == MotionEvent.ACTION_CANCEL ||
10039                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10040             stopNestedScroll();
10041         }
10042 
10043         return result;
10044     }
10045 
isAccessibilityFocusedViewOrHost()10046     boolean isAccessibilityFocusedViewOrHost() {
10047         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10048                 .getAccessibilityFocusedHost() == this);
10049     }
10050 
10051     /**
10052      * Filter the touch event to apply security policies.
10053      *
10054      * @param event The motion event to be filtered.
10055      * @return True if the event should be dispatched, false if the event should be dropped.
10056      *
10057      * @see #getFilterTouchesWhenObscured
10058      */
onFilterTouchEventForSecurity(MotionEvent event)10059     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10060         //noinspection RedundantIfStatement
10061         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10062                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10063             // Window is obscured, drop this touch.
10064             return false;
10065         }
10066         return true;
10067     }
10068 
10069     /**
10070      * Pass a trackball motion event down to the focused view.
10071      *
10072      * @param event The motion event to be dispatched.
10073      * @return True if the event was handled by the view, false otherwise.
10074      */
dispatchTrackballEvent(MotionEvent event)10075     public boolean dispatchTrackballEvent(MotionEvent event) {
10076         if (mInputEventConsistencyVerifier != null) {
10077             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10078         }
10079 
10080         return onTrackballEvent(event);
10081     }
10082 
10083     /**
10084      * Dispatch a generic motion event.
10085      * <p>
10086      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10087      * are delivered to the view under the pointer.  All other generic motion events are
10088      * delivered to the focused view.  Hover events are handled specially and are delivered
10089      * to {@link #onHoverEvent(MotionEvent)}.
10090      * </p>
10091      *
10092      * @param event The motion event to be dispatched.
10093      * @return True if the event was handled by the view, false otherwise.
10094      */
dispatchGenericMotionEvent(MotionEvent event)10095     public boolean dispatchGenericMotionEvent(MotionEvent event) {
10096         if (mInputEventConsistencyVerifier != null) {
10097             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10098         }
10099 
10100         final int source = event.getSource();
10101         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10102             final int action = event.getAction();
10103             if (action == MotionEvent.ACTION_HOVER_ENTER
10104                     || action == MotionEvent.ACTION_HOVER_MOVE
10105                     || action == MotionEvent.ACTION_HOVER_EXIT) {
10106                 if (dispatchHoverEvent(event)) {
10107                     return true;
10108                 }
10109             } else if (dispatchGenericPointerEvent(event)) {
10110                 return true;
10111             }
10112         } else if (dispatchGenericFocusedEvent(event)) {
10113             return true;
10114         }
10115 
10116         if (dispatchGenericMotionEventInternal(event)) {
10117             return true;
10118         }
10119 
10120         if (mInputEventConsistencyVerifier != null) {
10121             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10122         }
10123         return false;
10124     }
10125 
dispatchGenericMotionEventInternal(MotionEvent event)10126     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10127         //noinspection SimplifiableIfStatement
10128         ListenerInfo li = mListenerInfo;
10129         if (li != null && li.mOnGenericMotionListener != null
10130                 && (mViewFlags & ENABLED_MASK) == ENABLED
10131                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10132             return true;
10133         }
10134 
10135         if (onGenericMotionEvent(event)) {
10136             return true;
10137         }
10138 
10139         final int actionButton = event.getActionButton();
10140         switch (event.getActionMasked()) {
10141             case MotionEvent.ACTION_BUTTON_PRESS:
10142                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10143                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10144                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10145                     if (performContextClick(event.getX(), event.getY())) {
10146                         mInContextButtonPress = true;
10147                         setPressed(true, event.getX(), event.getY());
10148                         removeTapCallback();
10149                         removeLongPressCallback();
10150                         return true;
10151                     }
10152                 }
10153                 break;
10154 
10155             case MotionEvent.ACTION_BUTTON_RELEASE:
10156                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10157                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10158                     mInContextButtonPress = false;
10159                     mIgnoreNextUpEvent = true;
10160                 }
10161                 break;
10162         }
10163 
10164         if (mInputEventConsistencyVerifier != null) {
10165             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10166         }
10167         return false;
10168     }
10169 
10170     /**
10171      * Dispatch a hover event.
10172      * <p>
10173      * Do not call this method directly.
10174      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10175      * </p>
10176      *
10177      * @param event The motion event to be dispatched.
10178      * @return True if the event was handled by the view, false otherwise.
10179      */
dispatchHoverEvent(MotionEvent event)10180     protected boolean dispatchHoverEvent(MotionEvent event) {
10181         ListenerInfo li = mListenerInfo;
10182         //noinspection SimplifiableIfStatement
10183         if (li != null && li.mOnHoverListener != null
10184                 && (mViewFlags & ENABLED_MASK) == ENABLED
10185                 && li.mOnHoverListener.onHover(this, event)) {
10186             return true;
10187         }
10188 
10189         return onHoverEvent(event);
10190     }
10191 
10192     /**
10193      * Returns true if the view has a child to which it has recently sent
10194      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10195      * it does not have a hovered child, then it must be the innermost hovered view.
10196      * @hide
10197      */
hasHoveredChild()10198     protected boolean hasHoveredChild() {
10199         return false;
10200     }
10201 
10202     /**
10203      * Dispatch a generic motion event to the view under the first pointer.
10204      * <p>
10205      * Do not call this method directly.
10206      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10207      * </p>
10208      *
10209      * @param event The motion event to be dispatched.
10210      * @return True if the event was handled by the view, false otherwise.
10211      */
dispatchGenericPointerEvent(MotionEvent event)10212     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10213         return false;
10214     }
10215 
10216     /**
10217      * Dispatch a generic motion event to the currently focused view.
10218      * <p>
10219      * Do not call this method directly.
10220      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10221      * </p>
10222      *
10223      * @param event The motion event to be dispatched.
10224      * @return True if the event was handled by the view, false otherwise.
10225      */
dispatchGenericFocusedEvent(MotionEvent event)10226     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10227         return false;
10228     }
10229 
10230     /**
10231      * Dispatch a pointer event.
10232      * <p>
10233      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10234      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10235      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10236      * and should not be expected to handle other pointing device features.
10237      * </p>
10238      *
10239      * @param event The motion event to be dispatched.
10240      * @return True if the event was handled by the view, false otherwise.
10241      * @hide
10242      */
dispatchPointerEvent(MotionEvent event)10243     public final boolean dispatchPointerEvent(MotionEvent event) {
10244         if (event.isTouchEvent()) {
10245             return dispatchTouchEvent(event);
10246         } else {
10247             return dispatchGenericMotionEvent(event);
10248         }
10249     }
10250 
10251     /**
10252      * Called when the window containing this view gains or loses window focus.
10253      * ViewGroups should override to route to their children.
10254      *
10255      * @param hasFocus True if the window containing this view now has focus,
10256      *        false otherwise.
10257      */
dispatchWindowFocusChanged(boolean hasFocus)10258     public void dispatchWindowFocusChanged(boolean hasFocus) {
10259         onWindowFocusChanged(hasFocus);
10260     }
10261 
10262     /**
10263      * Called when the window containing this view gains or loses focus.  Note
10264      * that this is separate from view focus: to receive key events, both
10265      * your view and its window must have focus.  If a window is displayed
10266      * on top of yours that takes input focus, then your own window will lose
10267      * focus but the view focus will remain unchanged.
10268      *
10269      * @param hasWindowFocus True if the window containing this view now has
10270      *        focus, false otherwise.
10271      */
onWindowFocusChanged(boolean hasWindowFocus)10272     public void onWindowFocusChanged(boolean hasWindowFocus) {
10273         InputMethodManager imm = InputMethodManager.peekInstance();
10274         if (!hasWindowFocus) {
10275             if (isPressed()) {
10276                 setPressed(false);
10277             }
10278             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10279                 imm.focusOut(this);
10280             }
10281             removeLongPressCallback();
10282             removeTapCallback();
10283             onFocusLost();
10284         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10285             imm.focusIn(this);
10286         }
10287         refreshDrawableState();
10288     }
10289 
10290     /**
10291      * Returns true if this view is in a window that currently has window focus.
10292      * Note that this is not the same as the view itself having focus.
10293      *
10294      * @return True if this view is in a window that currently has window focus.
10295      */
hasWindowFocus()10296     public boolean hasWindowFocus() {
10297         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10298     }
10299 
10300     /**
10301      * Dispatch a view visibility change down the view hierarchy.
10302      * ViewGroups should override to route to their children.
10303      * @param changedView The view whose visibility changed. Could be 'this' or
10304      * an ancestor view.
10305      * @param visibility The new visibility of changedView: {@link #VISIBLE},
10306      * {@link #INVISIBLE} or {@link #GONE}.
10307      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)10308     protected void dispatchVisibilityChanged(@NonNull View changedView,
10309             @Visibility int visibility) {
10310         onVisibilityChanged(changedView, visibility);
10311     }
10312 
10313     /**
10314      * Called when the visibility of the view or an ancestor of the view has
10315      * changed.
10316      *
10317      * @param changedView The view whose visibility changed. May be
10318      *                    {@code this} or an ancestor view.
10319      * @param visibility The new visibility, one of {@link #VISIBLE},
10320      *                   {@link #INVISIBLE} or {@link #GONE}.
10321      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)10322     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10323     }
10324 
10325     /**
10326      * Dispatch a hint about whether this view is displayed. For instance, when
10327      * a View moves out of the screen, it might receives a display hint indicating
10328      * the view is not displayed. Applications should not <em>rely</em> on this hint
10329      * as there is no guarantee that they will receive one.
10330      *
10331      * @param hint A hint about whether or not this view is displayed:
10332      * {@link #VISIBLE} or {@link #INVISIBLE}.
10333      */
dispatchDisplayHint(@isibility int hint)10334     public void dispatchDisplayHint(@Visibility int hint) {
10335         onDisplayHint(hint);
10336     }
10337 
10338     /**
10339      * Gives this view a hint about whether is displayed or not. For instance, when
10340      * a View moves out of the screen, it might receives a display hint indicating
10341      * the view is not displayed. Applications should not <em>rely</em> on this hint
10342      * as there is no guarantee that they will receive one.
10343      *
10344      * @param hint A hint about whether or not this view is displayed:
10345      * {@link #VISIBLE} or {@link #INVISIBLE}.
10346      */
onDisplayHint(@isibility int hint)10347     protected void onDisplayHint(@Visibility int hint) {
10348     }
10349 
10350     /**
10351      * Dispatch a window visibility change down the view hierarchy.
10352      * ViewGroups should override to route to their children.
10353      *
10354      * @param visibility The new visibility of the window.
10355      *
10356      * @see #onWindowVisibilityChanged(int)
10357      */
dispatchWindowVisibilityChanged(@isibility int visibility)10358     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10359         onWindowVisibilityChanged(visibility);
10360     }
10361 
10362     /**
10363      * Called when the window containing has change its visibility
10364      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10365      * that this tells you whether or not your window is being made visible
10366      * to the window manager; this does <em>not</em> tell you whether or not
10367      * your window is obscured by other windows on the screen, even if it
10368      * is itself visible.
10369      *
10370      * @param visibility The new visibility of the window.
10371      */
onWindowVisibilityChanged(@isibility int visibility)10372     protected void onWindowVisibilityChanged(@Visibility int visibility) {
10373         if (visibility == VISIBLE) {
10374             initialAwakenScrollBars();
10375         }
10376     }
10377 
10378     /**
10379      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10380      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10381      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10382      *
10383      * @param isVisible true if this view's visibility to the user is uninterrupted by its
10384      *                  ancestors or by window visibility
10385      * @return true if this view is visible to the user, not counting clipping or overlapping
10386      */
dispatchVisibilityAggregated(boolean isVisible)10387     boolean dispatchVisibilityAggregated(boolean isVisible) {
10388         final boolean thisVisible = getVisibility() == VISIBLE;
10389         // If we're not visible but something is telling us we are, ignore it.
10390         if (thisVisible || !isVisible) {
10391             onVisibilityAggregated(isVisible);
10392         }
10393         return thisVisible && isVisible;
10394     }
10395 
10396     /**
10397      * Called when the user-visibility of this View is potentially affected by a change
10398      * to this view itself, an ancestor view or the window this view is attached to.
10399      *
10400      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10401      *                  and this view's window is also visible
10402      */
10403     @CallSuper
onVisibilityAggregated(boolean isVisible)10404     public void onVisibilityAggregated(boolean isVisible) {
10405         if (isVisible && mAttachInfo != null) {
10406             initialAwakenScrollBars();
10407         }
10408 
10409         final Drawable dr = mBackground;
10410         if (dr != null && isVisible != dr.isVisible()) {
10411             dr.setVisible(isVisible, false);
10412         }
10413         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10414         if (fg != null && isVisible != fg.isVisible()) {
10415             fg.setVisible(isVisible, false);
10416         }
10417     }
10418 
10419     /**
10420      * Returns the current visibility of the window this view is attached to
10421      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10422      *
10423      * @return Returns the current visibility of the view's window.
10424      */
10425     @Visibility
getWindowVisibility()10426     public int getWindowVisibility() {
10427         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10428     }
10429 
10430     /**
10431      * Retrieve the overall visible display size in which the window this view is
10432      * attached to has been positioned in.  This takes into account screen
10433      * decorations above the window, for both cases where the window itself
10434      * is being position inside of them or the window is being placed under
10435      * then and covered insets are used for the window to position its content
10436      * inside.  In effect, this tells you the available area where content can
10437      * be placed and remain visible to users.
10438      *
10439      * <p>This function requires an IPC back to the window manager to retrieve
10440      * the requested information, so should not be used in performance critical
10441      * code like drawing.
10442      *
10443      * @param outRect Filled in with the visible display frame.  If the view
10444      * is not attached to a window, this is simply the raw display size.
10445      */
getWindowVisibleDisplayFrame(Rect outRect)10446     public void getWindowVisibleDisplayFrame(Rect outRect) {
10447         if (mAttachInfo != null) {
10448             try {
10449                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10450             } catch (RemoteException e) {
10451                 return;
10452             }
10453             // XXX This is really broken, and probably all needs to be done
10454             // in the window manager, and we need to know more about whether
10455             // we want the area behind or in front of the IME.
10456             final Rect insets = mAttachInfo.mVisibleInsets;
10457             outRect.left += insets.left;
10458             outRect.top += insets.top;
10459             outRect.right -= insets.right;
10460             outRect.bottom -= insets.bottom;
10461             return;
10462         }
10463         // The view is not attached to a display so we don't have a context.
10464         // Make a best guess about the display size.
10465         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10466         d.getRectSize(outRect);
10467     }
10468 
10469     /**
10470      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10471      * is currently in without any insets.
10472      *
10473      * @hide
10474      */
getWindowDisplayFrame(Rect outRect)10475     public void getWindowDisplayFrame(Rect outRect) {
10476         if (mAttachInfo != null) {
10477             try {
10478                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10479             } catch (RemoteException e) {
10480                 return;
10481             }
10482             return;
10483         }
10484         // The view is not attached to a display so we don't have a context.
10485         // Make a best guess about the display size.
10486         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10487         d.getRectSize(outRect);
10488     }
10489 
10490     /**
10491      * Dispatch a notification about a resource configuration change down
10492      * the view hierarchy.
10493      * ViewGroups should override to route to their children.
10494      *
10495      * @param newConfig The new resource configuration.
10496      *
10497      * @see #onConfigurationChanged(android.content.res.Configuration)
10498      */
dispatchConfigurationChanged(Configuration newConfig)10499     public void dispatchConfigurationChanged(Configuration newConfig) {
10500         onConfigurationChanged(newConfig);
10501     }
10502 
10503     /**
10504      * Called when the current configuration of the resources being used
10505      * by the application have changed.  You can use this to decide when
10506      * to reload resources that can changed based on orientation and other
10507      * configuration characteristics.  You only need to use this if you are
10508      * not relying on the normal {@link android.app.Activity} mechanism of
10509      * recreating the activity instance upon a configuration change.
10510      *
10511      * @param newConfig The new resource configuration.
10512      */
onConfigurationChanged(Configuration newConfig)10513     protected void onConfigurationChanged(Configuration newConfig) {
10514     }
10515 
10516     /**
10517      * Private function to aggregate all per-view attributes in to the view
10518      * root.
10519      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)10520     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10521         performCollectViewAttributes(attachInfo, visibility);
10522     }
10523 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)10524     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10525         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10526             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10527                 attachInfo.mKeepScreenOn = true;
10528             }
10529             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10530             ListenerInfo li = mListenerInfo;
10531             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10532                 attachInfo.mHasSystemUiListeners = true;
10533             }
10534         }
10535     }
10536 
needGlobalAttributesUpdate(boolean force)10537     void needGlobalAttributesUpdate(boolean force) {
10538         final AttachInfo ai = mAttachInfo;
10539         if (ai != null && !ai.mRecomputeGlobalAttributes) {
10540             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10541                     || ai.mHasSystemUiListeners) {
10542                 ai.mRecomputeGlobalAttributes = true;
10543             }
10544         }
10545     }
10546 
10547     /**
10548      * Returns whether the device is currently in touch mode.  Touch mode is entered
10549      * once the user begins interacting with the device by touch, and affects various
10550      * things like whether focus is always visible to the user.
10551      *
10552      * @return Whether the device is in touch mode.
10553      */
10554     @ViewDebug.ExportedProperty
isInTouchMode()10555     public boolean isInTouchMode() {
10556         if (mAttachInfo != null) {
10557             return mAttachInfo.mInTouchMode;
10558         } else {
10559             return ViewRootImpl.isInTouchMode();
10560         }
10561     }
10562 
10563     /**
10564      * Returns the context the view is running in, through which it can
10565      * access the current theme, resources, etc.
10566      *
10567      * @return The view's Context.
10568      */
10569     @ViewDebug.CapturedViewProperty
getContext()10570     public final Context getContext() {
10571         return mContext;
10572     }
10573 
10574     /**
10575      * Handle a key event before it is processed by any input method
10576      * associated with the view hierarchy.  This can be used to intercept
10577      * key events in special situations before the IME consumes them; a
10578      * typical example would be handling the BACK key to update the application's
10579      * UI instead of allowing the IME to see it and close itself.
10580      *
10581      * @param keyCode The value in event.getKeyCode().
10582      * @param event Description of the key event.
10583      * @return If you handled the event, return true. If you want to allow the
10584      *         event to be handled by the next receiver, return false.
10585      */
onKeyPreIme(int keyCode, KeyEvent event)10586     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10587         return false;
10588     }
10589 
10590     /**
10591      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10592      * KeyEvent.Callback.onKeyDown()}: perform press of the view
10593      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10594      * is released, if the view is enabled and clickable.
10595      * <p>
10596      * Key presses in software keyboards will generally NOT trigger this
10597      * listener, although some may elect to do so in some situations. Do not
10598      * rely on this to catch software key presses.
10599      *
10600      * @param keyCode a key code that represents the button pressed, from
10601      *                {@link android.view.KeyEvent}
10602      * @param event the KeyEvent object that defines the button action
10603      */
onKeyDown(int keyCode, KeyEvent event)10604     public boolean onKeyDown(int keyCode, KeyEvent event) {
10605         if (KeyEvent.isConfirmKey(keyCode)) {
10606             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10607                 return true;
10608             }
10609 
10610             // Long clickable items don't necessarily have to be clickable.
10611             if (((mViewFlags & CLICKABLE) == CLICKABLE
10612                     || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10613                     && (event.getRepeatCount() == 0)) {
10614                 // For the purposes of menu anchoring and drawable hotspots,
10615                 // key events are considered to be at the center of the view.
10616                 final float x = getWidth() / 2f;
10617                 final float y = getHeight() / 2f;
10618                 setPressed(true, x, y);
10619                 checkForLongClick(0, x, y);
10620                 return true;
10621             }
10622         }
10623 
10624         return false;
10625     }
10626 
10627     /**
10628      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10629      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10630      * the event).
10631      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10632      * although some may elect to do so in some situations. Do not rely on this to
10633      * catch software key presses.
10634      */
onKeyLongPress(int keyCode, KeyEvent event)10635     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10636         return false;
10637     }
10638 
10639     /**
10640      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10641      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10642      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10643      * or {@link KeyEvent#KEYCODE_SPACE} is released.
10644      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10645      * although some may elect to do so in some situations. Do not rely on this to
10646      * catch software key presses.
10647      *
10648      * @param keyCode A key code that represents the button pressed, from
10649      *                {@link android.view.KeyEvent}.
10650      * @param event   The KeyEvent object that defines the button action.
10651      */
onKeyUp(int keyCode, KeyEvent event)10652     public boolean onKeyUp(int keyCode, KeyEvent event) {
10653         if (KeyEvent.isConfirmKey(keyCode)) {
10654             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10655                 return true;
10656             }
10657             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10658                 setPressed(false);
10659 
10660                 if (!mHasPerformedLongPress) {
10661                     // This is a tap, so remove the longpress check
10662                     removeLongPressCallback();
10663                     return performClick();
10664                 }
10665             }
10666         }
10667         return false;
10668     }
10669 
10670     /**
10671      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10672      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10673      * the event).
10674      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10675      * although some may elect to do so in some situations. Do not rely on this to
10676      * catch software key presses.
10677      *
10678      * @param keyCode     A key code that represents the button pressed, from
10679      *                    {@link android.view.KeyEvent}.
10680      * @param repeatCount The number of times the action was made.
10681      * @param event       The KeyEvent object that defines the button action.
10682      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)10683     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10684         return false;
10685     }
10686 
10687     /**
10688      * Called on the focused view when a key shortcut event is not handled.
10689      * Override this method to implement local key shortcuts for the View.
10690      * Key shortcuts can also be implemented by setting the
10691      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10692      *
10693      * @param keyCode The value in event.getKeyCode().
10694      * @param event Description of the key event.
10695      * @return If you handled the event, return true. If you want to allow the
10696      *         event to be handled by the next receiver, return false.
10697      */
onKeyShortcut(int keyCode, KeyEvent event)10698     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10699         return false;
10700     }
10701 
10702     /**
10703      * Check whether the called view is a text editor, in which case it
10704      * would make sense to automatically display a soft input window for
10705      * it.  Subclasses should override this if they implement
10706      * {@link #onCreateInputConnection(EditorInfo)} to return true if
10707      * a call on that method would return a non-null InputConnection, and
10708      * they are really a first-class editor that the user would normally
10709      * start typing on when the go into a window containing your view.
10710      *
10711      * <p>The default implementation always returns false.  This does
10712      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10713      * will not be called or the user can not otherwise perform edits on your
10714      * view; it is just a hint to the system that this is not the primary
10715      * purpose of this view.
10716      *
10717      * @return Returns true if this view is a text editor, else false.
10718      */
onCheckIsTextEditor()10719     public boolean onCheckIsTextEditor() {
10720         return false;
10721     }
10722 
10723     /**
10724      * Create a new InputConnection for an InputMethod to interact
10725      * with the view.  The default implementation returns null, since it doesn't
10726      * support input methods.  You can override this to implement such support.
10727      * This is only needed for views that take focus and text input.
10728      *
10729      * <p>When implementing this, you probably also want to implement
10730      * {@link #onCheckIsTextEditor()} to indicate you will return a
10731      * non-null InputConnection.</p>
10732      *
10733      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10734      * object correctly and in its entirety, so that the connected IME can rely
10735      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10736      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10737      * must be filled in with the correct cursor position for IMEs to work correctly
10738      * with your application.</p>
10739      *
10740      * @param outAttrs Fill in with attribute information about the connection.
10741      */
onCreateInputConnection(EditorInfo outAttrs)10742     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10743         return null;
10744     }
10745 
10746     /**
10747      * Called by the {@link android.view.inputmethod.InputMethodManager}
10748      * when a view who is not the current
10749      * input connection target is trying to make a call on the manager.  The
10750      * default implementation returns false; you can override this to return
10751      * true for certain views if you are performing InputConnection proxying
10752      * to them.
10753      * @param view The View that is making the InputMethodManager call.
10754      * @return Return true to allow the call, false to reject.
10755      */
checkInputConnectionProxy(View view)10756     public boolean checkInputConnectionProxy(View view) {
10757         return false;
10758     }
10759 
10760     /**
10761      * Show the context menu for this view. It is not safe to hold on to the
10762      * menu after returning from this method.
10763      *
10764      * You should normally not overload this method. Overload
10765      * {@link #onCreateContextMenu(ContextMenu)} or define an
10766      * {@link OnCreateContextMenuListener} to add items to the context menu.
10767      *
10768      * @param menu The context menu to populate
10769      */
createContextMenu(ContextMenu menu)10770     public void createContextMenu(ContextMenu menu) {
10771         ContextMenuInfo menuInfo = getContextMenuInfo();
10772 
10773         // Sets the current menu info so all items added to menu will have
10774         // my extra info set.
10775         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10776 
10777         onCreateContextMenu(menu);
10778         ListenerInfo li = mListenerInfo;
10779         if (li != null && li.mOnCreateContextMenuListener != null) {
10780             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10781         }
10782 
10783         // Clear the extra information so subsequent items that aren't mine don't
10784         // have my extra info.
10785         ((MenuBuilder)menu).setCurrentMenuInfo(null);
10786 
10787         if (mParent != null) {
10788             mParent.createContextMenu(menu);
10789         }
10790     }
10791 
10792     /**
10793      * Views should implement this if they have extra information to associate
10794      * with the context menu. The return result is supplied as a parameter to
10795      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10796      * callback.
10797      *
10798      * @return Extra information about the item for which the context menu
10799      *         should be shown. This information will vary across different
10800      *         subclasses of View.
10801      */
getContextMenuInfo()10802     protected ContextMenuInfo getContextMenuInfo() {
10803         return null;
10804     }
10805 
10806     /**
10807      * Views should implement this if the view itself is going to add items to
10808      * the context menu.
10809      *
10810      * @param menu the context menu to populate
10811      */
onCreateContextMenu(ContextMenu menu)10812     protected void onCreateContextMenu(ContextMenu menu) {
10813     }
10814 
10815     /**
10816      * Implement this method to handle trackball motion events.  The
10817      * <em>relative</em> movement of the trackball since the last event
10818      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10819      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10820      * that a movement of 1 corresponds to the user pressing one DPAD key (so
10821      * they will often be fractional values, representing the more fine-grained
10822      * movement information available from a trackball).
10823      *
10824      * @param event The motion event.
10825      * @return True if the event was handled, false otherwise.
10826      */
onTrackballEvent(MotionEvent event)10827     public boolean onTrackballEvent(MotionEvent event) {
10828         return false;
10829     }
10830 
10831     /**
10832      * Implement this method to handle generic motion events.
10833      * <p>
10834      * Generic motion events describe joystick movements, mouse hovers, track pad
10835      * touches, scroll wheel movements and other input events.  The
10836      * {@link MotionEvent#getSource() source} of the motion event specifies
10837      * the class of input that was received.  Implementations of this method
10838      * must examine the bits in the source before processing the event.
10839      * The following code example shows how this is done.
10840      * </p><p>
10841      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10842      * are delivered to the view under the pointer.  All other generic motion events are
10843      * delivered to the focused view.
10844      * </p>
10845      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10846      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10847      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10848      *             // process the joystick movement...
10849      *             return true;
10850      *         }
10851      *     }
10852      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10853      *         switch (event.getAction()) {
10854      *             case MotionEvent.ACTION_HOVER_MOVE:
10855      *                 // process the mouse hover movement...
10856      *                 return true;
10857      *             case MotionEvent.ACTION_SCROLL:
10858      *                 // process the scroll wheel movement...
10859      *                 return true;
10860      *         }
10861      *     }
10862      *     return super.onGenericMotionEvent(event);
10863      * }</pre>
10864      *
10865      * @param event The generic motion event being processed.
10866      * @return True if the event was handled, false otherwise.
10867      */
onGenericMotionEvent(MotionEvent event)10868     public boolean onGenericMotionEvent(MotionEvent event) {
10869         return false;
10870     }
10871 
10872     /**
10873      * Implement this method to handle hover events.
10874      * <p>
10875      * This method is called whenever a pointer is hovering into, over, or out of the
10876      * bounds of a view and the view is not currently being touched.
10877      * Hover events are represented as pointer events with action
10878      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10879      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10880      * </p>
10881      * <ul>
10882      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10883      * when the pointer enters the bounds of the view.</li>
10884      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10885      * when the pointer has already entered the bounds of the view and has moved.</li>
10886      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10887      * when the pointer has exited the bounds of the view or when the pointer is
10888      * about to go down due to a button click, tap, or similar user action that
10889      * causes the view to be touched.</li>
10890      * </ul>
10891      * <p>
10892      * The view should implement this method to return true to indicate that it is
10893      * handling the hover event, such as by changing its drawable state.
10894      * </p><p>
10895      * The default implementation calls {@link #setHovered} to update the hovered state
10896      * of the view when a hover enter or hover exit event is received, if the view
10897      * is enabled and is clickable.  The default implementation also sends hover
10898      * accessibility events.
10899      * </p>
10900      *
10901      * @param event The motion event that describes the hover.
10902      * @return True if the view handled the hover event.
10903      *
10904      * @see #isHovered
10905      * @see #setHovered
10906      * @see #onHoverChanged
10907      */
onHoverEvent(MotionEvent event)10908     public boolean onHoverEvent(MotionEvent event) {
10909         // The root view may receive hover (or touch) events that are outside the bounds of
10910         // the window.  This code ensures that we only send accessibility events for
10911         // hovers that are actually within the bounds of the root view.
10912         final int action = event.getActionMasked();
10913         if (!mSendingHoverAccessibilityEvents) {
10914             if ((action == MotionEvent.ACTION_HOVER_ENTER
10915                     || action == MotionEvent.ACTION_HOVER_MOVE)
10916                     && !hasHoveredChild()
10917                     && pointInView(event.getX(), event.getY())) {
10918                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10919                 mSendingHoverAccessibilityEvents = true;
10920             }
10921         } else {
10922             if (action == MotionEvent.ACTION_HOVER_EXIT
10923                     || (action == MotionEvent.ACTION_MOVE
10924                             && !pointInView(event.getX(), event.getY()))) {
10925                 mSendingHoverAccessibilityEvents = false;
10926                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10927             }
10928         }
10929 
10930         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10931                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
10932                 && isOnScrollbar(event.getX(), event.getY())) {
10933             awakenScrollBars();
10934         }
10935         if (isHoverable()) {
10936             switch (action) {
10937                 case MotionEvent.ACTION_HOVER_ENTER:
10938                     setHovered(true);
10939                     break;
10940                 case MotionEvent.ACTION_HOVER_EXIT:
10941                     setHovered(false);
10942                     break;
10943             }
10944 
10945             // Dispatch the event to onGenericMotionEvent before returning true.
10946             // This is to provide compatibility with existing applications that
10947             // handled HOVER_MOVE events in onGenericMotionEvent and that would
10948             // break because of the new default handling for hoverable views
10949             // in onHoverEvent.
10950             // Note that onGenericMotionEvent will be called by default when
10951             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10952             dispatchGenericMotionEventInternal(event);
10953             // The event was already handled by calling setHovered(), so always
10954             // return true.
10955             return true;
10956         }
10957 
10958         return false;
10959     }
10960 
10961     /**
10962      * Returns true if the view should handle {@link #onHoverEvent}
10963      * by calling {@link #setHovered} to change its hovered state.
10964      *
10965      * @return True if the view is hoverable.
10966      */
isHoverable()10967     private boolean isHoverable() {
10968         final int viewFlags = mViewFlags;
10969         if ((viewFlags & ENABLED_MASK) == DISABLED) {
10970             return false;
10971         }
10972 
10973         return (viewFlags & CLICKABLE) == CLICKABLE
10974                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10975                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10976     }
10977 
10978     /**
10979      * Returns true if the view is currently hovered.
10980      *
10981      * @return True if the view is currently hovered.
10982      *
10983      * @see #setHovered
10984      * @see #onHoverChanged
10985      */
10986     @ViewDebug.ExportedProperty
isHovered()10987     public boolean isHovered() {
10988         return (mPrivateFlags & PFLAG_HOVERED) != 0;
10989     }
10990 
10991     /**
10992      * Sets whether the view is currently hovered.
10993      * <p>
10994      * Calling this method also changes the drawable state of the view.  This
10995      * enables the view to react to hover by using different drawable resources
10996      * to change its appearance.
10997      * </p><p>
10998      * The {@link #onHoverChanged} method is called when the hovered state changes.
10999      * </p>
11000      *
11001      * @param hovered True if the view is hovered.
11002      *
11003      * @see #isHovered
11004      * @see #onHoverChanged
11005      */
setHovered(boolean hovered)11006     public void setHovered(boolean hovered) {
11007         if (hovered) {
11008             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11009                 mPrivateFlags |= PFLAG_HOVERED;
11010                 refreshDrawableState();
11011                 onHoverChanged(true);
11012             }
11013         } else {
11014             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11015                 mPrivateFlags &= ~PFLAG_HOVERED;
11016                 refreshDrawableState();
11017                 onHoverChanged(false);
11018             }
11019         }
11020     }
11021 
11022     /**
11023      * Implement this method to handle hover state changes.
11024      * <p>
11025      * This method is called whenever the hover state changes as a result of a
11026      * call to {@link #setHovered}.
11027      * </p>
11028      *
11029      * @param hovered The current hover state, as returned by {@link #isHovered}.
11030      *
11031      * @see #isHovered
11032      * @see #setHovered
11033      */
onHoverChanged(boolean hovered)11034     public void onHoverChanged(boolean hovered) {
11035     }
11036 
11037     /**
11038      * Handles scroll bar dragging by mouse input.
11039      *
11040      * @hide
11041      * @param event The motion event.
11042      *
11043      * @return true if the event was handled as a scroll bar dragging, false otherwise.
11044      */
handleScrollBarDragging(MotionEvent event)11045     protected boolean handleScrollBarDragging(MotionEvent event) {
11046         if (mScrollCache == null) {
11047             return false;
11048         }
11049         final float x = event.getX();
11050         final float y = event.getY();
11051         final int action = event.getAction();
11052         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11053                 && action != MotionEvent.ACTION_DOWN)
11054                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11055                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11056             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11057             return false;
11058         }
11059 
11060         switch (action) {
11061             case MotionEvent.ACTION_MOVE:
11062                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11063                     return false;
11064                 }
11065                 if (mScrollCache.mScrollBarDraggingState
11066                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11067                     final Rect bounds = mScrollCache.mScrollBarBounds;
11068                     getVerticalScrollBarBounds(bounds);
11069                     final int range = computeVerticalScrollRange();
11070                     final int offset = computeVerticalScrollOffset();
11071                     final int extent = computeVerticalScrollExtent();
11072 
11073                     final int thumbLength = ScrollBarUtils.getThumbLength(
11074                             bounds.height(), bounds.width(), extent, range);
11075                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
11076                             bounds.height(), thumbLength, extent, range, offset);
11077 
11078                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
11079                     final float maxThumbOffset = bounds.height() - thumbLength;
11080                     final float newThumbOffset =
11081                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11082                     final int height = getHeight();
11083                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11084                             && height > 0 && extent > 0) {
11085                         final int newY = Math.round((range - extent)
11086                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11087                         if (newY != getScrollY()) {
11088                             mScrollCache.mScrollBarDraggingPos = y;
11089                             setScrollY(newY);
11090                         }
11091                     }
11092                     return true;
11093                 }
11094                 if (mScrollCache.mScrollBarDraggingState
11095                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11096                     final Rect bounds = mScrollCache.mScrollBarBounds;
11097                     getHorizontalScrollBarBounds(bounds);
11098                     final int range = computeHorizontalScrollRange();
11099                     final int offset = computeHorizontalScrollOffset();
11100                     final int extent = computeHorizontalScrollExtent();
11101 
11102                     final int thumbLength = ScrollBarUtils.getThumbLength(
11103                             bounds.width(), bounds.height(), extent, range);
11104                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
11105                             bounds.width(), thumbLength, extent, range, offset);
11106 
11107                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
11108                     final float maxThumbOffset = bounds.width() - thumbLength;
11109                     final float newThumbOffset =
11110                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11111                     final int width = getWidth();
11112                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11113                             && width > 0 && extent > 0) {
11114                         final int newX = Math.round((range - extent)
11115                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11116                         if (newX != getScrollX()) {
11117                             mScrollCache.mScrollBarDraggingPos = x;
11118                             setScrollX(newX);
11119                         }
11120                     }
11121                     return true;
11122                 }
11123             case MotionEvent.ACTION_DOWN:
11124                 if (mScrollCache.state == ScrollabilityCache.OFF) {
11125                     return false;
11126                 }
11127                 if (isOnVerticalScrollbarThumb(x, y)) {
11128                     mScrollCache.mScrollBarDraggingState =
11129                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11130                     mScrollCache.mScrollBarDraggingPos = y;
11131                     return true;
11132                 }
11133                 if (isOnHorizontalScrollbarThumb(x, y)) {
11134                     mScrollCache.mScrollBarDraggingState =
11135                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11136                     mScrollCache.mScrollBarDraggingPos = x;
11137                     return true;
11138                 }
11139         }
11140         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11141         return false;
11142     }
11143 
11144     /**
11145      * Implement this method to handle touch screen motion events.
11146      * <p>
11147      * If this method is used to detect click actions, it is recommended that
11148      * the actions be performed by implementing and calling
11149      * {@link #performClick()}. This will ensure consistent system behavior,
11150      * including:
11151      * <ul>
11152      * <li>obeying click sound preferences
11153      * <li>dispatching OnClickListener calls
11154      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11155      * accessibility features are enabled
11156      * </ul>
11157      *
11158      * @param event The motion event.
11159      * @return True if the event was handled, false otherwise.
11160      */
onTouchEvent(MotionEvent event)11161     public boolean onTouchEvent(MotionEvent event) {
11162         final float x = event.getX();
11163         final float y = event.getY();
11164         final int viewFlags = mViewFlags;
11165         final int action = event.getAction();
11166 
11167         if ((viewFlags & ENABLED_MASK) == DISABLED) {
11168             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11169                 setPressed(false);
11170             }
11171             // A disabled view that is clickable still consumes the touch
11172             // events, it just doesn't respond to them.
11173             return (((viewFlags & CLICKABLE) == CLICKABLE
11174                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11175                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11176         }
11177         if (mTouchDelegate != null) {
11178             if (mTouchDelegate.onTouchEvent(event)) {
11179                 return true;
11180             }
11181         }
11182 
11183         if (((viewFlags & CLICKABLE) == CLICKABLE ||
11184                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11185                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11186             switch (action) {
11187                 case MotionEvent.ACTION_UP:
11188                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11189                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11190                         // take focus if we don't have it already and we should in
11191                         // touch mode.
11192                         boolean focusTaken = false;
11193                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11194                             focusTaken = requestFocus();
11195                         }
11196 
11197                         if (prepressed) {
11198                             // The button is being released before we actually
11199                             // showed it as pressed.  Make it show the pressed
11200                             // state now (before scheduling the click) to ensure
11201                             // the user sees it.
11202                             setPressed(true, x, y);
11203                        }
11204 
11205                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11206                             // This is a tap, so remove the longpress check
11207                             removeLongPressCallback();
11208 
11209                             // Only perform take click actions if we were in the pressed state
11210                             if (!focusTaken) {
11211                                 // Use a Runnable and post this rather than calling
11212                                 // performClick directly. This lets other visual state
11213                                 // of the view update before click actions start.
11214                                 if (mPerformClick == null) {
11215                                     mPerformClick = new PerformClick();
11216                                 }
11217                                 if (!post(mPerformClick)) {
11218                                     performClick();
11219                                 }
11220                             }
11221                         }
11222 
11223                         if (mUnsetPressedState == null) {
11224                             mUnsetPressedState = new UnsetPressedState();
11225                         }
11226 
11227                         if (prepressed) {
11228                             postDelayed(mUnsetPressedState,
11229                                     ViewConfiguration.getPressedStateDuration());
11230                         } else if (!post(mUnsetPressedState)) {
11231                             // If the post failed, unpress right now
11232                             mUnsetPressedState.run();
11233                         }
11234 
11235                         removeTapCallback();
11236                     }
11237                     mIgnoreNextUpEvent = false;
11238                     break;
11239 
11240                 case MotionEvent.ACTION_DOWN:
11241                     mHasPerformedLongPress = false;
11242 
11243                     if (performButtonActionOnTouchDown(event)) {
11244                         break;
11245                     }
11246 
11247                     // Walk up the hierarchy to determine if we're inside a scrolling container.
11248                     boolean isInScrollingContainer = isInScrollingContainer();
11249 
11250                     // For views inside a scrolling container, delay the pressed feedback for
11251                     // a short period in case this is a scroll.
11252                     if (isInScrollingContainer) {
11253                         mPrivateFlags |= PFLAG_PREPRESSED;
11254                         if (mPendingCheckForTap == null) {
11255                             mPendingCheckForTap = new CheckForTap();
11256                         }
11257                         mPendingCheckForTap.x = event.getX();
11258                         mPendingCheckForTap.y = event.getY();
11259                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11260                     } else {
11261                         // Not inside a scrolling container, so show the feedback right away
11262                         setPressed(true, x, y);
11263                         checkForLongClick(0, x, y);
11264                     }
11265                     break;
11266 
11267                 case MotionEvent.ACTION_CANCEL:
11268                     setPressed(false);
11269                     removeTapCallback();
11270                     removeLongPressCallback();
11271                     mInContextButtonPress = false;
11272                     mHasPerformedLongPress = false;
11273                     mIgnoreNextUpEvent = false;
11274                     break;
11275 
11276                 case MotionEvent.ACTION_MOVE:
11277                     drawableHotspotChanged(x, y);
11278 
11279                     // Be lenient about moving outside of buttons
11280                     if (!pointInView(x, y, mTouchSlop)) {
11281                         // Outside button
11282                         removeTapCallback();
11283                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11284                             // Remove any future long press/tap checks
11285                             removeLongPressCallback();
11286 
11287                             setPressed(false);
11288                         }
11289                     }
11290                     break;
11291             }
11292 
11293             return true;
11294         }
11295 
11296         return false;
11297     }
11298 
11299     /**
11300      * @hide
11301      */
isInScrollingContainer()11302     public boolean isInScrollingContainer() {
11303         ViewParent p = getParent();
11304         while (p != null && p instanceof ViewGroup) {
11305             if (((ViewGroup) p).shouldDelayChildPressedState()) {
11306                 return true;
11307             }
11308             p = p.getParent();
11309         }
11310         return false;
11311     }
11312 
11313     /**
11314      * Remove the longpress detection timer.
11315      */
removeLongPressCallback()11316     private void removeLongPressCallback() {
11317         if (mPendingCheckForLongPress != null) {
11318           removeCallbacks(mPendingCheckForLongPress);
11319         }
11320     }
11321 
11322     /**
11323      * Remove the pending click action
11324      */
removePerformClickCallback()11325     private void removePerformClickCallback() {
11326         if (mPerformClick != null) {
11327             removeCallbacks(mPerformClick);
11328         }
11329     }
11330 
11331     /**
11332      * Remove the prepress detection timer.
11333      */
removeUnsetPressCallback()11334     private void removeUnsetPressCallback() {
11335         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11336             setPressed(false);
11337             removeCallbacks(mUnsetPressedState);
11338         }
11339     }
11340 
11341     /**
11342      * Remove the tap detection timer.
11343      */
removeTapCallback()11344     private void removeTapCallback() {
11345         if (mPendingCheckForTap != null) {
11346             mPrivateFlags &= ~PFLAG_PREPRESSED;
11347             removeCallbacks(mPendingCheckForTap);
11348         }
11349     }
11350 
11351     /**
11352      * Cancels a pending long press.  Your subclass can use this if you
11353      * want the context menu to come up if the user presses and holds
11354      * at the same place, but you don't want it to come up if they press
11355      * and then move around enough to cause scrolling.
11356      */
cancelLongPress()11357     public void cancelLongPress() {
11358         removeLongPressCallback();
11359 
11360         /*
11361          * The prepressed state handled by the tap callback is a display
11362          * construct, but the tap callback will post a long press callback
11363          * less its own timeout. Remove it here.
11364          */
11365         removeTapCallback();
11366     }
11367 
11368     /**
11369      * Remove the pending callback for sending a
11370      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11371      */
removeSendViewScrolledAccessibilityEventCallback()11372     private void removeSendViewScrolledAccessibilityEventCallback() {
11373         if (mSendViewScrolledAccessibilityEvent != null) {
11374             removeCallbacks(mSendViewScrolledAccessibilityEvent);
11375             mSendViewScrolledAccessibilityEvent.mIsPending = false;
11376         }
11377     }
11378 
11379     /**
11380      * Sets the TouchDelegate for this View.
11381      */
setTouchDelegate(TouchDelegate delegate)11382     public void setTouchDelegate(TouchDelegate delegate) {
11383         mTouchDelegate = delegate;
11384     }
11385 
11386     /**
11387      * Gets the TouchDelegate for this View.
11388      */
getTouchDelegate()11389     public TouchDelegate getTouchDelegate() {
11390         return mTouchDelegate;
11391     }
11392 
11393     /**
11394      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11395      *
11396      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11397      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11398      * available. This method should only be called for touch events.
11399      *
11400      * <p class="note">This api is not intended for most applications. Buffered dispatch
11401      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11402      * streams will not improve your input latency. Side effects include: increased latency,
11403      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11404      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11405      * you.</p>
11406      */
requestUnbufferedDispatch(MotionEvent event)11407     public final void requestUnbufferedDispatch(MotionEvent event) {
11408         final int action = event.getAction();
11409         if (mAttachInfo == null
11410                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11411                 || !event.isTouchEvent()) {
11412             return;
11413         }
11414         mAttachInfo.mUnbufferedDispatchRequested = true;
11415     }
11416 
11417     /**
11418      * Set flags controlling behavior of this view.
11419      *
11420      * @param flags Constant indicating the value which should be set
11421      * @param mask Constant indicating the bit range that should be changed
11422      */
setFlags(int flags, int mask)11423     void setFlags(int flags, int mask) {
11424         final boolean accessibilityEnabled =
11425                 AccessibilityManager.getInstance(mContext).isEnabled();
11426         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11427 
11428         int old = mViewFlags;
11429         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11430 
11431         int changed = mViewFlags ^ old;
11432         if (changed == 0) {
11433             return;
11434         }
11435         int privateFlags = mPrivateFlags;
11436 
11437         /* Check if the FOCUSABLE bit has changed */
11438         if (((changed & FOCUSABLE_MASK) != 0) &&
11439                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11440             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11441                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11442                 /* Give up focus if we are no longer focusable */
11443                 clearFocus();
11444             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11445                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11446                 /*
11447                  * Tell the view system that we are now available to take focus
11448                  * if no one else already has it.
11449                  */
11450                 if (mParent != null) mParent.focusableViewAvailable(this);
11451             }
11452         }
11453 
11454         final int newVisibility = flags & VISIBILITY_MASK;
11455         if (newVisibility == VISIBLE) {
11456             if ((changed & VISIBILITY_MASK) != 0) {
11457                 /*
11458                  * If this view is becoming visible, invalidate it in case it changed while
11459                  * it was not visible. Marking it drawn ensures that the invalidation will
11460                  * go through.
11461                  */
11462                 mPrivateFlags |= PFLAG_DRAWN;
11463                 invalidate(true);
11464 
11465                 needGlobalAttributesUpdate(true);
11466 
11467                 // a view becoming visible is worth notifying the parent
11468                 // about in case nothing has focus.  even if this specific view
11469                 // isn't focusable, it may contain something that is, so let
11470                 // the root view try to give this focus if nothing else does.
11471                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11472                     mParent.focusableViewAvailable(this);
11473                 }
11474             }
11475         }
11476 
11477         /* Check if the GONE bit has changed */
11478         if ((changed & GONE) != 0) {
11479             needGlobalAttributesUpdate(false);
11480             requestLayout();
11481 
11482             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11483                 if (hasFocus()) clearFocus();
11484                 clearAccessibilityFocus();
11485                 destroyDrawingCache();
11486                 if (mParent instanceof View) {
11487                     // GONE views noop invalidation, so invalidate the parent
11488                     ((View) mParent).invalidate(true);
11489                 }
11490                 // Mark the view drawn to ensure that it gets invalidated properly the next
11491                 // time it is visible and gets invalidated
11492                 mPrivateFlags |= PFLAG_DRAWN;
11493             }
11494             if (mAttachInfo != null) {
11495                 mAttachInfo.mViewVisibilityChanged = true;
11496             }
11497         }
11498 
11499         /* Check if the VISIBLE bit has changed */
11500         if ((changed & INVISIBLE) != 0) {
11501             needGlobalAttributesUpdate(false);
11502             /*
11503              * If this view is becoming invisible, set the DRAWN flag so that
11504              * the next invalidate() will not be skipped.
11505              */
11506             mPrivateFlags |= PFLAG_DRAWN;
11507 
11508             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11509                 // root view becoming invisible shouldn't clear focus and accessibility focus
11510                 if (getRootView() != this) {
11511                     if (hasFocus()) clearFocus();
11512                     clearAccessibilityFocus();
11513                 }
11514             }
11515             if (mAttachInfo != null) {
11516                 mAttachInfo.mViewVisibilityChanged = true;
11517             }
11518         }
11519 
11520         if ((changed & VISIBILITY_MASK) != 0) {
11521             // If the view is invisible, cleanup its display list to free up resources
11522             if (newVisibility != VISIBLE && mAttachInfo != null) {
11523                 cleanupDraw();
11524             }
11525 
11526             if (mParent instanceof ViewGroup) {
11527                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
11528                         (changed & VISIBILITY_MASK), newVisibility);
11529                 ((View) mParent).invalidate(true);
11530             } else if (mParent != null) {
11531                 mParent.invalidateChild(this, null);
11532             }
11533 
11534             if (mAttachInfo != null) {
11535                 dispatchVisibilityChanged(this, newVisibility);
11536 
11537                 // Aggregated visibility changes are dispatched to attached views
11538                 // in visible windows where the parent is currently shown/drawn
11539                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11540                 // discounting clipping or overlapping. This makes it a good place
11541                 // to change animation states.
11542                 if (mParent != null && getWindowVisibility() == VISIBLE &&
11543                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11544                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
11545                 }
11546                 notifySubtreeAccessibilityStateChangedIfNeeded();
11547             }
11548         }
11549 
11550         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11551             destroyDrawingCache();
11552         }
11553 
11554         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11555             destroyDrawingCache();
11556             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11557             invalidateParentCaches();
11558         }
11559 
11560         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11561             destroyDrawingCache();
11562             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11563         }
11564 
11565         if ((changed & DRAW_MASK) != 0) {
11566             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11567                 if (mBackground != null
11568                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11569                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11570                 } else {
11571                     mPrivateFlags |= PFLAG_SKIP_DRAW;
11572                 }
11573             } else {
11574                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11575             }
11576             requestLayout();
11577             invalidate(true);
11578         }
11579 
11580         if ((changed & KEEP_SCREEN_ON) != 0) {
11581             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11582                 mParent.recomputeViewAttributes(this);
11583             }
11584         }
11585 
11586         if (accessibilityEnabled) {
11587             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11588                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11589                     || (changed & CONTEXT_CLICKABLE) != 0) {
11590                 if (oldIncludeForAccessibility != includeForAccessibility()) {
11591                     notifySubtreeAccessibilityStateChangedIfNeeded();
11592                 } else {
11593                     notifyViewAccessibilityStateChangedIfNeeded(
11594                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11595                 }
11596             } else if ((changed & ENABLED_MASK) != 0) {
11597                 notifyViewAccessibilityStateChangedIfNeeded(
11598                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11599             }
11600         }
11601     }
11602 
11603     /**
11604      * Change the view's z order in the tree, so it's on top of other sibling
11605      * views. This ordering change may affect layout, if the parent container
11606      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11607      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11608      * method should be followed by calls to {@link #requestLayout()} and
11609      * {@link View#invalidate()} on the view's parent to force the parent to redraw
11610      * with the new child ordering.
11611      *
11612      * @see ViewGroup#bringChildToFront(View)
11613      */
bringToFront()11614     public void bringToFront() {
11615         if (mParent != null) {
11616             mParent.bringChildToFront(this);
11617         }
11618     }
11619 
11620     /**
11621      * This is called in response to an internal scroll in this view (i.e., the
11622      * view scrolled its own contents). This is typically as a result of
11623      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11624      * called.
11625      *
11626      * @param l Current horizontal scroll origin.
11627      * @param t Current vertical scroll origin.
11628      * @param oldl Previous horizontal scroll origin.
11629      * @param oldt Previous vertical scroll origin.
11630      */
onScrollChanged(int l, int t, int oldl, int oldt)11631     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11632         notifySubtreeAccessibilityStateChangedIfNeeded();
11633 
11634         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11635             postSendViewScrolledAccessibilityEventCallback();
11636         }
11637 
11638         mBackgroundSizeChanged = true;
11639         if (mForegroundInfo != null) {
11640             mForegroundInfo.mBoundsChanged = true;
11641         }
11642 
11643         final AttachInfo ai = mAttachInfo;
11644         if (ai != null) {
11645             ai.mViewScrollChanged = true;
11646         }
11647 
11648         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11649             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11650         }
11651     }
11652 
11653     /**
11654      * Interface definition for a callback to be invoked when the scroll
11655      * X or Y positions of a view change.
11656      * <p>
11657      * <b>Note:</b> Some views handle scrolling independently from View and may
11658      * have their own separate listeners for scroll-type events. For example,
11659      * {@link android.widget.ListView ListView} allows clients to register an
11660      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11661      * to listen for changes in list scroll position.
11662      *
11663      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11664      */
11665     public interface OnScrollChangeListener {
11666         /**
11667          * Called when the scroll position of a view changes.
11668          *
11669          * @param v The view whose scroll position has changed.
11670          * @param scrollX Current horizontal scroll origin.
11671          * @param scrollY Current vertical scroll origin.
11672          * @param oldScrollX Previous horizontal scroll origin.
11673          * @param oldScrollY Previous vertical scroll origin.
11674          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)11675         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11676     }
11677 
11678     /**
11679      * Interface definition for a callback to be invoked when the layout bounds of a view
11680      * changes due to layout processing.
11681      */
11682     public interface OnLayoutChangeListener {
11683         /**
11684          * Called when the layout bounds of a view changes due to layout processing.
11685          *
11686          * @param v The view whose bounds have changed.
11687          * @param left The new value of the view's left property.
11688          * @param top The new value of the view's top property.
11689          * @param right The new value of the view's right property.
11690          * @param bottom The new value of the view's bottom property.
11691          * @param oldLeft The previous value of the view's left property.
11692          * @param oldTop The previous value of the view's top property.
11693          * @param oldRight The previous value of the view's right property.
11694          * @param oldBottom The previous value of the view's bottom property.
11695          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)11696         void onLayoutChange(View v, int left, int top, int right, int bottom,
11697             int oldLeft, int oldTop, int oldRight, int oldBottom);
11698     }
11699 
11700     /**
11701      * This is called during layout when the size of this view has changed. If
11702      * you were just added to the view hierarchy, you're called with the old
11703      * values of 0.
11704      *
11705      * @param w Current width of this view.
11706      * @param h Current height of this view.
11707      * @param oldw Old width of this view.
11708      * @param oldh Old height of this view.
11709      */
onSizeChanged(int w, int h, int oldw, int oldh)11710     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11711     }
11712 
11713     /**
11714      * Called by draw to draw the child views. This may be overridden
11715      * by derived classes to gain control just before its children are drawn
11716      * (but after its own view has been drawn).
11717      * @param canvas the canvas on which to draw the view
11718      */
dispatchDraw(Canvas canvas)11719     protected void dispatchDraw(Canvas canvas) {
11720 
11721     }
11722 
11723     /**
11724      * Gets the parent of this view. Note that the parent is a
11725      * ViewParent and not necessarily a View.
11726      *
11727      * @return Parent of this view.
11728      */
getParent()11729     public final ViewParent getParent() {
11730         return mParent;
11731     }
11732 
11733     /**
11734      * Set the horizontal scrolled position of your view. This will cause a call to
11735      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11736      * invalidated.
11737      * @param value the x position to scroll to
11738      */
setScrollX(int value)11739     public void setScrollX(int value) {
11740         scrollTo(value, mScrollY);
11741     }
11742 
11743     /**
11744      * Set the vertical scrolled position of your view. This will cause a call to
11745      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11746      * invalidated.
11747      * @param value the y position to scroll to
11748      */
setScrollY(int value)11749     public void setScrollY(int value) {
11750         scrollTo(mScrollX, value);
11751     }
11752 
11753     /**
11754      * Return the scrolled left position of this view. This is the left edge of
11755      * the displayed part of your view. You do not need to draw any pixels
11756      * farther left, since those are outside of the frame of your view on
11757      * screen.
11758      *
11759      * @return The left edge of the displayed part of your view, in pixels.
11760      */
getScrollX()11761     public final int getScrollX() {
11762         return mScrollX;
11763     }
11764 
11765     /**
11766      * Return the scrolled top position of this view. This is the top edge of
11767      * the displayed part of your view. You do not need to draw any pixels above
11768      * it, since those are outside of the frame of your view on screen.
11769      *
11770      * @return The top edge of the displayed part of your view, in pixels.
11771      */
getScrollY()11772     public final int getScrollY() {
11773         return mScrollY;
11774     }
11775 
11776     /**
11777      * Return the width of the your view.
11778      *
11779      * @return The width of your view, in pixels.
11780      */
11781     @ViewDebug.ExportedProperty(category = "layout")
getWidth()11782     public final int getWidth() {
11783         return mRight - mLeft;
11784     }
11785 
11786     /**
11787      * Return the height of your view.
11788      *
11789      * @return The height of your view, in pixels.
11790      */
11791     @ViewDebug.ExportedProperty(category = "layout")
getHeight()11792     public final int getHeight() {
11793         return mBottom - mTop;
11794     }
11795 
11796     /**
11797      * Return the visible drawing bounds of your view. Fills in the output
11798      * rectangle with the values from getScrollX(), getScrollY(),
11799      * getWidth(), and getHeight(). These bounds do not account for any
11800      * transformation properties currently set on the view, such as
11801      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11802      *
11803      * @param outRect The (scrolled) drawing bounds of the view.
11804      */
getDrawingRect(Rect outRect)11805     public void getDrawingRect(Rect outRect) {
11806         outRect.left = mScrollX;
11807         outRect.top = mScrollY;
11808         outRect.right = mScrollX + (mRight - mLeft);
11809         outRect.bottom = mScrollY + (mBottom - mTop);
11810     }
11811 
11812     /**
11813      * Like {@link #getMeasuredWidthAndState()}, but only returns the
11814      * raw width component (that is the result is masked by
11815      * {@link #MEASURED_SIZE_MASK}).
11816      *
11817      * @return The raw measured width of this view.
11818      */
getMeasuredWidth()11819     public final int getMeasuredWidth() {
11820         return mMeasuredWidth & MEASURED_SIZE_MASK;
11821     }
11822 
11823     /**
11824      * Return the full width measurement information for this view as computed
11825      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11826      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11827      * This should be used during measurement and layout calculations only. Use
11828      * {@link #getWidth()} to see how wide a view is after layout.
11829      *
11830      * @return The measured width of this view as a bit mask.
11831      */
11832     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11833             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11834                     name = "MEASURED_STATE_TOO_SMALL"),
11835     })
getMeasuredWidthAndState()11836     public final int getMeasuredWidthAndState() {
11837         return mMeasuredWidth;
11838     }
11839 
11840     /**
11841      * Like {@link #getMeasuredHeightAndState()}, but only returns the
11842      * raw width component (that is the result is masked by
11843      * {@link #MEASURED_SIZE_MASK}).
11844      *
11845      * @return The raw measured height of this view.
11846      */
getMeasuredHeight()11847     public final int getMeasuredHeight() {
11848         return mMeasuredHeight & MEASURED_SIZE_MASK;
11849     }
11850 
11851     /**
11852      * Return the full height measurement information for this view as computed
11853      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11854      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11855      * This should be used during measurement and layout calculations only. Use
11856      * {@link #getHeight()} to see how wide a view is after layout.
11857      *
11858      * @return The measured width of this view as a bit mask.
11859      */
11860     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11861             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11862                     name = "MEASURED_STATE_TOO_SMALL"),
11863     })
getMeasuredHeightAndState()11864     public final int getMeasuredHeightAndState() {
11865         return mMeasuredHeight;
11866     }
11867 
11868     /**
11869      * Return only the state bits of {@link #getMeasuredWidthAndState()}
11870      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11871      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11872      * and the height component is at the shifted bits
11873      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11874      */
getMeasuredState()11875     public final int getMeasuredState() {
11876         return (mMeasuredWidth&MEASURED_STATE_MASK)
11877                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11878                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11879     }
11880 
11881     /**
11882      * The transform matrix of this view, which is calculated based on the current
11883      * rotation, scale, and pivot properties.
11884      *
11885      * @see #getRotation()
11886      * @see #getScaleX()
11887      * @see #getScaleY()
11888      * @see #getPivotX()
11889      * @see #getPivotY()
11890      * @return The current transform matrix for the view
11891      */
getMatrix()11892     public Matrix getMatrix() {
11893         ensureTransformationInfo();
11894         final Matrix matrix = mTransformationInfo.mMatrix;
11895         mRenderNode.getMatrix(matrix);
11896         return matrix;
11897     }
11898 
11899     /**
11900      * Returns true if the transform matrix is the identity matrix.
11901      * Recomputes the matrix if necessary.
11902      *
11903      * @return True if the transform matrix is the identity matrix, false otherwise.
11904      */
hasIdentityMatrix()11905     final boolean hasIdentityMatrix() {
11906         return mRenderNode.hasIdentityMatrix();
11907     }
11908 
ensureTransformationInfo()11909     void ensureTransformationInfo() {
11910         if (mTransformationInfo == null) {
11911             mTransformationInfo = new TransformationInfo();
11912         }
11913     }
11914 
11915     /**
11916      * Utility method to retrieve the inverse of the current mMatrix property.
11917      * We cache the matrix to avoid recalculating it when transform properties
11918      * have not changed.
11919      *
11920      * @return The inverse of the current matrix of this view.
11921      * @hide
11922      */
getInverseMatrix()11923     public final Matrix getInverseMatrix() {
11924         ensureTransformationInfo();
11925         if (mTransformationInfo.mInverseMatrix == null) {
11926             mTransformationInfo.mInverseMatrix = new Matrix();
11927         }
11928         final Matrix matrix = mTransformationInfo.mInverseMatrix;
11929         mRenderNode.getInverseMatrix(matrix);
11930         return matrix;
11931     }
11932 
11933     /**
11934      * Gets the distance along the Z axis from the camera to this view.
11935      *
11936      * @see #setCameraDistance(float)
11937      *
11938      * @return The distance along the Z axis.
11939      */
getCameraDistance()11940     public float getCameraDistance() {
11941         final float dpi = mResources.getDisplayMetrics().densityDpi;
11942         return -(mRenderNode.getCameraDistance() * dpi);
11943     }
11944 
11945     /**
11946      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11947      * views are drawn) from the camera to this view. The camera's distance
11948      * affects 3D transformations, for instance rotations around the X and Y
11949      * axis. If the rotationX or rotationY properties are changed and this view is
11950      * large (more than half the size of the screen), it is recommended to always
11951      * use a camera distance that's greater than the height (X axis rotation) or
11952      * the width (Y axis rotation) of this view.</p>
11953      *
11954      * <p>The distance of the camera from the view plane can have an affect on the
11955      * perspective distortion of the view when it is rotated around the x or y axis.
11956      * For example, a large distance will result in a large viewing angle, and there
11957      * will not be much perspective distortion of the view as it rotates. A short
11958      * distance may cause much more perspective distortion upon rotation, and can
11959      * also result in some drawing artifacts if the rotated view ends up partially
11960      * behind the camera (which is why the recommendation is to use a distance at
11961      * least as far as the size of the view, if the view is to be rotated.)</p>
11962      *
11963      * <p>The distance is expressed in "depth pixels." The default distance depends
11964      * on the screen density. For instance, on a medium density display, the
11965      * default distance is 1280. On a high density display, the default distance
11966      * is 1920.</p>
11967      *
11968      * <p>If you want to specify a distance that leads to visually consistent
11969      * results across various densities, use the following formula:</p>
11970      * <pre>
11971      * float scale = context.getResources().getDisplayMetrics().density;
11972      * view.setCameraDistance(distance * scale);
11973      * </pre>
11974      *
11975      * <p>The density scale factor of a high density display is 1.5,
11976      * and 1920 = 1280 * 1.5.</p>
11977      *
11978      * @param distance The distance in "depth pixels", if negative the opposite
11979      *        value is used
11980      *
11981      * @see #setRotationX(float)
11982      * @see #setRotationY(float)
11983      */
setCameraDistance(float distance)11984     public void setCameraDistance(float distance) {
11985         final float dpi = mResources.getDisplayMetrics().densityDpi;
11986 
11987         invalidateViewProperty(true, false);
11988         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11989         invalidateViewProperty(false, false);
11990 
11991         invalidateParentIfNeededAndWasQuickRejected();
11992     }
11993 
11994     /**
11995      * The degrees that the view is rotated around the pivot point.
11996      *
11997      * @see #setRotation(float)
11998      * @see #getPivotX()
11999      * @see #getPivotY()
12000      *
12001      * @return The degrees of rotation.
12002      */
12003     @ViewDebug.ExportedProperty(category = "drawing")
getRotation()12004     public float getRotation() {
12005         return mRenderNode.getRotation();
12006     }
12007 
12008     /**
12009      * Sets the degrees that the view is rotated around the pivot point. Increasing values
12010      * result in clockwise rotation.
12011      *
12012      * @param rotation The degrees of rotation.
12013      *
12014      * @see #getRotation()
12015      * @see #getPivotX()
12016      * @see #getPivotY()
12017      * @see #setRotationX(float)
12018      * @see #setRotationY(float)
12019      *
12020      * @attr ref android.R.styleable#View_rotation
12021      */
setRotation(float rotation)12022     public void setRotation(float rotation) {
12023         if (rotation != getRotation()) {
12024             // Double-invalidation is necessary to capture view's old and new areas
12025             invalidateViewProperty(true, false);
12026             mRenderNode.setRotation(rotation);
12027             invalidateViewProperty(false, true);
12028 
12029             invalidateParentIfNeededAndWasQuickRejected();
12030             notifySubtreeAccessibilityStateChangedIfNeeded();
12031         }
12032     }
12033 
12034     /**
12035      * The degrees that the view is rotated around the vertical axis through the pivot point.
12036      *
12037      * @see #getPivotX()
12038      * @see #getPivotY()
12039      * @see #setRotationY(float)
12040      *
12041      * @return The degrees of Y rotation.
12042      */
12043     @ViewDebug.ExportedProperty(category = "drawing")
getRotationY()12044     public float getRotationY() {
12045         return mRenderNode.getRotationY();
12046     }
12047 
12048     /**
12049      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12050      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12051      * down the y axis.
12052      *
12053      * When rotating large views, it is recommended to adjust the camera distance
12054      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12055      *
12056      * @param rotationY The degrees of Y rotation.
12057      *
12058      * @see #getRotationY()
12059      * @see #getPivotX()
12060      * @see #getPivotY()
12061      * @see #setRotation(float)
12062      * @see #setRotationX(float)
12063      * @see #setCameraDistance(float)
12064      *
12065      * @attr ref android.R.styleable#View_rotationY
12066      */
setRotationY(float rotationY)12067     public void setRotationY(float rotationY) {
12068         if (rotationY != getRotationY()) {
12069             invalidateViewProperty(true, false);
12070             mRenderNode.setRotationY(rotationY);
12071             invalidateViewProperty(false, true);
12072 
12073             invalidateParentIfNeededAndWasQuickRejected();
12074             notifySubtreeAccessibilityStateChangedIfNeeded();
12075         }
12076     }
12077 
12078     /**
12079      * The degrees that the view is rotated around the horizontal axis through the pivot point.
12080      *
12081      * @see #getPivotX()
12082      * @see #getPivotY()
12083      * @see #setRotationX(float)
12084      *
12085      * @return The degrees of X rotation.
12086      */
12087     @ViewDebug.ExportedProperty(category = "drawing")
getRotationX()12088     public float getRotationX() {
12089         return mRenderNode.getRotationX();
12090     }
12091 
12092     /**
12093      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12094      * Increasing values result in clockwise rotation from the viewpoint of looking down the
12095      * x axis.
12096      *
12097      * When rotating large views, it is recommended to adjust the camera distance
12098      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12099      *
12100      * @param rotationX The degrees of X rotation.
12101      *
12102      * @see #getRotationX()
12103      * @see #getPivotX()
12104      * @see #getPivotY()
12105      * @see #setRotation(float)
12106      * @see #setRotationY(float)
12107      * @see #setCameraDistance(float)
12108      *
12109      * @attr ref android.R.styleable#View_rotationX
12110      */
setRotationX(float rotationX)12111     public void setRotationX(float rotationX) {
12112         if (rotationX != getRotationX()) {
12113             invalidateViewProperty(true, false);
12114             mRenderNode.setRotationX(rotationX);
12115             invalidateViewProperty(false, true);
12116 
12117             invalidateParentIfNeededAndWasQuickRejected();
12118             notifySubtreeAccessibilityStateChangedIfNeeded();
12119         }
12120     }
12121 
12122     /**
12123      * The amount that the view is scaled in x around the pivot point, as a proportion of
12124      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12125      *
12126      * <p>By default, this is 1.0f.
12127      *
12128      * @see #getPivotX()
12129      * @see #getPivotY()
12130      * @return The scaling factor.
12131      */
12132     @ViewDebug.ExportedProperty(category = "drawing")
getScaleX()12133     public float getScaleX() {
12134         return mRenderNode.getScaleX();
12135     }
12136 
12137     /**
12138      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12139      * the view's unscaled width. A value of 1 means that no scaling is applied.
12140      *
12141      * @param scaleX The scaling factor.
12142      * @see #getPivotX()
12143      * @see #getPivotY()
12144      *
12145      * @attr ref android.R.styleable#View_scaleX
12146      */
setScaleX(float scaleX)12147     public void setScaleX(float scaleX) {
12148         if (scaleX != getScaleX()) {
12149             invalidateViewProperty(true, false);
12150             mRenderNode.setScaleX(scaleX);
12151             invalidateViewProperty(false, true);
12152 
12153             invalidateParentIfNeededAndWasQuickRejected();
12154             notifySubtreeAccessibilityStateChangedIfNeeded();
12155         }
12156     }
12157 
12158     /**
12159      * The amount that the view is scaled in y around the pivot point, as a proportion of
12160      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12161      *
12162      * <p>By default, this is 1.0f.
12163      *
12164      * @see #getPivotX()
12165      * @see #getPivotY()
12166      * @return The scaling factor.
12167      */
12168     @ViewDebug.ExportedProperty(category = "drawing")
getScaleY()12169     public float getScaleY() {
12170         return mRenderNode.getScaleY();
12171     }
12172 
12173     /**
12174      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12175      * the view's unscaled width. A value of 1 means that no scaling is applied.
12176      *
12177      * @param scaleY The scaling factor.
12178      * @see #getPivotX()
12179      * @see #getPivotY()
12180      *
12181      * @attr ref android.R.styleable#View_scaleY
12182      */
setScaleY(float scaleY)12183     public void setScaleY(float scaleY) {
12184         if (scaleY != getScaleY()) {
12185             invalidateViewProperty(true, false);
12186             mRenderNode.setScaleY(scaleY);
12187             invalidateViewProperty(false, true);
12188 
12189             invalidateParentIfNeededAndWasQuickRejected();
12190             notifySubtreeAccessibilityStateChangedIfNeeded();
12191         }
12192     }
12193 
12194     /**
12195      * The x location of the point around which the view is {@link #setRotation(float) rotated}
12196      * and {@link #setScaleX(float) scaled}.
12197      *
12198      * @see #getRotation()
12199      * @see #getScaleX()
12200      * @see #getScaleY()
12201      * @see #getPivotY()
12202      * @return The x location of the pivot point.
12203      *
12204      * @attr ref android.R.styleable#View_transformPivotX
12205      */
12206     @ViewDebug.ExportedProperty(category = "drawing")
getPivotX()12207     public float getPivotX() {
12208         return mRenderNode.getPivotX();
12209     }
12210 
12211     /**
12212      * Sets the x location of the point around which the view is
12213      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12214      * By default, the pivot point is centered on the object.
12215      * Setting this property disables this behavior and causes the view to use only the
12216      * explicitly set pivotX and pivotY values.
12217      *
12218      * @param pivotX The x location of the pivot point.
12219      * @see #getRotation()
12220      * @see #getScaleX()
12221      * @see #getScaleY()
12222      * @see #getPivotY()
12223      *
12224      * @attr ref android.R.styleable#View_transformPivotX
12225      */
setPivotX(float pivotX)12226     public void setPivotX(float pivotX) {
12227         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12228             invalidateViewProperty(true, false);
12229             mRenderNode.setPivotX(pivotX);
12230             invalidateViewProperty(false, true);
12231 
12232             invalidateParentIfNeededAndWasQuickRejected();
12233         }
12234     }
12235 
12236     /**
12237      * The y location of the point around which the view is {@link #setRotation(float) rotated}
12238      * and {@link #setScaleY(float) scaled}.
12239      *
12240      * @see #getRotation()
12241      * @see #getScaleX()
12242      * @see #getScaleY()
12243      * @see #getPivotY()
12244      * @return The y location of the pivot point.
12245      *
12246      * @attr ref android.R.styleable#View_transformPivotY
12247      */
12248     @ViewDebug.ExportedProperty(category = "drawing")
getPivotY()12249     public float getPivotY() {
12250         return mRenderNode.getPivotY();
12251     }
12252 
12253     /**
12254      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12255      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12256      * Setting this property disables this behavior and causes the view to use only the
12257      * explicitly set pivotX and pivotY values.
12258      *
12259      * @param pivotY The y location of the pivot point.
12260      * @see #getRotation()
12261      * @see #getScaleX()
12262      * @see #getScaleY()
12263      * @see #getPivotY()
12264      *
12265      * @attr ref android.R.styleable#View_transformPivotY
12266      */
setPivotY(float pivotY)12267     public void setPivotY(float pivotY) {
12268         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12269             invalidateViewProperty(true, false);
12270             mRenderNode.setPivotY(pivotY);
12271             invalidateViewProperty(false, true);
12272 
12273             invalidateParentIfNeededAndWasQuickRejected();
12274         }
12275     }
12276 
12277     /**
12278      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12279      * completely transparent and 1 means the view is completely opaque.
12280      *
12281      * <p>By default this is 1.0f.
12282      * @return The opacity of the view.
12283      */
12284     @ViewDebug.ExportedProperty(category = "drawing")
getAlpha()12285     public float getAlpha() {
12286         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12287     }
12288 
12289     /**
12290      * Sets the behavior for overlapping rendering for this view (see {@link
12291      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12292      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12293      * providing the value which is then used internally. That is, when {@link
12294      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12295      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12296      * instead.
12297      *
12298      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12299      * instead of that returned by {@link #hasOverlappingRendering()}.
12300      *
12301      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12302      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)12303     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12304         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12305         if (hasOverlappingRendering) {
12306             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12307         } else {
12308             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12309         }
12310     }
12311 
12312     /**
12313      * Returns the value for overlapping rendering that is used internally. This is either
12314      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12315      * the return value of {@link #hasOverlappingRendering()}, otherwise.
12316      *
12317      * @return The value for overlapping rendering being used internally.
12318      */
getHasOverlappingRendering()12319     public final boolean getHasOverlappingRendering() {
12320         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12321                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12322                 hasOverlappingRendering();
12323     }
12324 
12325     /**
12326      * Returns whether this View has content which overlaps.
12327      *
12328      * <p>This function, intended to be overridden by specific View types, is an optimization when
12329      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12330      * an offscreen buffer and then composited into place, which can be expensive. If the view has
12331      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12332      * directly. An example of overlapping rendering is a TextView with a background image, such as
12333      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12334      * ImageView with only the foreground image. The default implementation returns true; subclasses
12335      * should override if they have cases which can be optimized.</p>
12336      *
12337      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12338      * necessitates that a View return true if it uses the methods internally without passing the
12339      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12340      *
12341      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12342      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12343      *
12344      * @return true if the content in this view might overlap, false otherwise.
12345      */
12346     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()12347     public boolean hasOverlappingRendering() {
12348         return true;
12349     }
12350 
12351     /**
12352      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12353      * completely transparent and 1 means the view is completely opaque.
12354      *
12355      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12356      * can have significant performance implications, especially for large views. It is best to use
12357      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12358      *
12359      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12360      * strongly recommended for performance reasons to either override
12361      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12362      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12363      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12364      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12365      * of rendering cost, even for simple or small views. Starting with
12366      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12367      * applied to the view at the rendering level.</p>
12368      *
12369      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12370      * responsible for applying the opacity itself.</p>
12371      *
12372      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12373      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12374      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12375      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12376      *
12377      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12378      * value will clip a View to its bounds, unless the View returns <code>false</code> from
12379      * {@link #hasOverlappingRendering}.</p>
12380      *
12381      * @param alpha The opacity of the view.
12382      *
12383      * @see #hasOverlappingRendering()
12384      * @see #setLayerType(int, android.graphics.Paint)
12385      *
12386      * @attr ref android.R.styleable#View_alpha
12387      */
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)12388     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12389         ensureTransformationInfo();
12390         if (mTransformationInfo.mAlpha != alpha) {
12391             // Report visibility changes, which can affect children, to accessibility
12392             if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12393                 notifySubtreeAccessibilityStateChangedIfNeeded();
12394             }
12395             mTransformationInfo.mAlpha = alpha;
12396             if (onSetAlpha((int) (alpha * 255))) {
12397                 mPrivateFlags |= PFLAG_ALPHA_SET;
12398                 // subclass is handling alpha - don't optimize rendering cache invalidation
12399                 invalidateParentCaches();
12400                 invalidate(true);
12401             } else {
12402                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12403                 invalidateViewProperty(true, false);
12404                 mRenderNode.setAlpha(getFinalAlpha());
12405             }
12406         }
12407     }
12408 
12409     /**
12410      * Faster version of setAlpha() which performs the same steps except there are
12411      * no calls to invalidate(). The caller of this function should perform proper invalidation
12412      * on the parent and this object. The return value indicates whether the subclass handles
12413      * alpha (the return value for onSetAlpha()).
12414      *
12415      * @param alpha The new value for the alpha property
12416      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12417      *         the new value for the alpha property is different from the old value
12418      */
setAlphaNoInvalidation(float alpha)12419     boolean setAlphaNoInvalidation(float alpha) {
12420         ensureTransformationInfo();
12421         if (mTransformationInfo.mAlpha != alpha) {
12422             mTransformationInfo.mAlpha = alpha;
12423             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12424             if (subclassHandlesAlpha) {
12425                 mPrivateFlags |= PFLAG_ALPHA_SET;
12426                 return true;
12427             } else {
12428                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12429                 mRenderNode.setAlpha(getFinalAlpha());
12430             }
12431         }
12432         return false;
12433     }
12434 
12435     /**
12436      * This property is hidden and intended only for use by the Fade transition, which
12437      * animates it to produce a visual translucency that does not side-effect (or get
12438      * affected by) the real alpha property. This value is composited with the other
12439      * alpha value (and the AlphaAnimation value, when that is present) to produce
12440      * a final visual translucency result, which is what is passed into the DisplayList.
12441      *
12442      * @hide
12443      */
setTransitionAlpha(float alpha)12444     public void setTransitionAlpha(float alpha) {
12445         ensureTransformationInfo();
12446         if (mTransformationInfo.mTransitionAlpha != alpha) {
12447             mTransformationInfo.mTransitionAlpha = alpha;
12448             mPrivateFlags &= ~PFLAG_ALPHA_SET;
12449             invalidateViewProperty(true, false);
12450             mRenderNode.setAlpha(getFinalAlpha());
12451         }
12452     }
12453 
12454     /**
12455      * Calculates the visual alpha of this view, which is a combination of the actual
12456      * alpha value and the transitionAlpha value (if set).
12457      */
getFinalAlpha()12458     private float getFinalAlpha() {
12459         if (mTransformationInfo != null) {
12460             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12461         }
12462         return 1;
12463     }
12464 
12465     /**
12466      * This property is hidden and intended only for use by the Fade transition, which
12467      * animates it to produce a visual translucency that does not side-effect (or get
12468      * affected by) the real alpha property. This value is composited with the other
12469      * alpha value (and the AlphaAnimation value, when that is present) to produce
12470      * a final visual translucency result, which is what is passed into the DisplayList.
12471      *
12472      * @hide
12473      */
12474     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()12475     public float getTransitionAlpha() {
12476         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12477     }
12478 
12479     /**
12480      * Top position of this view relative to its parent.
12481      *
12482      * @return The top of this view, in pixels.
12483      */
12484     @ViewDebug.CapturedViewProperty
getTop()12485     public final int getTop() {
12486         return mTop;
12487     }
12488 
12489     /**
12490      * Sets the top position of this view relative to its parent. This method is meant to be called
12491      * by the layout system and should not generally be called otherwise, because the property
12492      * may be changed at any time by the layout.
12493      *
12494      * @param top The top of this view, in pixels.
12495      */
setTop(int top)12496     public final void setTop(int top) {
12497         if (top != mTop) {
12498             final boolean matrixIsIdentity = hasIdentityMatrix();
12499             if (matrixIsIdentity) {
12500                 if (mAttachInfo != null) {
12501                     int minTop;
12502                     int yLoc;
12503                     if (top < mTop) {
12504                         minTop = top;
12505                         yLoc = top - mTop;
12506                     } else {
12507                         minTop = mTop;
12508                         yLoc = 0;
12509                     }
12510                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12511                 }
12512             } else {
12513                 // Double-invalidation is necessary to capture view's old and new areas
12514                 invalidate(true);
12515             }
12516 
12517             int width = mRight - mLeft;
12518             int oldHeight = mBottom - mTop;
12519 
12520             mTop = top;
12521             mRenderNode.setTop(mTop);
12522 
12523             sizeChange(width, mBottom - mTop, width, oldHeight);
12524 
12525             if (!matrixIsIdentity) {
12526                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12527                 invalidate(true);
12528             }
12529             mBackgroundSizeChanged = true;
12530             if (mForegroundInfo != null) {
12531                 mForegroundInfo.mBoundsChanged = true;
12532             }
12533             invalidateParentIfNeeded();
12534             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12535                 // View was rejected last time it was drawn by its parent; this may have changed
12536                 invalidateParentIfNeeded();
12537             }
12538         }
12539     }
12540 
12541     /**
12542      * Bottom position of this view relative to its parent.
12543      *
12544      * @return The bottom of this view, in pixels.
12545      */
12546     @ViewDebug.CapturedViewProperty
getBottom()12547     public final int getBottom() {
12548         return mBottom;
12549     }
12550 
12551     /**
12552      * True if this view has changed since the last time being drawn.
12553      *
12554      * @return The dirty state of this view.
12555      */
isDirty()12556     public boolean isDirty() {
12557         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12558     }
12559 
12560     /**
12561      * Sets the bottom position of this view relative to its parent. This method is meant to be
12562      * called by the layout system and should not generally be called otherwise, because the
12563      * property may be changed at any time by the layout.
12564      *
12565      * @param bottom The bottom of this view, in pixels.
12566      */
setBottom(int bottom)12567     public final void setBottom(int bottom) {
12568         if (bottom != mBottom) {
12569             final boolean matrixIsIdentity = hasIdentityMatrix();
12570             if (matrixIsIdentity) {
12571                 if (mAttachInfo != null) {
12572                     int maxBottom;
12573                     if (bottom < mBottom) {
12574                         maxBottom = mBottom;
12575                     } else {
12576                         maxBottom = bottom;
12577                     }
12578                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12579                 }
12580             } else {
12581                 // Double-invalidation is necessary to capture view's old and new areas
12582                 invalidate(true);
12583             }
12584 
12585             int width = mRight - mLeft;
12586             int oldHeight = mBottom - mTop;
12587 
12588             mBottom = bottom;
12589             mRenderNode.setBottom(mBottom);
12590 
12591             sizeChange(width, mBottom - mTop, width, oldHeight);
12592 
12593             if (!matrixIsIdentity) {
12594                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12595                 invalidate(true);
12596             }
12597             mBackgroundSizeChanged = true;
12598             if (mForegroundInfo != null) {
12599                 mForegroundInfo.mBoundsChanged = true;
12600             }
12601             invalidateParentIfNeeded();
12602             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12603                 // View was rejected last time it was drawn by its parent; this may have changed
12604                 invalidateParentIfNeeded();
12605             }
12606         }
12607     }
12608 
12609     /**
12610      * Left position of this view relative to its parent.
12611      *
12612      * @return The left edge of this view, in pixels.
12613      */
12614     @ViewDebug.CapturedViewProperty
getLeft()12615     public final int getLeft() {
12616         return mLeft;
12617     }
12618 
12619     /**
12620      * Sets the left position of this view relative to its parent. This method is meant to be called
12621      * by the layout system and should not generally be called otherwise, because the property
12622      * may be changed at any time by the layout.
12623      *
12624      * @param left The left of this view, in pixels.
12625      */
setLeft(int left)12626     public final void setLeft(int left) {
12627         if (left != mLeft) {
12628             final boolean matrixIsIdentity = hasIdentityMatrix();
12629             if (matrixIsIdentity) {
12630                 if (mAttachInfo != null) {
12631                     int minLeft;
12632                     int xLoc;
12633                     if (left < mLeft) {
12634                         minLeft = left;
12635                         xLoc = left - mLeft;
12636                     } else {
12637                         minLeft = mLeft;
12638                         xLoc = 0;
12639                     }
12640                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12641                 }
12642             } else {
12643                 // Double-invalidation is necessary to capture view's old and new areas
12644                 invalidate(true);
12645             }
12646 
12647             int oldWidth = mRight - mLeft;
12648             int height = mBottom - mTop;
12649 
12650             mLeft = left;
12651             mRenderNode.setLeft(left);
12652 
12653             sizeChange(mRight - mLeft, height, oldWidth, height);
12654 
12655             if (!matrixIsIdentity) {
12656                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12657                 invalidate(true);
12658             }
12659             mBackgroundSizeChanged = true;
12660             if (mForegroundInfo != null) {
12661                 mForegroundInfo.mBoundsChanged = true;
12662             }
12663             invalidateParentIfNeeded();
12664             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12665                 // View was rejected last time it was drawn by its parent; this may have changed
12666                 invalidateParentIfNeeded();
12667             }
12668         }
12669     }
12670 
12671     /**
12672      * Right position of this view relative to its parent.
12673      *
12674      * @return The right edge of this view, in pixels.
12675      */
12676     @ViewDebug.CapturedViewProperty
getRight()12677     public final int getRight() {
12678         return mRight;
12679     }
12680 
12681     /**
12682      * Sets the right position of this view relative to its parent. This method is meant to be called
12683      * by the layout system and should not generally be called otherwise, because the property
12684      * may be changed at any time by the layout.
12685      *
12686      * @param right The right of this view, in pixels.
12687      */
setRight(int right)12688     public final void setRight(int right) {
12689         if (right != mRight) {
12690             final boolean matrixIsIdentity = hasIdentityMatrix();
12691             if (matrixIsIdentity) {
12692                 if (mAttachInfo != null) {
12693                     int maxRight;
12694                     if (right < mRight) {
12695                         maxRight = mRight;
12696                     } else {
12697                         maxRight = right;
12698                     }
12699                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12700                 }
12701             } else {
12702                 // Double-invalidation is necessary to capture view's old and new areas
12703                 invalidate(true);
12704             }
12705 
12706             int oldWidth = mRight - mLeft;
12707             int height = mBottom - mTop;
12708 
12709             mRight = right;
12710             mRenderNode.setRight(mRight);
12711 
12712             sizeChange(mRight - mLeft, height, oldWidth, height);
12713 
12714             if (!matrixIsIdentity) {
12715                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12716                 invalidate(true);
12717             }
12718             mBackgroundSizeChanged = true;
12719             if (mForegroundInfo != null) {
12720                 mForegroundInfo.mBoundsChanged = true;
12721             }
12722             invalidateParentIfNeeded();
12723             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12724                 // View was rejected last time it was drawn by its parent; this may have changed
12725                 invalidateParentIfNeeded();
12726             }
12727         }
12728     }
12729 
12730     /**
12731      * The visual x position of this view, in pixels. This is equivalent to the
12732      * {@link #setTranslationX(float) translationX} property plus the current
12733      * {@link #getLeft() left} property.
12734      *
12735      * @return The visual x position of this view, in pixels.
12736      */
12737     @ViewDebug.ExportedProperty(category = "drawing")
getX()12738     public float getX() {
12739         return mLeft + getTranslationX();
12740     }
12741 
12742     /**
12743      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12744      * {@link #setTranslationX(float) translationX} property to be the difference between
12745      * the x value passed in and the current {@link #getLeft() left} property.
12746      *
12747      * @param x The visual x position of this view, in pixels.
12748      */
setX(float x)12749     public void setX(float x) {
12750         setTranslationX(x - mLeft);
12751     }
12752 
12753     /**
12754      * The visual y position of this view, in pixels. This is equivalent to the
12755      * {@link #setTranslationY(float) translationY} property plus the current
12756      * {@link #getTop() top} property.
12757      *
12758      * @return The visual y position of this view, in pixels.
12759      */
12760     @ViewDebug.ExportedProperty(category = "drawing")
getY()12761     public float getY() {
12762         return mTop + getTranslationY();
12763     }
12764 
12765     /**
12766      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12767      * {@link #setTranslationY(float) translationY} property to be the difference between
12768      * the y value passed in and the current {@link #getTop() top} property.
12769      *
12770      * @param y The visual y position of this view, in pixels.
12771      */
setY(float y)12772     public void setY(float y) {
12773         setTranslationY(y - mTop);
12774     }
12775 
12776     /**
12777      * The visual z position of this view, in pixels. This is equivalent to the
12778      * {@link #setTranslationZ(float) translationZ} property plus the current
12779      * {@link #getElevation() elevation} property.
12780      *
12781      * @return The visual z position of this view, in pixels.
12782      */
12783     @ViewDebug.ExportedProperty(category = "drawing")
getZ()12784     public float getZ() {
12785         return getElevation() + getTranslationZ();
12786     }
12787 
12788     /**
12789      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12790      * {@link #setTranslationZ(float) translationZ} property to be the difference between
12791      * the x value passed in and the current {@link #getElevation() elevation} property.
12792      *
12793      * @param z The visual z position of this view, in pixels.
12794      */
setZ(float z)12795     public void setZ(float z) {
12796         setTranslationZ(z - getElevation());
12797     }
12798 
12799     /**
12800      * The base elevation of this view relative to its parent, in pixels.
12801      *
12802      * @return The base depth position of the view, in pixels.
12803      */
12804     @ViewDebug.ExportedProperty(category = "drawing")
getElevation()12805     public float getElevation() {
12806         return mRenderNode.getElevation();
12807     }
12808 
12809     /**
12810      * Sets the base elevation of this view, in pixels.
12811      *
12812      * @attr ref android.R.styleable#View_elevation
12813      */
setElevation(float elevation)12814     public void setElevation(float elevation) {
12815         if (elevation != getElevation()) {
12816             invalidateViewProperty(true, false);
12817             mRenderNode.setElevation(elevation);
12818             invalidateViewProperty(false, true);
12819 
12820             invalidateParentIfNeededAndWasQuickRejected();
12821         }
12822     }
12823 
12824     /**
12825      * The horizontal location of this view relative to its {@link #getLeft() left} position.
12826      * This position is post-layout, in addition to wherever the object's
12827      * layout placed it.
12828      *
12829      * @return The horizontal position of this view relative to its left position, in pixels.
12830      */
12831     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationX()12832     public float getTranslationX() {
12833         return mRenderNode.getTranslationX();
12834     }
12835 
12836     /**
12837      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12838      * This effectively positions the object post-layout, in addition to wherever the object's
12839      * layout placed it.
12840      *
12841      * @param translationX The horizontal position of this view relative to its left position,
12842      * in pixels.
12843      *
12844      * @attr ref android.R.styleable#View_translationX
12845      */
setTranslationX(float translationX)12846     public void setTranslationX(float translationX) {
12847         if (translationX != getTranslationX()) {
12848             invalidateViewProperty(true, false);
12849             mRenderNode.setTranslationX(translationX);
12850             invalidateViewProperty(false, true);
12851 
12852             invalidateParentIfNeededAndWasQuickRejected();
12853             notifySubtreeAccessibilityStateChangedIfNeeded();
12854         }
12855     }
12856 
12857     /**
12858      * The vertical location of this view relative to its {@link #getTop() top} position.
12859      * This position is post-layout, in addition to wherever the object's
12860      * layout placed it.
12861      *
12862      * @return The vertical position of this view relative to its top position,
12863      * in pixels.
12864      */
12865     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationY()12866     public float getTranslationY() {
12867         return mRenderNode.getTranslationY();
12868     }
12869 
12870     /**
12871      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12872      * This effectively positions the object post-layout, in addition to wherever the object's
12873      * layout placed it.
12874      *
12875      * @param translationY The vertical position of this view relative to its top position,
12876      * in pixels.
12877      *
12878      * @attr ref android.R.styleable#View_translationY
12879      */
setTranslationY(float translationY)12880     public void setTranslationY(float translationY) {
12881         if (translationY != getTranslationY()) {
12882             invalidateViewProperty(true, false);
12883             mRenderNode.setTranslationY(translationY);
12884             invalidateViewProperty(false, true);
12885 
12886             invalidateParentIfNeededAndWasQuickRejected();
12887             notifySubtreeAccessibilityStateChangedIfNeeded();
12888         }
12889     }
12890 
12891     /**
12892      * The depth location of this view relative to its {@link #getElevation() elevation}.
12893      *
12894      * @return The depth of this view relative to its elevation.
12895      */
12896     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationZ()12897     public float getTranslationZ() {
12898         return mRenderNode.getTranslationZ();
12899     }
12900 
12901     /**
12902      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12903      *
12904      * @attr ref android.R.styleable#View_translationZ
12905      */
setTranslationZ(float translationZ)12906     public void setTranslationZ(float translationZ) {
12907         if (translationZ != getTranslationZ()) {
12908             invalidateViewProperty(true, false);
12909             mRenderNode.setTranslationZ(translationZ);
12910             invalidateViewProperty(false, true);
12911 
12912             invalidateParentIfNeededAndWasQuickRejected();
12913         }
12914     }
12915 
12916     /** @hide */
setAnimationMatrix(Matrix matrix)12917     public void setAnimationMatrix(Matrix matrix) {
12918         invalidateViewProperty(true, false);
12919         mRenderNode.setAnimationMatrix(matrix);
12920         invalidateViewProperty(false, true);
12921 
12922         invalidateParentIfNeededAndWasQuickRejected();
12923     }
12924 
12925     /**
12926      * Returns the current StateListAnimator if exists.
12927      *
12928      * @return StateListAnimator or null if it does not exists
12929      * @see    #setStateListAnimator(android.animation.StateListAnimator)
12930      */
getStateListAnimator()12931     public StateListAnimator getStateListAnimator() {
12932         return mStateListAnimator;
12933     }
12934 
12935     /**
12936      * Attaches the provided StateListAnimator to this View.
12937      * <p>
12938      * Any previously attached StateListAnimator will be detached.
12939      *
12940      * @param stateListAnimator The StateListAnimator to update the view
12941      * @see {@link android.animation.StateListAnimator}
12942      */
setStateListAnimator(StateListAnimator stateListAnimator)12943     public void setStateListAnimator(StateListAnimator stateListAnimator) {
12944         if (mStateListAnimator == stateListAnimator) {
12945             return;
12946         }
12947         if (mStateListAnimator != null) {
12948             mStateListAnimator.setTarget(null);
12949         }
12950         mStateListAnimator = stateListAnimator;
12951         if (stateListAnimator != null) {
12952             stateListAnimator.setTarget(this);
12953             if (isAttachedToWindow()) {
12954                 stateListAnimator.setState(getDrawableState());
12955             }
12956         }
12957     }
12958 
12959     /**
12960      * Returns whether the Outline should be used to clip the contents of the View.
12961      * <p>
12962      * Note that this flag will only be respected if the View's Outline returns true from
12963      * {@link Outline#canClip()}.
12964      *
12965      * @see #setOutlineProvider(ViewOutlineProvider)
12966      * @see #setClipToOutline(boolean)
12967      */
getClipToOutline()12968     public final boolean getClipToOutline() {
12969         return mRenderNode.getClipToOutline();
12970     }
12971 
12972     /**
12973      * Sets whether the View's Outline should be used to clip the contents of the View.
12974      * <p>
12975      * Only a single non-rectangular clip can be applied on a View at any time.
12976      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12977      * circular reveal} animation take priority over Outline clipping, and
12978      * child Outline clipping takes priority over Outline clipping done by a
12979      * parent.
12980      * <p>
12981      * Note that this flag will only be respected if the View's Outline returns true from
12982      * {@link Outline#canClip()}.
12983      *
12984      * @see #setOutlineProvider(ViewOutlineProvider)
12985      * @see #getClipToOutline()
12986      */
setClipToOutline(boolean clipToOutline)12987     public void setClipToOutline(boolean clipToOutline) {
12988         damageInParent();
12989         if (getClipToOutline() != clipToOutline) {
12990             mRenderNode.setClipToOutline(clipToOutline);
12991         }
12992     }
12993 
12994     // correspond to the enum values of View_outlineProvider
12995     private static final int PROVIDER_BACKGROUND = 0;
12996     private static final int PROVIDER_NONE = 1;
12997     private static final int PROVIDER_BOUNDS = 2;
12998     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)12999     private void setOutlineProviderFromAttribute(int providerInt) {
13000         switch (providerInt) {
13001             case PROVIDER_BACKGROUND:
13002                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13003                 break;
13004             case PROVIDER_NONE:
13005                 setOutlineProvider(null);
13006                 break;
13007             case PROVIDER_BOUNDS:
13008                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
13009                 break;
13010             case PROVIDER_PADDED_BOUNDS:
13011                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13012                 break;
13013         }
13014     }
13015 
13016     /**
13017      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13018      * the shape of the shadow it casts, and enables outline clipping.
13019      * <p>
13020      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13021      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13022      * outline provider with this method allows this behavior to be overridden.
13023      * <p>
13024      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13025      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13026      * <p>
13027      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13028      *
13029      * @see #setClipToOutline(boolean)
13030      * @see #getClipToOutline()
13031      * @see #getOutlineProvider()
13032      */
setOutlineProvider(ViewOutlineProvider provider)13033     public void setOutlineProvider(ViewOutlineProvider provider) {
13034         mOutlineProvider = provider;
13035         invalidateOutline();
13036     }
13037 
13038     /**
13039      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13040      * that defines the shape of the shadow it casts, and enables outline clipping.
13041      *
13042      * @see #setOutlineProvider(ViewOutlineProvider)
13043      */
getOutlineProvider()13044     public ViewOutlineProvider getOutlineProvider() {
13045         return mOutlineProvider;
13046     }
13047 
13048     /**
13049      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13050      *
13051      * @see #setOutlineProvider(ViewOutlineProvider)
13052      */
invalidateOutline()13053     public void invalidateOutline() {
13054         rebuildOutline();
13055 
13056         notifySubtreeAccessibilityStateChangedIfNeeded();
13057         invalidateViewProperty(false, false);
13058     }
13059 
13060     /**
13061      * Internal version of {@link #invalidateOutline()} which invalidates the
13062      * outline without invalidating the view itself. This is intended to be called from
13063      * within methods in the View class itself which are the result of the view being
13064      * invalidated already. For example, when we are drawing the background of a View,
13065      * we invalidate the outline in case it changed in the meantime, but we do not
13066      * need to invalidate the view because we're already drawing the background as part
13067      * of drawing the view in response to an earlier invalidation of the view.
13068      */
rebuildOutline()13069     private void rebuildOutline() {
13070         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13071         if (mAttachInfo == null) return;
13072 
13073         if (mOutlineProvider == null) {
13074             // no provider, remove outline
13075             mRenderNode.setOutline(null);
13076         } else {
13077             final Outline outline = mAttachInfo.mTmpOutline;
13078             outline.setEmpty();
13079             outline.setAlpha(1.0f);
13080 
13081             mOutlineProvider.getOutline(this, outline);
13082             mRenderNode.setOutline(outline);
13083         }
13084     }
13085 
13086     /**
13087      * HierarchyViewer only
13088      *
13089      * @hide
13090      */
13091     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()13092     public boolean hasShadow() {
13093         return mRenderNode.hasShadow();
13094     }
13095 
13096 
13097     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)13098     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13099         mRenderNode.setRevealClip(shouldClip, x, y, radius);
13100         invalidateViewProperty(false, false);
13101     }
13102 
13103     /**
13104      * Hit rectangle in parent's coordinates
13105      *
13106      * @param outRect The hit rectangle of the view.
13107      */
getHitRect(Rect outRect)13108     public void getHitRect(Rect outRect) {
13109         if (hasIdentityMatrix() || mAttachInfo == null) {
13110             outRect.set(mLeft, mTop, mRight, mBottom);
13111         } else {
13112             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13113             tmpRect.set(0, 0, getWidth(), getHeight());
13114             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13115             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13116                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13117         }
13118     }
13119 
13120     /**
13121      * Determines whether the given point, in local coordinates is inside the view.
13122      */
pointInView(float localX, float localY)13123     /*package*/ final boolean pointInView(float localX, float localY) {
13124         return pointInView(localX, localY, 0);
13125     }
13126 
13127     /**
13128      * Utility method to determine whether the given point, in local coordinates,
13129      * is inside the view, where the area of the view is expanded by the slop factor.
13130      * This method is called while processing touch-move events to determine if the event
13131      * is still within the view.
13132      *
13133      * @hide
13134      */
pointInView(float localX, float localY, float slop)13135     public boolean pointInView(float localX, float localY, float slop) {
13136         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13137                 localY < ((mBottom - mTop) + slop);
13138     }
13139 
13140     /**
13141      * When a view has focus and the user navigates away from it, the next view is searched for
13142      * starting from the rectangle filled in by this method.
13143      *
13144      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13145      * of the view.  However, if your view maintains some idea of internal selection,
13146      * such as a cursor, or a selected row or column, you should override this method and
13147      * fill in a more specific rectangle.
13148      *
13149      * @param r The rectangle to fill in, in this view's coordinates.
13150      */
getFocusedRect(Rect r)13151     public void getFocusedRect(Rect r) {
13152         getDrawingRect(r);
13153     }
13154 
13155     /**
13156      * If some part of this view is not clipped by any of its parents, then
13157      * return that area in r in global (root) coordinates. To convert r to local
13158      * coordinates (without taking possible View rotations into account), offset
13159      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13160      * If the view is completely clipped or translated out, return false.
13161      *
13162      * @param r If true is returned, r holds the global coordinates of the
13163      *        visible portion of this view.
13164      * @param globalOffset If true is returned, globalOffset holds the dx,dy
13165      *        between this view and its root. globalOffet may be null.
13166      * @return true if r is non-empty (i.e. part of the view is visible at the
13167      *         root level.
13168      */
getGlobalVisibleRect(Rect r, Point globalOffset)13169     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13170         int width = mRight - mLeft;
13171         int height = mBottom - mTop;
13172         if (width > 0 && height > 0) {
13173             r.set(0, 0, width, height);
13174             if (globalOffset != null) {
13175                 globalOffset.set(-mScrollX, -mScrollY);
13176             }
13177             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13178         }
13179         return false;
13180     }
13181 
getGlobalVisibleRect(Rect r)13182     public final boolean getGlobalVisibleRect(Rect r) {
13183         return getGlobalVisibleRect(r, null);
13184     }
13185 
getLocalVisibleRect(Rect r)13186     public final boolean getLocalVisibleRect(Rect r) {
13187         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13188         if (getGlobalVisibleRect(r, offset)) {
13189             r.offset(-offset.x, -offset.y); // make r local
13190             return true;
13191         }
13192         return false;
13193     }
13194 
13195     /**
13196      * Offset this view's vertical location by the specified number of pixels.
13197      *
13198      * @param offset the number of pixels to offset the view by
13199      */
offsetTopAndBottom(int offset)13200     public void offsetTopAndBottom(int offset) {
13201         if (offset != 0) {
13202             final boolean matrixIsIdentity = hasIdentityMatrix();
13203             if (matrixIsIdentity) {
13204                 if (isHardwareAccelerated()) {
13205                     invalidateViewProperty(false, false);
13206                 } else {
13207                     final ViewParent p = mParent;
13208                     if (p != null && mAttachInfo != null) {
13209                         final Rect r = mAttachInfo.mTmpInvalRect;
13210                         int minTop;
13211                         int maxBottom;
13212                         int yLoc;
13213                         if (offset < 0) {
13214                             minTop = mTop + offset;
13215                             maxBottom = mBottom;
13216                             yLoc = offset;
13217                         } else {
13218                             minTop = mTop;
13219                             maxBottom = mBottom + offset;
13220                             yLoc = 0;
13221                         }
13222                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13223                         p.invalidateChild(this, r);
13224                     }
13225                 }
13226             } else {
13227                 invalidateViewProperty(false, false);
13228             }
13229 
13230             mTop += offset;
13231             mBottom += offset;
13232             mRenderNode.offsetTopAndBottom(offset);
13233             if (isHardwareAccelerated()) {
13234                 invalidateViewProperty(false, false);
13235                 invalidateParentIfNeededAndWasQuickRejected();
13236             } else {
13237                 if (!matrixIsIdentity) {
13238                     invalidateViewProperty(false, true);
13239                 }
13240                 invalidateParentIfNeeded();
13241             }
13242             notifySubtreeAccessibilityStateChangedIfNeeded();
13243         }
13244     }
13245 
13246     /**
13247      * Offset this view's horizontal location by the specified amount of pixels.
13248      *
13249      * @param offset the number of pixels to offset the view by
13250      */
offsetLeftAndRight(int offset)13251     public void offsetLeftAndRight(int offset) {
13252         if (offset != 0) {
13253             final boolean matrixIsIdentity = hasIdentityMatrix();
13254             if (matrixIsIdentity) {
13255                 if (isHardwareAccelerated()) {
13256                     invalidateViewProperty(false, false);
13257                 } else {
13258                     final ViewParent p = mParent;
13259                     if (p != null && mAttachInfo != null) {
13260                         final Rect r = mAttachInfo.mTmpInvalRect;
13261                         int minLeft;
13262                         int maxRight;
13263                         if (offset < 0) {
13264                             minLeft = mLeft + offset;
13265                             maxRight = mRight;
13266                         } else {
13267                             minLeft = mLeft;
13268                             maxRight = mRight + offset;
13269                         }
13270                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13271                         p.invalidateChild(this, r);
13272                     }
13273                 }
13274             } else {
13275                 invalidateViewProperty(false, false);
13276             }
13277 
13278             mLeft += offset;
13279             mRight += offset;
13280             mRenderNode.offsetLeftAndRight(offset);
13281             if (isHardwareAccelerated()) {
13282                 invalidateViewProperty(false, false);
13283                 invalidateParentIfNeededAndWasQuickRejected();
13284             } else {
13285                 if (!matrixIsIdentity) {
13286                     invalidateViewProperty(false, true);
13287                 }
13288                 invalidateParentIfNeeded();
13289             }
13290             notifySubtreeAccessibilityStateChangedIfNeeded();
13291         }
13292     }
13293 
13294     /**
13295      * Get the LayoutParams associated with this view. All views should have
13296      * layout parameters. These supply parameters to the <i>parent</i> of this
13297      * view specifying how it should be arranged. There are many subclasses of
13298      * ViewGroup.LayoutParams, and these correspond to the different subclasses
13299      * of ViewGroup that are responsible for arranging their children.
13300      *
13301      * This method may return null if this View is not attached to a parent
13302      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13303      * was not invoked successfully. When a View is attached to a parent
13304      * ViewGroup, this method must not return null.
13305      *
13306      * @return The LayoutParams associated with this view, or null if no
13307      *         parameters have been set yet
13308      */
13309     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()13310     public ViewGroup.LayoutParams getLayoutParams() {
13311         return mLayoutParams;
13312     }
13313 
13314     /**
13315      * Set the layout parameters associated with this view. These supply
13316      * parameters to the <i>parent</i> of this view specifying how it should be
13317      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13318      * correspond to the different subclasses of ViewGroup that are responsible
13319      * for arranging their children.
13320      *
13321      * @param params The layout parameters for this view, cannot be null
13322      */
setLayoutParams(ViewGroup.LayoutParams params)13323     public void setLayoutParams(ViewGroup.LayoutParams params) {
13324         if (params == null) {
13325             throw new NullPointerException("Layout parameters cannot be null");
13326         }
13327         mLayoutParams = params;
13328         resolveLayoutParams();
13329         if (mParent instanceof ViewGroup) {
13330             ((ViewGroup) mParent).onSetLayoutParams(this, params);
13331         }
13332         requestLayout();
13333     }
13334 
13335     /**
13336      * Resolve the layout parameters depending on the resolved layout direction
13337      *
13338      * @hide
13339      */
resolveLayoutParams()13340     public void resolveLayoutParams() {
13341         if (mLayoutParams != null) {
13342             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13343         }
13344     }
13345 
13346     /**
13347      * Set the scrolled position of your view. This will cause a call to
13348      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13349      * invalidated.
13350      * @param x the x position to scroll to
13351      * @param y the y position to scroll to
13352      */
scrollTo(int x, int y)13353     public void scrollTo(int x, int y) {
13354         if (mScrollX != x || mScrollY != y) {
13355             int oldX = mScrollX;
13356             int oldY = mScrollY;
13357             mScrollX = x;
13358             mScrollY = y;
13359             invalidateParentCaches();
13360             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13361             if (!awakenScrollBars()) {
13362                 postInvalidateOnAnimation();
13363             }
13364         }
13365     }
13366 
13367     /**
13368      * Move the scrolled position of your view. This will cause a call to
13369      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13370      * invalidated.
13371      * @param x the amount of pixels to scroll by horizontally
13372      * @param y the amount of pixels to scroll by vertically
13373      */
scrollBy(int x, int y)13374     public void scrollBy(int x, int y) {
13375         scrollTo(mScrollX + x, mScrollY + y);
13376     }
13377 
13378     /**
13379      * <p>Trigger the scrollbars to draw. When invoked this method starts an
13380      * animation to fade the scrollbars out after a default delay. If a subclass
13381      * provides animated scrolling, the start delay should equal the duration
13382      * of the scrolling animation.</p>
13383      *
13384      * <p>The animation starts only if at least one of the scrollbars is
13385      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13386      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13387      * this method returns true, and false otherwise. If the animation is
13388      * started, this method calls {@link #invalidate()}; in that case the
13389      * caller should not call {@link #invalidate()}.</p>
13390      *
13391      * <p>This method should be invoked every time a subclass directly updates
13392      * the scroll parameters.</p>
13393      *
13394      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13395      * and {@link #scrollTo(int, int)}.</p>
13396      *
13397      * @return true if the animation is played, false otherwise
13398      *
13399      * @see #awakenScrollBars(int)
13400      * @see #scrollBy(int, int)
13401      * @see #scrollTo(int, int)
13402      * @see #isHorizontalScrollBarEnabled()
13403      * @see #isVerticalScrollBarEnabled()
13404      * @see #setHorizontalScrollBarEnabled(boolean)
13405      * @see #setVerticalScrollBarEnabled(boolean)
13406      */
awakenScrollBars()13407     protected boolean awakenScrollBars() {
13408         return mScrollCache != null &&
13409                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13410     }
13411 
13412     /**
13413      * Trigger the scrollbars to draw.
13414      * This method differs from awakenScrollBars() only in its default duration.
13415      * initialAwakenScrollBars() will show the scroll bars for longer than
13416      * usual to give the user more of a chance to notice them.
13417      *
13418      * @return true if the animation is played, false otherwise.
13419      */
initialAwakenScrollBars()13420     private boolean initialAwakenScrollBars() {
13421         return mScrollCache != null &&
13422                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13423     }
13424 
13425     /**
13426      * <p>
13427      * Trigger the scrollbars to draw. When invoked this method starts an
13428      * animation to fade the scrollbars out after a fixed delay. If a subclass
13429      * provides animated scrolling, the start delay should equal the duration of
13430      * the scrolling animation.
13431      * </p>
13432      *
13433      * <p>
13434      * The animation starts only if at least one of the scrollbars is enabled,
13435      * as specified by {@link #isHorizontalScrollBarEnabled()} and
13436      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13437      * this method returns true, and false otherwise. If the animation is
13438      * started, this method calls {@link #invalidate()}; in that case the caller
13439      * should not call {@link #invalidate()}.
13440      * </p>
13441      *
13442      * <p>
13443      * This method should be invoked every time a subclass directly updates the
13444      * scroll parameters.
13445      * </p>
13446      *
13447      * @param startDelay the delay, in milliseconds, after which the animation
13448      *        should start; when the delay is 0, the animation starts
13449      *        immediately
13450      * @return true if the animation is played, false otherwise
13451      *
13452      * @see #scrollBy(int, int)
13453      * @see #scrollTo(int, int)
13454      * @see #isHorizontalScrollBarEnabled()
13455      * @see #isVerticalScrollBarEnabled()
13456      * @see #setHorizontalScrollBarEnabled(boolean)
13457      * @see #setVerticalScrollBarEnabled(boolean)
13458      */
awakenScrollBars(int startDelay)13459     protected boolean awakenScrollBars(int startDelay) {
13460         return awakenScrollBars(startDelay, true);
13461     }
13462 
13463     /**
13464      * <p>
13465      * Trigger the scrollbars to draw. When invoked this method starts an
13466      * animation to fade the scrollbars out after a fixed delay. If a subclass
13467      * provides animated scrolling, the start delay should equal the duration of
13468      * the scrolling animation.
13469      * </p>
13470      *
13471      * <p>
13472      * The animation starts only if at least one of the scrollbars is enabled,
13473      * as specified by {@link #isHorizontalScrollBarEnabled()} and
13474      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13475      * this method returns true, and false otherwise. If the animation is
13476      * started, this method calls {@link #invalidate()} if the invalidate parameter
13477      * is set to true; in that case the caller
13478      * should not call {@link #invalidate()}.
13479      * </p>
13480      *
13481      * <p>
13482      * This method should be invoked every time a subclass directly updates the
13483      * scroll parameters.
13484      * </p>
13485      *
13486      * @param startDelay the delay, in milliseconds, after which the animation
13487      *        should start; when the delay is 0, the animation starts
13488      *        immediately
13489      *
13490      * @param invalidate Whether this method should call invalidate
13491      *
13492      * @return true if the animation is played, false otherwise
13493      *
13494      * @see #scrollBy(int, int)
13495      * @see #scrollTo(int, int)
13496      * @see #isHorizontalScrollBarEnabled()
13497      * @see #isVerticalScrollBarEnabled()
13498      * @see #setHorizontalScrollBarEnabled(boolean)
13499      * @see #setVerticalScrollBarEnabled(boolean)
13500      */
awakenScrollBars(int startDelay, boolean invalidate)13501     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13502         final ScrollabilityCache scrollCache = mScrollCache;
13503 
13504         if (scrollCache == null || !scrollCache.fadeScrollBars) {
13505             return false;
13506         }
13507 
13508         if (scrollCache.scrollBar == null) {
13509             scrollCache.scrollBar = new ScrollBarDrawable();
13510             scrollCache.scrollBar.setState(getDrawableState());
13511             scrollCache.scrollBar.setCallback(this);
13512         }
13513 
13514         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13515 
13516             if (invalidate) {
13517                 // Invalidate to show the scrollbars
13518                 postInvalidateOnAnimation();
13519             }
13520 
13521             if (scrollCache.state == ScrollabilityCache.OFF) {
13522                 // FIXME: this is copied from WindowManagerService.
13523                 // We should get this value from the system when it
13524                 // is possible to do so.
13525                 final int KEY_REPEAT_FIRST_DELAY = 750;
13526                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13527             }
13528 
13529             // Tell mScrollCache when we should start fading. This may
13530             // extend the fade start time if one was already scheduled
13531             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13532             scrollCache.fadeStartTime = fadeStartTime;
13533             scrollCache.state = ScrollabilityCache.ON;
13534 
13535             // Schedule our fader to run, unscheduling any old ones first
13536             if (mAttachInfo != null) {
13537                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
13538                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13539             }
13540 
13541             return true;
13542         }
13543 
13544         return false;
13545     }
13546 
13547     /**
13548      * Do not invalidate views which are not visible and which are not running an animation. They
13549      * will not get drawn and they should not set dirty flags as if they will be drawn
13550      */
skipInvalidate()13551     private boolean skipInvalidate() {
13552         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13553                 (!(mParent instanceof ViewGroup) ||
13554                         !((ViewGroup) mParent).isViewTransitioning(this));
13555     }
13556 
13557     /**
13558      * Mark the area defined by dirty as needing to be drawn. If the view is
13559      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13560      * point in the future.
13561      * <p>
13562      * This must be called from a UI thread. To call from a non-UI thread, call
13563      * {@link #postInvalidate()}.
13564      * <p>
13565      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13566      * {@code dirty}.
13567      *
13568      * @param dirty the rectangle representing the bounds of the dirty region
13569      */
invalidate(Rect dirty)13570     public void invalidate(Rect dirty) {
13571         final int scrollX = mScrollX;
13572         final int scrollY = mScrollY;
13573         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13574                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13575     }
13576 
13577     /**
13578      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13579      * coordinates of the dirty rect are relative to the view. If the view is
13580      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13581      * point in the future.
13582      * <p>
13583      * This must be called from a UI thread. To call from a non-UI thread, call
13584      * {@link #postInvalidate()}.
13585      *
13586      * @param l the left position of the dirty region
13587      * @param t the top position of the dirty region
13588      * @param r the right position of the dirty region
13589      * @param b the bottom position of the dirty region
13590      */
invalidate(int l, int t, int r, int b)13591     public void invalidate(int l, int t, int r, int b) {
13592         final int scrollX = mScrollX;
13593         final int scrollY = mScrollY;
13594         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13595     }
13596 
13597     /**
13598      * Invalidate the whole view. If the view is visible,
13599      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13600      * the future.
13601      * <p>
13602      * This must be called from a UI thread. To call from a non-UI thread, call
13603      * {@link #postInvalidate()}.
13604      */
invalidate()13605     public void invalidate() {
13606         invalidate(true);
13607     }
13608 
13609     /**
13610      * This is where the invalidate() work actually happens. A full invalidate()
13611      * causes the drawing cache to be invalidated, but this function can be
13612      * called with invalidateCache set to false to skip that invalidation step
13613      * for cases that do not need it (for example, a component that remains at
13614      * the same dimensions with the same content).
13615      *
13616      * @param invalidateCache Whether the drawing cache for this view should be
13617      *            invalidated as well. This is usually true for a full
13618      *            invalidate, but may be set to false if the View's contents or
13619      *            dimensions have not changed.
13620      */
invalidate(boolean invalidateCache)13621     void invalidate(boolean invalidateCache) {
13622         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13623     }
13624 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)13625     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13626             boolean fullInvalidate) {
13627         if (mGhostView != null) {
13628             mGhostView.invalidate(true);
13629             return;
13630         }
13631 
13632         if (skipInvalidate()) {
13633             return;
13634         }
13635 
13636         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13637                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13638                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13639                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13640             if (fullInvalidate) {
13641                 mLastIsOpaque = isOpaque();
13642                 mPrivateFlags &= ~PFLAG_DRAWN;
13643             }
13644 
13645             mPrivateFlags |= PFLAG_DIRTY;
13646 
13647             if (invalidateCache) {
13648                 mPrivateFlags |= PFLAG_INVALIDATED;
13649                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13650             }
13651 
13652             // Propagate the damage rectangle to the parent view.
13653             final AttachInfo ai = mAttachInfo;
13654             final ViewParent p = mParent;
13655             if (p != null && ai != null && l < r && t < b) {
13656                 final Rect damage = ai.mTmpInvalRect;
13657                 damage.set(l, t, r, b);
13658                 p.invalidateChild(this, damage);
13659             }
13660 
13661             // Damage the entire projection receiver, if necessary.
13662             if (mBackground != null && mBackground.isProjected()) {
13663                 final View receiver = getProjectionReceiver();
13664                 if (receiver != null) {
13665                     receiver.damageInParent();
13666                 }
13667             }
13668 
13669             // Damage the entire IsolatedZVolume receiving this view's shadow.
13670             if (isHardwareAccelerated() && getZ() != 0) {
13671                 damageShadowReceiver();
13672             }
13673         }
13674     }
13675 
13676     /**
13677      * @return this view's projection receiver, or {@code null} if none exists
13678      */
getProjectionReceiver()13679     private View getProjectionReceiver() {
13680         ViewParent p = getParent();
13681         while (p != null && p instanceof View) {
13682             final View v = (View) p;
13683             if (v.isProjectionReceiver()) {
13684                 return v;
13685             }
13686             p = p.getParent();
13687         }
13688 
13689         return null;
13690     }
13691 
13692     /**
13693      * @return whether the view is a projection receiver
13694      */
isProjectionReceiver()13695     private boolean isProjectionReceiver() {
13696         return mBackground != null;
13697     }
13698 
13699     /**
13700      * Damage area of the screen that can be covered by this View's shadow.
13701      *
13702      * This method will guarantee that any changes to shadows cast by a View
13703      * are damaged on the screen for future redraw.
13704      */
damageShadowReceiver()13705     private void damageShadowReceiver() {
13706         final AttachInfo ai = mAttachInfo;
13707         if (ai != null) {
13708             ViewParent p = getParent();
13709             if (p != null && p instanceof ViewGroup) {
13710                 final ViewGroup vg = (ViewGroup) p;
13711                 vg.damageInParent();
13712             }
13713         }
13714     }
13715 
13716     /**
13717      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13718      * set any flags or handle all of the cases handled by the default invalidation methods.
13719      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13720      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13721      * walk up the hierarchy, transforming the dirty rect as necessary.
13722      *
13723      * The method also handles normal invalidation logic if display list properties are not
13724      * being used in this view. The invalidateParent and forceRedraw flags are used by that
13725      * backup approach, to handle these cases used in the various property-setting methods.
13726      *
13727      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13728      * are not being used in this view
13729      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13730      * list properties are not being used in this view
13731      */
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)13732     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13733         if (!isHardwareAccelerated()
13734                 || !mRenderNode.isValid()
13735                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13736             if (invalidateParent) {
13737                 invalidateParentCaches();
13738             }
13739             if (forceRedraw) {
13740                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13741             }
13742             invalidate(false);
13743         } else {
13744             damageInParent();
13745         }
13746         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13747             damageShadowReceiver();
13748         }
13749     }
13750 
13751     /**
13752      * Tells the parent view to damage this view's bounds.
13753      *
13754      * @hide
13755      */
damageInParent()13756     protected void damageInParent() {
13757         final AttachInfo ai = mAttachInfo;
13758         final ViewParent p = mParent;
13759         if (p != null && ai != null) {
13760             final Rect r = ai.mTmpInvalRect;
13761             r.set(0, 0, mRight - mLeft, mBottom - mTop);
13762             if (mParent instanceof ViewGroup) {
13763                 ((ViewGroup) mParent).damageChild(this, r);
13764             } else {
13765                 mParent.invalidateChild(this, r);
13766             }
13767         }
13768     }
13769 
13770     /**
13771      * Utility method to transform a given Rect by the current matrix of this view.
13772      */
transformRect(final Rect rect)13773     void transformRect(final Rect rect) {
13774         if (!getMatrix().isIdentity()) {
13775             RectF boundingRect = mAttachInfo.mTmpTransformRect;
13776             boundingRect.set(rect);
13777             getMatrix().mapRect(boundingRect);
13778             rect.set((int) Math.floor(boundingRect.left),
13779                     (int) Math.floor(boundingRect.top),
13780                     (int) Math.ceil(boundingRect.right),
13781                     (int) Math.ceil(boundingRect.bottom));
13782         }
13783     }
13784 
13785     /**
13786      * Used to indicate that the parent of this view should clear its caches. This functionality
13787      * is used to force the parent to rebuild its display list (when hardware-accelerated),
13788      * which is necessary when various parent-managed properties of the view change, such as
13789      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13790      * clears the parent caches and does not causes an invalidate event.
13791      *
13792      * @hide
13793      */
invalidateParentCaches()13794     protected void invalidateParentCaches() {
13795         if (mParent instanceof View) {
13796             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13797         }
13798     }
13799 
13800     /**
13801      * Used to indicate that the parent of this view should be invalidated. This functionality
13802      * is used to force the parent to rebuild its display list (when hardware-accelerated),
13803      * which is necessary when various parent-managed properties of the view change, such as
13804      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13805      * an invalidation event to the parent.
13806      *
13807      * @hide
13808      */
invalidateParentIfNeeded()13809     protected void invalidateParentIfNeeded() {
13810         if (isHardwareAccelerated() && mParent instanceof View) {
13811             ((View) mParent).invalidate(true);
13812         }
13813     }
13814 
13815     /**
13816      * @hide
13817      */
invalidateParentIfNeededAndWasQuickRejected()13818     protected void invalidateParentIfNeededAndWasQuickRejected() {
13819         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13820             // View was rejected last time it was drawn by its parent; this may have changed
13821             invalidateParentIfNeeded();
13822         }
13823     }
13824 
13825     /**
13826      * Indicates whether this View is opaque. An opaque View guarantees that it will
13827      * draw all the pixels overlapping its bounds using a fully opaque color.
13828      *
13829      * Subclasses of View should override this method whenever possible to indicate
13830      * whether an instance is opaque. Opaque Views are treated in a special way by
13831      * the View hierarchy, possibly allowing it to perform optimizations during
13832      * invalidate/draw passes.
13833      *
13834      * @return True if this View is guaranteed to be fully opaque, false otherwise.
13835      */
13836     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()13837     public boolean isOpaque() {
13838         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13839                 getFinalAlpha() >= 1.0f;
13840     }
13841 
13842     /**
13843      * @hide
13844      */
computeOpaqueFlags()13845     protected void computeOpaqueFlags() {
13846         // Opaque if:
13847         //   - Has a background
13848         //   - Background is opaque
13849         //   - Doesn't have scrollbars or scrollbars overlay
13850 
13851         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13852             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13853         } else {
13854             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13855         }
13856 
13857         final int flags = mViewFlags;
13858         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13859                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13860                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13861             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13862         } else {
13863             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13864         }
13865     }
13866 
13867     /**
13868      * @hide
13869      */
hasOpaqueScrollbars()13870     protected boolean hasOpaqueScrollbars() {
13871         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13872     }
13873 
13874     /**
13875      * @return A handler associated with the thread running the View. This
13876      * handler can be used to pump events in the UI events queue.
13877      */
getHandler()13878     public Handler getHandler() {
13879         final AttachInfo attachInfo = mAttachInfo;
13880         if (attachInfo != null) {
13881             return attachInfo.mHandler;
13882         }
13883         return null;
13884     }
13885 
13886     /**
13887      * Returns the queue of runnable for this view.
13888      *
13889      * @return the queue of runnables for this view
13890      */
getRunQueue()13891     private HandlerActionQueue getRunQueue() {
13892         if (mRunQueue == null) {
13893             mRunQueue = new HandlerActionQueue();
13894         }
13895         return mRunQueue;
13896     }
13897 
13898     /**
13899      * Gets the view root associated with the View.
13900      * @return The view root, or null if none.
13901      * @hide
13902      */
getViewRootImpl()13903     public ViewRootImpl getViewRootImpl() {
13904         if (mAttachInfo != null) {
13905             return mAttachInfo.mViewRootImpl;
13906         }
13907         return null;
13908     }
13909 
13910     /**
13911      * @hide
13912      */
getHardwareRenderer()13913     public ThreadedRenderer getHardwareRenderer() {
13914         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13915     }
13916 
13917     /**
13918      * <p>Causes the Runnable to be added to the message queue.
13919      * The runnable will be run on the user interface thread.</p>
13920      *
13921      * @param action The Runnable that will be executed.
13922      *
13923      * @return Returns true if the Runnable was successfully placed in to the
13924      *         message queue.  Returns false on failure, usually because the
13925      *         looper processing the message queue is exiting.
13926      *
13927      * @see #postDelayed
13928      * @see #removeCallbacks
13929      */
post(Runnable action)13930     public boolean post(Runnable action) {
13931         final AttachInfo attachInfo = mAttachInfo;
13932         if (attachInfo != null) {
13933             return attachInfo.mHandler.post(action);
13934         }
13935 
13936         // Postpone the runnable until we know on which thread it needs to run.
13937         // Assume that the runnable will be successfully placed after attach.
13938         getRunQueue().post(action);
13939         return true;
13940     }
13941 
13942     /**
13943      * <p>Causes the Runnable to be added to the message queue, to be run
13944      * after the specified amount of time elapses.
13945      * The runnable will be run on the user interface thread.</p>
13946      *
13947      * @param action The Runnable that will be executed.
13948      * @param delayMillis The delay (in milliseconds) until the Runnable
13949      *        will be executed.
13950      *
13951      * @return true if the Runnable was successfully placed in to the
13952      *         message queue.  Returns false on failure, usually because the
13953      *         looper processing the message queue is exiting.  Note that a
13954      *         result of true does not mean the Runnable will be processed --
13955      *         if the looper is quit before the delivery time of the message
13956      *         occurs then the message will be dropped.
13957      *
13958      * @see #post
13959      * @see #removeCallbacks
13960      */
postDelayed(Runnable action, long delayMillis)13961     public boolean postDelayed(Runnable action, long delayMillis) {
13962         final AttachInfo attachInfo = mAttachInfo;
13963         if (attachInfo != null) {
13964             return attachInfo.mHandler.postDelayed(action, delayMillis);
13965         }
13966 
13967         // Postpone the runnable until we know on which thread it needs to run.
13968         // Assume that the runnable will be successfully placed after attach.
13969         getRunQueue().postDelayed(action, delayMillis);
13970         return true;
13971     }
13972 
13973     /**
13974      * <p>Causes the Runnable to execute on the next animation time step.
13975      * The runnable will be run on the user interface thread.</p>
13976      *
13977      * @param action The Runnable that will be executed.
13978      *
13979      * @see #postOnAnimationDelayed
13980      * @see #removeCallbacks
13981      */
postOnAnimation(Runnable action)13982     public void postOnAnimation(Runnable action) {
13983         final AttachInfo attachInfo = mAttachInfo;
13984         if (attachInfo != null) {
13985             attachInfo.mViewRootImpl.mChoreographer.postCallback(
13986                     Choreographer.CALLBACK_ANIMATION, action, null);
13987         } else {
13988             // Postpone the runnable until we know
13989             // on which thread it needs to run.
13990             getRunQueue().post(action);
13991         }
13992     }
13993 
13994     /**
13995      * <p>Causes the Runnable to execute on the next animation time step,
13996      * after the specified amount of time elapses.
13997      * The runnable will be run on the user interface thread.</p>
13998      *
13999      * @param action The Runnable that will be executed.
14000      * @param delayMillis The delay (in milliseconds) until the Runnable
14001      *        will be executed.
14002      *
14003      * @see #postOnAnimation
14004      * @see #removeCallbacks
14005      */
postOnAnimationDelayed(Runnable action, long delayMillis)14006     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14007         final AttachInfo attachInfo = mAttachInfo;
14008         if (attachInfo != null) {
14009             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14010                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14011         } else {
14012             // Postpone the runnable until we know
14013             // on which thread it needs to run.
14014             getRunQueue().postDelayed(action, delayMillis);
14015         }
14016     }
14017 
14018     /**
14019      * <p>Removes the specified Runnable from the message queue.</p>
14020      *
14021      * @param action The Runnable to remove from the message handling queue
14022      *
14023      * @return true if this view could ask the Handler to remove the Runnable,
14024      *         false otherwise. When the returned value is true, the Runnable
14025      *         may or may not have been actually removed from the message queue
14026      *         (for instance, if the Runnable was not in the queue already.)
14027      *
14028      * @see #post
14029      * @see #postDelayed
14030      * @see #postOnAnimation
14031      * @see #postOnAnimationDelayed
14032      */
removeCallbacks(Runnable action)14033     public boolean removeCallbacks(Runnable action) {
14034         if (action != null) {
14035             final AttachInfo attachInfo = mAttachInfo;
14036             if (attachInfo != null) {
14037                 attachInfo.mHandler.removeCallbacks(action);
14038                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14039                         Choreographer.CALLBACK_ANIMATION, action, null);
14040             }
14041             getRunQueue().removeCallbacks(action);
14042         }
14043         return true;
14044     }
14045 
14046     /**
14047      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14048      * Use this to invalidate the View from a non-UI thread.</p>
14049      *
14050      * <p>This method can be invoked from outside of the UI thread
14051      * only when this View is attached to a window.</p>
14052      *
14053      * @see #invalidate()
14054      * @see #postInvalidateDelayed(long)
14055      */
postInvalidate()14056     public void postInvalidate() {
14057         postInvalidateDelayed(0);
14058     }
14059 
14060     /**
14061      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14062      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14063      *
14064      * <p>This method can be invoked from outside of the UI thread
14065      * only when this View is attached to a window.</p>
14066      *
14067      * @param left The left coordinate of the rectangle to invalidate.
14068      * @param top The top coordinate of the rectangle to invalidate.
14069      * @param right The right coordinate of the rectangle to invalidate.
14070      * @param bottom The bottom coordinate of the rectangle to invalidate.
14071      *
14072      * @see #invalidate(int, int, int, int)
14073      * @see #invalidate(Rect)
14074      * @see #postInvalidateDelayed(long, int, int, int, int)
14075      */
postInvalidate(int left, int top, int right, int bottom)14076     public void postInvalidate(int left, int top, int right, int bottom) {
14077         postInvalidateDelayed(0, left, top, right, bottom);
14078     }
14079 
14080     /**
14081      * <p>Cause an invalidate to happen on a subsequent cycle through the event
14082      * loop. Waits for the specified amount of time.</p>
14083      *
14084      * <p>This method can be invoked from outside of the UI thread
14085      * only when this View is attached to a window.</p>
14086      *
14087      * @param delayMilliseconds the duration in milliseconds to delay the
14088      *         invalidation by
14089      *
14090      * @see #invalidate()
14091      * @see #postInvalidate()
14092      */
postInvalidateDelayed(long delayMilliseconds)14093     public void postInvalidateDelayed(long delayMilliseconds) {
14094         // We try only with the AttachInfo because there's no point in invalidating
14095         // if we are not attached to our window
14096         final AttachInfo attachInfo = mAttachInfo;
14097         if (attachInfo != null) {
14098             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14099         }
14100     }
14101 
14102     /**
14103      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14104      * through the event loop. Waits for the specified amount of time.</p>
14105      *
14106      * <p>This method can be invoked from outside of the UI thread
14107      * only when this View is attached to a window.</p>
14108      *
14109      * @param delayMilliseconds the duration in milliseconds to delay the
14110      *         invalidation by
14111      * @param left The left coordinate of the rectangle to invalidate.
14112      * @param top The top coordinate of the rectangle to invalidate.
14113      * @param right The right coordinate of the rectangle to invalidate.
14114      * @param bottom The bottom coordinate of the rectangle to invalidate.
14115      *
14116      * @see #invalidate(int, int, int, int)
14117      * @see #invalidate(Rect)
14118      * @see #postInvalidate(int, int, int, int)
14119      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)14120     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14121             int right, int bottom) {
14122 
14123         // We try only with the AttachInfo because there's no point in invalidating
14124         // if we are not attached to our window
14125         final AttachInfo attachInfo = mAttachInfo;
14126         if (attachInfo != null) {
14127             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14128             info.target = this;
14129             info.left = left;
14130             info.top = top;
14131             info.right = right;
14132             info.bottom = bottom;
14133 
14134             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14135         }
14136     }
14137 
14138     /**
14139      * <p>Cause an invalidate to happen on the next animation time step, typically the
14140      * next display frame.</p>
14141      *
14142      * <p>This method can be invoked from outside of the UI thread
14143      * only when this View is attached to a window.</p>
14144      *
14145      * @see #invalidate()
14146      */
postInvalidateOnAnimation()14147     public void postInvalidateOnAnimation() {
14148         // We try only with the AttachInfo because there's no point in invalidating
14149         // if we are not attached to our window
14150         final AttachInfo attachInfo = mAttachInfo;
14151         if (attachInfo != null) {
14152             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14153         }
14154     }
14155 
14156     /**
14157      * <p>Cause an invalidate of the specified area to happen on the next animation
14158      * time step, typically the next display frame.</p>
14159      *
14160      * <p>This method can be invoked from outside of the UI thread
14161      * only when this View is attached to a window.</p>
14162      *
14163      * @param left The left coordinate of the rectangle to invalidate.
14164      * @param top The top coordinate of the rectangle to invalidate.
14165      * @param right The right coordinate of the rectangle to invalidate.
14166      * @param bottom The bottom coordinate of the rectangle to invalidate.
14167      *
14168      * @see #invalidate(int, int, int, int)
14169      * @see #invalidate(Rect)
14170      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)14171     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14172         // We try only with the AttachInfo because there's no point in invalidating
14173         // if we are not attached to our window
14174         final AttachInfo attachInfo = mAttachInfo;
14175         if (attachInfo != null) {
14176             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14177             info.target = this;
14178             info.left = left;
14179             info.top = top;
14180             info.right = right;
14181             info.bottom = bottom;
14182 
14183             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14184         }
14185     }
14186 
14187     /**
14188      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14189      * This event is sent at most once every
14190      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14191      */
postSendViewScrolledAccessibilityEventCallback()14192     private void postSendViewScrolledAccessibilityEventCallback() {
14193         if (mSendViewScrolledAccessibilityEvent == null) {
14194             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14195         }
14196         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14197             mSendViewScrolledAccessibilityEvent.mIsPending = true;
14198             postDelayed(mSendViewScrolledAccessibilityEvent,
14199                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14200         }
14201     }
14202 
14203     /**
14204      * Called by a parent to request that a child update its values for mScrollX
14205      * and mScrollY if necessary. This will typically be done if the child is
14206      * animating a scroll using a {@link android.widget.Scroller Scroller}
14207      * object.
14208      */
computeScroll()14209     public void computeScroll() {
14210     }
14211 
14212     /**
14213      * <p>Indicate whether the horizontal edges are faded when the view is
14214      * scrolled horizontally.</p>
14215      *
14216      * @return true if the horizontal edges should are faded on scroll, false
14217      *         otherwise
14218      *
14219      * @see #setHorizontalFadingEdgeEnabled(boolean)
14220      *
14221      * @attr ref android.R.styleable#View_requiresFadingEdge
14222      */
isHorizontalFadingEdgeEnabled()14223     public boolean isHorizontalFadingEdgeEnabled() {
14224         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14225     }
14226 
14227     /**
14228      * <p>Define whether the horizontal edges should be faded when this view
14229      * is scrolled horizontally.</p>
14230      *
14231      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14232      *                                    be faded when the view is scrolled
14233      *                                    horizontally
14234      *
14235      * @see #isHorizontalFadingEdgeEnabled()
14236      *
14237      * @attr ref android.R.styleable#View_requiresFadingEdge
14238      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)14239     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14240         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14241             if (horizontalFadingEdgeEnabled) {
14242                 initScrollCache();
14243             }
14244 
14245             mViewFlags ^= FADING_EDGE_HORIZONTAL;
14246         }
14247     }
14248 
14249     /**
14250      * <p>Indicate whether the vertical edges are faded when the view is
14251      * scrolled horizontally.</p>
14252      *
14253      * @return true if the vertical edges should are faded on scroll, false
14254      *         otherwise
14255      *
14256      * @see #setVerticalFadingEdgeEnabled(boolean)
14257      *
14258      * @attr ref android.R.styleable#View_requiresFadingEdge
14259      */
isVerticalFadingEdgeEnabled()14260     public boolean isVerticalFadingEdgeEnabled() {
14261         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14262     }
14263 
14264     /**
14265      * <p>Define whether the vertical edges should be faded when this view
14266      * is scrolled vertically.</p>
14267      *
14268      * @param verticalFadingEdgeEnabled true if the vertical edges should
14269      *                                  be faded when the view is scrolled
14270      *                                  vertically
14271      *
14272      * @see #isVerticalFadingEdgeEnabled()
14273      *
14274      * @attr ref android.R.styleable#View_requiresFadingEdge
14275      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)14276     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14277         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14278             if (verticalFadingEdgeEnabled) {
14279                 initScrollCache();
14280             }
14281 
14282             mViewFlags ^= FADING_EDGE_VERTICAL;
14283         }
14284     }
14285 
14286     /**
14287      * Returns the strength, or intensity, of the top faded edge. The strength is
14288      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14289      * returns 0.0 or 1.0 but no value in between.
14290      *
14291      * Subclasses should override this method to provide a smoother fade transition
14292      * when scrolling occurs.
14293      *
14294      * @return the intensity of the top fade as a float between 0.0f and 1.0f
14295      */
getTopFadingEdgeStrength()14296     protected float getTopFadingEdgeStrength() {
14297         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14298     }
14299 
14300     /**
14301      * Returns the strength, or intensity, of the bottom faded edge. The strength is
14302      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14303      * returns 0.0 or 1.0 but no value in between.
14304      *
14305      * Subclasses should override this method to provide a smoother fade transition
14306      * when scrolling occurs.
14307      *
14308      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14309      */
getBottomFadingEdgeStrength()14310     protected float getBottomFadingEdgeStrength() {
14311         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14312                 computeVerticalScrollRange() ? 1.0f : 0.0f;
14313     }
14314 
14315     /**
14316      * Returns the strength, or intensity, of the left faded edge. The strength is
14317      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14318      * returns 0.0 or 1.0 but no value in between.
14319      *
14320      * Subclasses should override this method to provide a smoother fade transition
14321      * when scrolling occurs.
14322      *
14323      * @return the intensity of the left fade as a float between 0.0f and 1.0f
14324      */
getLeftFadingEdgeStrength()14325     protected float getLeftFadingEdgeStrength() {
14326         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14327     }
14328 
14329     /**
14330      * Returns the strength, or intensity, of the right faded edge. The strength is
14331      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14332      * returns 0.0 or 1.0 but no value in between.
14333      *
14334      * Subclasses should override this method to provide a smoother fade transition
14335      * when scrolling occurs.
14336      *
14337      * @return the intensity of the right fade as a float between 0.0f and 1.0f
14338      */
getRightFadingEdgeStrength()14339     protected float getRightFadingEdgeStrength() {
14340         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14341                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
14342     }
14343 
14344     /**
14345      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14346      * scrollbar is not drawn by default.</p>
14347      *
14348      * @return true if the horizontal scrollbar should be painted, false
14349      *         otherwise
14350      *
14351      * @see #setHorizontalScrollBarEnabled(boolean)
14352      */
isHorizontalScrollBarEnabled()14353     public boolean isHorizontalScrollBarEnabled() {
14354         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14355     }
14356 
14357     /**
14358      * <p>Define whether the horizontal scrollbar should be drawn or not. The
14359      * scrollbar is not drawn by default.</p>
14360      *
14361      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14362      *                                   be painted
14363      *
14364      * @see #isHorizontalScrollBarEnabled()
14365      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)14366     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14367         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14368             mViewFlags ^= SCROLLBARS_HORIZONTAL;
14369             computeOpaqueFlags();
14370             resolvePadding();
14371         }
14372     }
14373 
14374     /**
14375      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14376      * scrollbar is not drawn by default.</p>
14377      *
14378      * @return true if the vertical scrollbar should be painted, false
14379      *         otherwise
14380      *
14381      * @see #setVerticalScrollBarEnabled(boolean)
14382      */
isVerticalScrollBarEnabled()14383     public boolean isVerticalScrollBarEnabled() {
14384         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14385     }
14386 
14387     /**
14388      * <p>Define whether the vertical scrollbar should be drawn or not. The
14389      * scrollbar is not drawn by default.</p>
14390      *
14391      * @param verticalScrollBarEnabled true if the vertical scrollbar should
14392      *                                 be painted
14393      *
14394      * @see #isVerticalScrollBarEnabled()
14395      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)14396     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14397         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14398             mViewFlags ^= SCROLLBARS_VERTICAL;
14399             computeOpaqueFlags();
14400             resolvePadding();
14401         }
14402     }
14403 
14404     /**
14405      * @hide
14406      */
recomputePadding()14407     protected void recomputePadding() {
14408         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14409     }
14410 
14411     /**
14412      * Define whether scrollbars will fade when the view is not scrolling.
14413      *
14414      * @param fadeScrollbars whether to enable fading
14415      *
14416      * @attr ref android.R.styleable#View_fadeScrollbars
14417      */
setScrollbarFadingEnabled(boolean fadeScrollbars)14418     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14419         initScrollCache();
14420         final ScrollabilityCache scrollabilityCache = mScrollCache;
14421         scrollabilityCache.fadeScrollBars = fadeScrollbars;
14422         if (fadeScrollbars) {
14423             scrollabilityCache.state = ScrollabilityCache.OFF;
14424         } else {
14425             scrollabilityCache.state = ScrollabilityCache.ON;
14426         }
14427     }
14428 
14429     /**
14430      *
14431      * Returns true if scrollbars will fade when this view is not scrolling
14432      *
14433      * @return true if scrollbar fading is enabled
14434      *
14435      * @attr ref android.R.styleable#View_fadeScrollbars
14436      */
isScrollbarFadingEnabled()14437     public boolean isScrollbarFadingEnabled() {
14438         return mScrollCache != null && mScrollCache.fadeScrollBars;
14439     }
14440 
14441     /**
14442      *
14443      * Returns the delay before scrollbars fade.
14444      *
14445      * @return the delay before scrollbars fade
14446      *
14447      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14448      */
getScrollBarDefaultDelayBeforeFade()14449     public int getScrollBarDefaultDelayBeforeFade() {
14450         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14451                 mScrollCache.scrollBarDefaultDelayBeforeFade;
14452     }
14453 
14454     /**
14455      * Define the delay before scrollbars fade.
14456      *
14457      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14458      *
14459      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14460      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)14461     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14462         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14463     }
14464 
14465     /**
14466      *
14467      * Returns the scrollbar fade duration.
14468      *
14469      * @return the scrollbar fade duration
14470      *
14471      * @attr ref android.R.styleable#View_scrollbarFadeDuration
14472      */
getScrollBarFadeDuration()14473     public int getScrollBarFadeDuration() {
14474         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14475                 mScrollCache.scrollBarFadeDuration;
14476     }
14477 
14478     /**
14479      * Define the scrollbar fade duration.
14480      *
14481      * @param scrollBarFadeDuration - the scrollbar fade duration
14482      *
14483      * @attr ref android.R.styleable#View_scrollbarFadeDuration
14484      */
setScrollBarFadeDuration(int scrollBarFadeDuration)14485     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14486         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14487     }
14488 
14489     /**
14490      *
14491      * Returns the scrollbar size.
14492      *
14493      * @return the scrollbar size
14494      *
14495      * @attr ref android.R.styleable#View_scrollbarSize
14496      */
getScrollBarSize()14497     public int getScrollBarSize() {
14498         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14499                 mScrollCache.scrollBarSize;
14500     }
14501 
14502     /**
14503      * Define the scrollbar size.
14504      *
14505      * @param scrollBarSize - the scrollbar size
14506      *
14507      * @attr ref android.R.styleable#View_scrollbarSize
14508      */
setScrollBarSize(int scrollBarSize)14509     public void setScrollBarSize(int scrollBarSize) {
14510         getScrollCache().scrollBarSize = scrollBarSize;
14511     }
14512 
14513     /**
14514      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14515      * inset. When inset, they add to the padding of the view. And the scrollbars
14516      * can be drawn inside the padding area or on the edge of the view. For example,
14517      * if a view has a background drawable and you want to draw the scrollbars
14518      * inside the padding specified by the drawable, you can use
14519      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14520      * appear at the edge of the view, ignoring the padding, then you can use
14521      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14522      * @param style the style of the scrollbars. Should be one of
14523      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14524      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14525      * @see #SCROLLBARS_INSIDE_OVERLAY
14526      * @see #SCROLLBARS_INSIDE_INSET
14527      * @see #SCROLLBARS_OUTSIDE_OVERLAY
14528      * @see #SCROLLBARS_OUTSIDE_INSET
14529      *
14530      * @attr ref android.R.styleable#View_scrollbarStyle
14531      */
setScrollBarStyle(@crollBarStyle int style)14532     public void setScrollBarStyle(@ScrollBarStyle int style) {
14533         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14534             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14535             computeOpaqueFlags();
14536             resolvePadding();
14537         }
14538     }
14539 
14540     /**
14541      * <p>Returns the current scrollbar style.</p>
14542      * @return the current scrollbar style
14543      * @see #SCROLLBARS_INSIDE_OVERLAY
14544      * @see #SCROLLBARS_INSIDE_INSET
14545      * @see #SCROLLBARS_OUTSIDE_OVERLAY
14546      * @see #SCROLLBARS_OUTSIDE_INSET
14547      *
14548      * @attr ref android.R.styleable#View_scrollbarStyle
14549      */
14550     @ViewDebug.ExportedProperty(mapping = {
14551             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14552             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14553             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14554             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14555     })
14556     @ScrollBarStyle
getScrollBarStyle()14557     public int getScrollBarStyle() {
14558         return mViewFlags & SCROLLBARS_STYLE_MASK;
14559     }
14560 
14561     /**
14562      * <p>Compute the horizontal range that the horizontal scrollbar
14563      * represents.</p>
14564      *
14565      * <p>The range is expressed in arbitrary units that must be the same as the
14566      * units used by {@link #computeHorizontalScrollExtent()} and
14567      * {@link #computeHorizontalScrollOffset()}.</p>
14568      *
14569      * <p>The default range is the drawing width of this view.</p>
14570      *
14571      * @return the total horizontal range represented by the horizontal
14572      *         scrollbar
14573      *
14574      * @see #computeHorizontalScrollExtent()
14575      * @see #computeHorizontalScrollOffset()
14576      * @see android.widget.ScrollBarDrawable
14577      */
computeHorizontalScrollRange()14578     protected int computeHorizontalScrollRange() {
14579         return getWidth();
14580     }
14581 
14582     /**
14583      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14584      * within the horizontal range. This value is used to compute the position
14585      * of the thumb within the scrollbar's track.</p>
14586      *
14587      * <p>The range is expressed in arbitrary units that must be the same as the
14588      * units used by {@link #computeHorizontalScrollRange()} and
14589      * {@link #computeHorizontalScrollExtent()}.</p>
14590      *
14591      * <p>The default offset is the scroll offset of this view.</p>
14592      *
14593      * @return the horizontal offset of the scrollbar's thumb
14594      *
14595      * @see #computeHorizontalScrollRange()
14596      * @see #computeHorizontalScrollExtent()
14597      * @see android.widget.ScrollBarDrawable
14598      */
computeHorizontalScrollOffset()14599     protected int computeHorizontalScrollOffset() {
14600         return mScrollX;
14601     }
14602 
14603     /**
14604      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14605      * within the horizontal range. This value is used to compute the length
14606      * of the thumb within the scrollbar's track.</p>
14607      *
14608      * <p>The range is expressed in arbitrary units that must be the same as the
14609      * units used by {@link #computeHorizontalScrollRange()} and
14610      * {@link #computeHorizontalScrollOffset()}.</p>
14611      *
14612      * <p>The default extent is the drawing width of this view.</p>
14613      *
14614      * @return the horizontal extent of the scrollbar's thumb
14615      *
14616      * @see #computeHorizontalScrollRange()
14617      * @see #computeHorizontalScrollOffset()
14618      * @see android.widget.ScrollBarDrawable
14619      */
computeHorizontalScrollExtent()14620     protected int computeHorizontalScrollExtent() {
14621         return getWidth();
14622     }
14623 
14624     /**
14625      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14626      *
14627      * <p>The range is expressed in arbitrary units that must be the same as the
14628      * units used by {@link #computeVerticalScrollExtent()} and
14629      * {@link #computeVerticalScrollOffset()}.</p>
14630      *
14631      * @return the total vertical range represented by the vertical scrollbar
14632      *
14633      * <p>The default range is the drawing height of this view.</p>
14634      *
14635      * @see #computeVerticalScrollExtent()
14636      * @see #computeVerticalScrollOffset()
14637      * @see android.widget.ScrollBarDrawable
14638      */
computeVerticalScrollRange()14639     protected int computeVerticalScrollRange() {
14640         return getHeight();
14641     }
14642 
14643     /**
14644      * <p>Compute the vertical offset of the vertical scrollbar's thumb
14645      * within the horizontal range. This value is used to compute the position
14646      * of the thumb within the scrollbar's track.</p>
14647      *
14648      * <p>The range is expressed in arbitrary units that must be the same as the
14649      * units used by {@link #computeVerticalScrollRange()} and
14650      * {@link #computeVerticalScrollExtent()}.</p>
14651      *
14652      * <p>The default offset is the scroll offset of this view.</p>
14653      *
14654      * @return the vertical offset of the scrollbar's thumb
14655      *
14656      * @see #computeVerticalScrollRange()
14657      * @see #computeVerticalScrollExtent()
14658      * @see android.widget.ScrollBarDrawable
14659      */
computeVerticalScrollOffset()14660     protected int computeVerticalScrollOffset() {
14661         return mScrollY;
14662     }
14663 
14664     /**
14665      * <p>Compute the vertical extent of the vertical scrollbar's thumb
14666      * within the vertical range. This value is used to compute the length
14667      * of the thumb within the scrollbar's track.</p>
14668      *
14669      * <p>The range is expressed in arbitrary units that must be the same as the
14670      * units used by {@link #computeVerticalScrollRange()} and
14671      * {@link #computeVerticalScrollOffset()}.</p>
14672      *
14673      * <p>The default extent is the drawing height of this view.</p>
14674      *
14675      * @return the vertical extent of the scrollbar's thumb
14676      *
14677      * @see #computeVerticalScrollRange()
14678      * @see #computeVerticalScrollOffset()
14679      * @see android.widget.ScrollBarDrawable
14680      */
computeVerticalScrollExtent()14681     protected int computeVerticalScrollExtent() {
14682         return getHeight();
14683     }
14684 
14685     /**
14686      * Check if this view can be scrolled horizontally in a certain direction.
14687      *
14688      * @param direction Negative to check scrolling left, positive to check scrolling right.
14689      * @return true if this view can be scrolled in the specified direction, false otherwise.
14690      */
canScrollHorizontally(int direction)14691     public boolean canScrollHorizontally(int direction) {
14692         final int offset = computeHorizontalScrollOffset();
14693         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14694         if (range == 0) return false;
14695         if (direction < 0) {
14696             return offset > 0;
14697         } else {
14698             return offset < range - 1;
14699         }
14700     }
14701 
14702     /**
14703      * Check if this view can be scrolled vertically in a certain direction.
14704      *
14705      * @param direction Negative to check scrolling up, positive to check scrolling down.
14706      * @return true if this view can be scrolled in the specified direction, false otherwise.
14707      */
canScrollVertically(int direction)14708     public boolean canScrollVertically(int direction) {
14709         final int offset = computeVerticalScrollOffset();
14710         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14711         if (range == 0) return false;
14712         if (direction < 0) {
14713             return offset > 0;
14714         } else {
14715             return offset < range - 1;
14716         }
14717     }
14718 
getScrollIndicatorBounds(@onNull Rect out)14719     void getScrollIndicatorBounds(@NonNull Rect out) {
14720         out.left = mScrollX;
14721         out.right = mScrollX + mRight - mLeft;
14722         out.top = mScrollY;
14723         out.bottom = mScrollY + mBottom - mTop;
14724     }
14725 
onDrawScrollIndicators(Canvas c)14726     private void onDrawScrollIndicators(Canvas c) {
14727         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14728             // No scroll indicators enabled.
14729             return;
14730         }
14731 
14732         final Drawable dr = mScrollIndicatorDrawable;
14733         if (dr == null) {
14734             // Scroll indicators aren't supported here.
14735             return;
14736         }
14737 
14738         final int h = dr.getIntrinsicHeight();
14739         final int w = dr.getIntrinsicWidth();
14740         final Rect rect = mAttachInfo.mTmpInvalRect;
14741         getScrollIndicatorBounds(rect);
14742 
14743         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14744             final boolean canScrollUp = canScrollVertically(-1);
14745             if (canScrollUp) {
14746                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14747                 dr.draw(c);
14748             }
14749         }
14750 
14751         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14752             final boolean canScrollDown = canScrollVertically(1);
14753             if (canScrollDown) {
14754                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14755                 dr.draw(c);
14756             }
14757         }
14758 
14759         final int leftRtl;
14760         final int rightRtl;
14761         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14762             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14763             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14764         } else {
14765             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14766             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14767         }
14768 
14769         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14770         if ((mPrivateFlags3 & leftMask) != 0) {
14771             final boolean canScrollLeft = canScrollHorizontally(-1);
14772             if (canScrollLeft) {
14773                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14774                 dr.draw(c);
14775             }
14776         }
14777 
14778         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14779         if ((mPrivateFlags3 & rightMask) != 0) {
14780             final boolean canScrollRight = canScrollHorizontally(1);
14781             if (canScrollRight) {
14782                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14783                 dr.draw(c);
14784             }
14785         }
14786     }
14787 
getHorizontalScrollBarBounds(Rect bounds)14788     private void getHorizontalScrollBarBounds(Rect bounds) {
14789         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14790         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14791                 && !isVerticalScrollBarHidden();
14792         final int size = getHorizontalScrollbarHeight();
14793         final int verticalScrollBarGap = drawVerticalScrollBar ?
14794                 getVerticalScrollbarWidth() : 0;
14795         final int width = mRight - mLeft;
14796         final int height = mBottom - mTop;
14797         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14798         bounds.left = mScrollX + (mPaddingLeft & inside);
14799         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14800         bounds.bottom = bounds.top + size;
14801     }
14802 
getVerticalScrollBarBounds(Rect bounds)14803     private void getVerticalScrollBarBounds(Rect bounds) {
14804         if (mRoundScrollbarRenderer == null) {
14805             getStraightVerticalScrollBarBounds(bounds);
14806         } else {
14807             getRoundVerticalScrollBarBounds(bounds);
14808         }
14809     }
14810 
getRoundVerticalScrollBarBounds(Rect bounds)14811     private void getRoundVerticalScrollBarBounds(Rect bounds) {
14812         final int width = mRight - mLeft;
14813         final int height = mBottom - mTop;
14814         // Do not take padding into account as we always want the scrollbars
14815         // to hug the screen for round wearable devices.
14816         bounds.left = mScrollX;
14817         bounds.top = mScrollY;
14818         bounds.right = bounds.left + width;
14819         bounds.bottom = mScrollY + height;
14820     }
14821 
getStraightVerticalScrollBarBounds(Rect bounds)14822     private void getStraightVerticalScrollBarBounds(Rect bounds) {
14823         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14824         final int size = getVerticalScrollbarWidth();
14825         int verticalScrollbarPosition = mVerticalScrollbarPosition;
14826         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14827             verticalScrollbarPosition = isLayoutRtl() ?
14828                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14829         }
14830         final int width = mRight - mLeft;
14831         final int height = mBottom - mTop;
14832         switch (verticalScrollbarPosition) {
14833             default:
14834             case SCROLLBAR_POSITION_RIGHT:
14835                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14836                 break;
14837             case SCROLLBAR_POSITION_LEFT:
14838                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
14839                 break;
14840         }
14841         bounds.top = mScrollY + (mPaddingTop & inside);
14842         bounds.right = bounds.left + size;
14843         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14844     }
14845 
14846     /**
14847      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14848      * scrollbars are painted only if they have been awakened first.</p>
14849      *
14850      * @param canvas the canvas on which to draw the scrollbars
14851      *
14852      * @see #awakenScrollBars(int)
14853      */
onDrawScrollBars(Canvas canvas)14854     protected final void onDrawScrollBars(Canvas canvas) {
14855         // scrollbars are drawn only when the animation is running
14856         final ScrollabilityCache cache = mScrollCache;
14857 
14858         if (cache != null) {
14859 
14860             int state = cache.state;
14861 
14862             if (state == ScrollabilityCache.OFF) {
14863                 return;
14864             }
14865 
14866             boolean invalidate = false;
14867 
14868             if (state == ScrollabilityCache.FADING) {
14869                 // We're fading -- get our fade interpolation
14870                 if (cache.interpolatorValues == null) {
14871                     cache.interpolatorValues = new float[1];
14872                 }
14873 
14874                 float[] values = cache.interpolatorValues;
14875 
14876                 // Stops the animation if we're done
14877                 if (cache.scrollBarInterpolator.timeToValues(values) ==
14878                         Interpolator.Result.FREEZE_END) {
14879                     cache.state = ScrollabilityCache.OFF;
14880                 } else {
14881                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14882                 }
14883 
14884                 // This will make the scroll bars inval themselves after
14885                 // drawing. We only want this when we're fading so that
14886                 // we prevent excessive redraws
14887                 invalidate = true;
14888             } else {
14889                 // We're just on -- but we may have been fading before so
14890                 // reset alpha
14891                 cache.scrollBar.mutate().setAlpha(255);
14892             }
14893 
14894             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14895             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14896                     && !isVerticalScrollBarHidden();
14897 
14898             // Fork out the scroll bar drawing for round wearable devices.
14899             if (mRoundScrollbarRenderer != null) {
14900                 if (drawVerticalScrollBar) {
14901                     final Rect bounds = cache.mScrollBarBounds;
14902                     getVerticalScrollBarBounds(bounds);
14903                     mRoundScrollbarRenderer.drawRoundScrollbars(
14904                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
14905                     if (invalidate) {
14906                         invalidate();
14907                     }
14908                 }
14909                 // Do not draw horizontal scroll bars for round wearable devices.
14910             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14911                 final ScrollBarDrawable scrollBar = cache.scrollBar;
14912 
14913                 if (drawHorizontalScrollBar) {
14914                     scrollBar.setParameters(computeHorizontalScrollRange(),
14915                             computeHorizontalScrollOffset(),
14916                             computeHorizontalScrollExtent(), false);
14917                     final Rect bounds = cache.mScrollBarBounds;
14918                     getHorizontalScrollBarBounds(bounds);
14919                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14920                             bounds.right, bounds.bottom);
14921                     if (invalidate) {
14922                         invalidate(bounds);
14923                     }
14924                 }
14925 
14926                 if (drawVerticalScrollBar) {
14927                     scrollBar.setParameters(computeVerticalScrollRange(),
14928                             computeVerticalScrollOffset(),
14929                             computeVerticalScrollExtent(), true);
14930                     final Rect bounds = cache.mScrollBarBounds;
14931                     getVerticalScrollBarBounds(bounds);
14932                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14933                             bounds.right, bounds.bottom);
14934                     if (invalidate) {
14935                         invalidate(bounds);
14936                     }
14937                 }
14938             }
14939         }
14940     }
14941 
14942     /**
14943      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14944      * FastScroller is visible.
14945      * @return whether to temporarily hide the vertical scrollbar
14946      * @hide
14947      */
isVerticalScrollBarHidden()14948     protected boolean isVerticalScrollBarHidden() {
14949         return false;
14950     }
14951 
14952     /**
14953      * <p>Draw the horizontal scrollbar if
14954      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14955      *
14956      * @param canvas the canvas on which to draw the scrollbar
14957      * @param scrollBar the scrollbar's drawable
14958      *
14959      * @see #isHorizontalScrollBarEnabled()
14960      * @see #computeHorizontalScrollRange()
14961      * @see #computeHorizontalScrollExtent()
14962      * @see #computeHorizontalScrollOffset()
14963      * @see android.widget.ScrollBarDrawable
14964      * @hide
14965      */
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14966     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14967             int l, int t, int r, int b) {
14968         scrollBar.setBounds(l, t, r, b);
14969         scrollBar.draw(canvas);
14970     }
14971 
14972     /**
14973      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14974      * returns true.</p>
14975      *
14976      * @param canvas the canvas on which to draw the scrollbar
14977      * @param scrollBar the scrollbar's drawable
14978      *
14979      * @see #isVerticalScrollBarEnabled()
14980      * @see #computeVerticalScrollRange()
14981      * @see #computeVerticalScrollExtent()
14982      * @see #computeVerticalScrollOffset()
14983      * @see android.widget.ScrollBarDrawable
14984      * @hide
14985      */
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14986     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14987             int l, int t, int r, int b) {
14988         scrollBar.setBounds(l, t, r, b);
14989         scrollBar.draw(canvas);
14990     }
14991 
14992     /**
14993      * Implement this to do your drawing.
14994      *
14995      * @param canvas the canvas on which the background will be drawn
14996      */
onDraw(Canvas canvas)14997     protected void onDraw(Canvas canvas) {
14998     }
14999 
15000     /*
15001      * Caller is responsible for calling requestLayout if necessary.
15002      * (This allows addViewInLayout to not request a new layout.)
15003      */
assignParent(ViewParent parent)15004     void assignParent(ViewParent parent) {
15005         if (mParent == null) {
15006             mParent = parent;
15007         } else if (parent == null) {
15008             mParent = null;
15009         } else {
15010             throw new RuntimeException("view " + this + " being added, but"
15011                     + " it already has a parent");
15012         }
15013     }
15014 
15015     /**
15016      * This is called when the view is attached to a window.  At this point it
15017      * has a Surface and will start drawing.  Note that this function is
15018      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15019      * however it may be called any time before the first onDraw -- including
15020      * before or after {@link #onMeasure(int, int)}.
15021      *
15022      * @see #onDetachedFromWindow()
15023      */
15024     @CallSuper
onAttachedToWindow()15025     protected void onAttachedToWindow() {
15026         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15027             mParent.requestTransparentRegion(this);
15028         }
15029 
15030         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15031 
15032         jumpDrawablesToCurrentState();
15033 
15034         resetSubtreeAccessibilityStateChanged();
15035 
15036         // rebuild, since Outline not maintained while View is detached
15037         rebuildOutline();
15038 
15039         if (isFocused()) {
15040             InputMethodManager imm = InputMethodManager.peekInstance();
15041             if (imm != null) {
15042                 imm.focusIn(this);
15043             }
15044         }
15045     }
15046 
15047     /**
15048      * Resolve all RTL related properties.
15049      *
15050      * @return true if resolution of RTL properties has been done
15051      *
15052      * @hide
15053      */
resolveRtlPropertiesIfNeeded()15054     public boolean resolveRtlPropertiesIfNeeded() {
15055         if (!needRtlPropertiesResolution()) return false;
15056 
15057         // Order is important here: LayoutDirection MUST be resolved first
15058         if (!isLayoutDirectionResolved()) {
15059             resolveLayoutDirection();
15060             resolveLayoutParams();
15061         }
15062         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15063         if (!isTextDirectionResolved()) {
15064             resolveTextDirection();
15065         }
15066         if (!isTextAlignmentResolved()) {
15067             resolveTextAlignment();
15068         }
15069         // Should resolve Drawables before Padding because we need the layout direction of the
15070         // Drawable to correctly resolve Padding.
15071         if (!areDrawablesResolved()) {
15072             resolveDrawables();
15073         }
15074         if (!isPaddingResolved()) {
15075             resolvePadding();
15076         }
15077         onRtlPropertiesChanged(getLayoutDirection());
15078         return true;
15079     }
15080 
15081     /**
15082      * Reset resolution of all RTL related properties.
15083      *
15084      * @hide
15085      */
resetRtlProperties()15086     public void resetRtlProperties() {
15087         resetResolvedLayoutDirection();
15088         resetResolvedTextDirection();
15089         resetResolvedTextAlignment();
15090         resetResolvedPadding();
15091         resetResolvedDrawables();
15092     }
15093 
15094     /**
15095      * @see #onScreenStateChanged(int)
15096      */
dispatchScreenStateChanged(int screenState)15097     void dispatchScreenStateChanged(int screenState) {
15098         onScreenStateChanged(screenState);
15099     }
15100 
15101     /**
15102      * This method is called whenever the state of the screen this view is
15103      * attached to changes. A state change will usually occurs when the screen
15104      * turns on or off (whether it happens automatically or the user does it
15105      * manually.)
15106      *
15107      * @param screenState The new state of the screen. Can be either
15108      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15109      */
onScreenStateChanged(int screenState)15110     public void onScreenStateChanged(int screenState) {
15111     }
15112 
15113     /**
15114      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15115      */
hasRtlSupport()15116     private boolean hasRtlSupport() {
15117         return mContext.getApplicationInfo().hasRtlSupport();
15118     }
15119 
15120     /**
15121      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15122      * RTL not supported)
15123      */
isRtlCompatibilityMode()15124     private boolean isRtlCompatibilityMode() {
15125         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15126         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15127     }
15128 
15129     /**
15130      * @return true if RTL properties need resolution.
15131      *
15132      */
needRtlPropertiesResolution()15133     private boolean needRtlPropertiesResolution() {
15134         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15135     }
15136 
15137     /**
15138      * Called when any RTL property (layout direction or text direction or text alignment) has
15139      * been changed.
15140      *
15141      * Subclasses need to override this method to take care of cached information that depends on the
15142      * resolved layout direction, or to inform child views that inherit their layout direction.
15143      *
15144      * The default implementation does nothing.
15145      *
15146      * @param layoutDirection the direction of the layout
15147      *
15148      * @see #LAYOUT_DIRECTION_LTR
15149      * @see #LAYOUT_DIRECTION_RTL
15150      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)15151     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15152     }
15153 
15154     /**
15155      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15156      * that the parent directionality can and will be resolved before its children.
15157      *
15158      * @return true if resolution has been done, false otherwise.
15159      *
15160      * @hide
15161      */
resolveLayoutDirection()15162     public boolean resolveLayoutDirection() {
15163         // Clear any previous layout direction resolution
15164         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15165 
15166         if (hasRtlSupport()) {
15167             // Set resolved depending on layout direction
15168             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15169                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15170                 case LAYOUT_DIRECTION_INHERIT:
15171                     // We cannot resolve yet. LTR is by default and let the resolution happen again
15172                     // later to get the correct resolved value
15173                     if (!canResolveLayoutDirection()) return false;
15174 
15175                     // Parent has not yet resolved, LTR is still the default
15176                     try {
15177                         if (!mParent.isLayoutDirectionResolved()) return false;
15178 
15179                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15180                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15181                         }
15182                     } catch (AbstractMethodError e) {
15183                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15184                                 " does not fully implement ViewParent", e);
15185                     }
15186                     break;
15187                 case LAYOUT_DIRECTION_RTL:
15188                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15189                     break;
15190                 case LAYOUT_DIRECTION_LOCALE:
15191                     if((LAYOUT_DIRECTION_RTL ==
15192                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15193                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15194                     }
15195                     break;
15196                 default:
15197                     // Nothing to do, LTR by default
15198             }
15199         }
15200 
15201         // Set to resolved
15202         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15203         return true;
15204     }
15205 
15206     /**
15207      * Check if layout direction resolution can be done.
15208      *
15209      * @return true if layout direction resolution can be done otherwise return false.
15210      */
canResolveLayoutDirection()15211     public boolean canResolveLayoutDirection() {
15212         switch (getRawLayoutDirection()) {
15213             case LAYOUT_DIRECTION_INHERIT:
15214                 if (mParent != null) {
15215                     try {
15216                         return mParent.canResolveLayoutDirection();
15217                     } catch (AbstractMethodError e) {
15218                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15219                                 " does not fully implement ViewParent", e);
15220                     }
15221                 }
15222                 return false;
15223 
15224             default:
15225                 return true;
15226         }
15227     }
15228 
15229     /**
15230      * Reset the resolved layout direction. Layout direction will be resolved during a call to
15231      * {@link #onMeasure(int, int)}.
15232      *
15233      * @hide
15234      */
resetResolvedLayoutDirection()15235     public void resetResolvedLayoutDirection() {
15236         // Reset the current resolved bits
15237         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15238     }
15239 
15240     /**
15241      * @return true if the layout direction is inherited.
15242      *
15243      * @hide
15244      */
isLayoutDirectionInherited()15245     public boolean isLayoutDirectionInherited() {
15246         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15247     }
15248 
15249     /**
15250      * @return true if layout direction has been resolved.
15251      */
isLayoutDirectionResolved()15252     public boolean isLayoutDirectionResolved() {
15253         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15254     }
15255 
15256     /**
15257      * Return if padding has been resolved
15258      *
15259      * @hide
15260      */
isPaddingResolved()15261     boolean isPaddingResolved() {
15262         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15263     }
15264 
15265     /**
15266      * Resolves padding depending on layout direction, if applicable, and
15267      * recomputes internal padding values to adjust for scroll bars.
15268      *
15269      * @hide
15270      */
resolvePadding()15271     public void resolvePadding() {
15272         final int resolvedLayoutDirection = getLayoutDirection();
15273 
15274         if (!isRtlCompatibilityMode()) {
15275             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15276             // If start / end padding are defined, they will be resolved (hence overriding) to
15277             // left / right or right / left depending on the resolved layout direction.
15278             // If start / end padding are not defined, use the left / right ones.
15279             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15280                 Rect padding = sThreadLocal.get();
15281                 if (padding == null) {
15282                     padding = new Rect();
15283                     sThreadLocal.set(padding);
15284                 }
15285                 mBackground.getPadding(padding);
15286                 if (!mLeftPaddingDefined) {
15287                     mUserPaddingLeftInitial = padding.left;
15288                 }
15289                 if (!mRightPaddingDefined) {
15290                     mUserPaddingRightInitial = padding.right;
15291                 }
15292             }
15293             switch (resolvedLayoutDirection) {
15294                 case LAYOUT_DIRECTION_RTL:
15295                     if (mUserPaddingStart != UNDEFINED_PADDING) {
15296                         mUserPaddingRight = mUserPaddingStart;
15297                     } else {
15298                         mUserPaddingRight = mUserPaddingRightInitial;
15299                     }
15300                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
15301                         mUserPaddingLeft = mUserPaddingEnd;
15302                     } else {
15303                         mUserPaddingLeft = mUserPaddingLeftInitial;
15304                     }
15305                     break;
15306                 case LAYOUT_DIRECTION_LTR:
15307                 default:
15308                     if (mUserPaddingStart != UNDEFINED_PADDING) {
15309                         mUserPaddingLeft = mUserPaddingStart;
15310                     } else {
15311                         mUserPaddingLeft = mUserPaddingLeftInitial;
15312                     }
15313                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
15314                         mUserPaddingRight = mUserPaddingEnd;
15315                     } else {
15316                         mUserPaddingRight = mUserPaddingRightInitial;
15317                     }
15318             }
15319 
15320             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15321         }
15322 
15323         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15324         onRtlPropertiesChanged(resolvedLayoutDirection);
15325 
15326         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15327     }
15328 
15329     /**
15330      * Reset the resolved layout direction.
15331      *
15332      * @hide
15333      */
resetResolvedPadding()15334     public void resetResolvedPadding() {
15335         resetResolvedPaddingInternal();
15336     }
15337 
15338     /**
15339      * Used when we only want to reset *this* view's padding and not trigger overrides
15340      * in ViewGroup that reset children too.
15341      */
resetResolvedPaddingInternal()15342     void resetResolvedPaddingInternal() {
15343         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15344     }
15345 
15346     /**
15347      * This is called when the view is detached from a window.  At this point it
15348      * no longer has a surface for drawing.
15349      *
15350      * @see #onAttachedToWindow()
15351      */
15352     @CallSuper
onDetachedFromWindow()15353     protected void onDetachedFromWindow() {
15354     }
15355 
15356     /**
15357      * This is a framework-internal mirror of onDetachedFromWindow() that's called
15358      * after onDetachedFromWindow().
15359      *
15360      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15361      * The super method should be called at the end of the overridden method to ensure
15362      * subclasses are destroyed first
15363      *
15364      * @hide
15365      */
15366     @CallSuper
onDetachedFromWindowInternal()15367     protected void onDetachedFromWindowInternal() {
15368         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15369         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15370         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15371 
15372         removeUnsetPressCallback();
15373         removeLongPressCallback();
15374         removePerformClickCallback();
15375         removeSendViewScrolledAccessibilityEventCallback();
15376         stopNestedScroll();
15377 
15378         // Anything that started animating right before detach should already
15379         // be in its final state when re-attached.
15380         jumpDrawablesToCurrentState();
15381 
15382         destroyDrawingCache();
15383 
15384         cleanupDraw();
15385         mCurrentAnimation = null;
15386     }
15387 
cleanupDraw()15388     private void cleanupDraw() {
15389         resetDisplayList();
15390         if (mAttachInfo != null) {
15391             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15392         }
15393     }
15394 
invalidateInheritedLayoutMode(int layoutModeOfRoot)15395     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15396     }
15397 
15398     /**
15399      * @return The number of times this view has been attached to a window
15400      */
getWindowAttachCount()15401     protected int getWindowAttachCount() {
15402         return mWindowAttachCount;
15403     }
15404 
15405     /**
15406      * Retrieve a unique token identifying the window this view is attached to.
15407      * @return Return the window's token for use in
15408      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15409      */
getWindowToken()15410     public IBinder getWindowToken() {
15411         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15412     }
15413 
15414     /**
15415      * Retrieve the {@link WindowId} for the window this view is
15416      * currently attached to.
15417      */
getWindowId()15418     public WindowId getWindowId() {
15419         if (mAttachInfo == null) {
15420             return null;
15421         }
15422         if (mAttachInfo.mWindowId == null) {
15423             try {
15424                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15425                         mAttachInfo.mWindowToken);
15426                 mAttachInfo.mWindowId = new WindowId(
15427                         mAttachInfo.mIWindowId);
15428             } catch (RemoteException e) {
15429             }
15430         }
15431         return mAttachInfo.mWindowId;
15432     }
15433 
15434     /**
15435      * Retrieve a unique token identifying the top-level "real" window of
15436      * the window that this view is attached to.  That is, this is like
15437      * {@link #getWindowToken}, except if the window this view in is a panel
15438      * window (attached to another containing window), then the token of
15439      * the containing window is returned instead.
15440      *
15441      * @return Returns the associated window token, either
15442      * {@link #getWindowToken()} or the containing window's token.
15443      */
getApplicationWindowToken()15444     public IBinder getApplicationWindowToken() {
15445         AttachInfo ai = mAttachInfo;
15446         if (ai != null) {
15447             IBinder appWindowToken = ai.mPanelParentWindowToken;
15448             if (appWindowToken == null) {
15449                 appWindowToken = ai.mWindowToken;
15450             }
15451             return appWindowToken;
15452         }
15453         return null;
15454     }
15455 
15456     /**
15457      * Gets the logical display to which the view's window has been attached.
15458      *
15459      * @return The logical display, or null if the view is not currently attached to a window.
15460      */
getDisplay()15461     public Display getDisplay() {
15462         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15463     }
15464 
15465     /**
15466      * Retrieve private session object this view hierarchy is using to
15467      * communicate with the window manager.
15468      * @return the session object to communicate with the window manager
15469      */
getWindowSession()15470     /*package*/ IWindowSession getWindowSession() {
15471         return mAttachInfo != null ? mAttachInfo.mSession : null;
15472     }
15473 
15474     /**
15475      * Return the visibility value of the least visible component passed.
15476      */
combineVisibility(int vis1, int vis2)15477     int combineVisibility(int vis1, int vis2) {
15478         // This works because VISIBLE < INVISIBLE < GONE.
15479         return Math.max(vis1, vis2);
15480     }
15481 
15482     /**
15483      * @param info the {@link android.view.View.AttachInfo} to associated with
15484      *        this view
15485      */
dispatchAttachedToWindow(AttachInfo info, int visibility)15486     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15487         mAttachInfo = info;
15488         if (mOverlay != null) {
15489             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15490         }
15491         mWindowAttachCount++;
15492         // We will need to evaluate the drawable state at least once.
15493         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15494         if (mFloatingTreeObserver != null) {
15495             info.mTreeObserver.merge(mFloatingTreeObserver);
15496             mFloatingTreeObserver = null;
15497         }
15498 
15499         registerPendingFrameMetricsObservers();
15500 
15501         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15502             mAttachInfo.mScrollContainers.add(this);
15503             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15504         }
15505         // Transfer all pending runnables.
15506         if (mRunQueue != null) {
15507             mRunQueue.executeActions(info.mHandler);
15508             mRunQueue = null;
15509         }
15510         performCollectViewAttributes(mAttachInfo, visibility);
15511         onAttachedToWindow();
15512 
15513         ListenerInfo li = mListenerInfo;
15514         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15515                 li != null ? li.mOnAttachStateChangeListeners : null;
15516         if (listeners != null && listeners.size() > 0) {
15517             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15518             // perform the dispatching. The iterator is a safe guard against listeners that
15519             // could mutate the list by calling the various add/remove methods. This prevents
15520             // the array from being modified while we iterate it.
15521             for (OnAttachStateChangeListener listener : listeners) {
15522                 listener.onViewAttachedToWindow(this);
15523             }
15524         }
15525 
15526         int vis = info.mWindowVisibility;
15527         if (vis != GONE) {
15528             onWindowVisibilityChanged(vis);
15529             if (isShown()) {
15530                 // Calling onVisibilityAggregated directly here since the subtree will also
15531                 // receive dispatchAttachedToWindow and this same call
15532                 onVisibilityAggregated(vis == VISIBLE);
15533             }
15534         }
15535 
15536         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15537         // As all views in the subtree will already receive dispatchAttachedToWindow
15538         // traversing the subtree again here is not desired.
15539         onVisibilityChanged(this, visibility);
15540 
15541         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15542             // If nobody has evaluated the drawable state yet, then do it now.
15543             refreshDrawableState();
15544         }
15545         needGlobalAttributesUpdate(false);
15546     }
15547 
dispatchDetachedFromWindow()15548     void dispatchDetachedFromWindow() {
15549         AttachInfo info = mAttachInfo;
15550         if (info != null) {
15551             int vis = info.mWindowVisibility;
15552             if (vis != GONE) {
15553                 onWindowVisibilityChanged(GONE);
15554                 if (isShown()) {
15555                     // Invoking onVisibilityAggregated directly here since the subtree
15556                     // will also receive detached from window
15557                     onVisibilityAggregated(false);
15558                 }
15559             }
15560         }
15561 
15562         onDetachedFromWindow();
15563         onDetachedFromWindowInternal();
15564 
15565         InputMethodManager imm = InputMethodManager.peekInstance();
15566         if (imm != null) {
15567             imm.onViewDetachedFromWindow(this);
15568         }
15569 
15570         ListenerInfo li = mListenerInfo;
15571         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15572                 li != null ? li.mOnAttachStateChangeListeners : null;
15573         if (listeners != null && listeners.size() > 0) {
15574             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15575             // perform the dispatching. The iterator is a safe guard against listeners that
15576             // could mutate the list by calling the various add/remove methods. This prevents
15577             // the array from being modified while we iterate it.
15578             for (OnAttachStateChangeListener listener : listeners) {
15579                 listener.onViewDetachedFromWindow(this);
15580             }
15581         }
15582 
15583         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15584             mAttachInfo.mScrollContainers.remove(this);
15585             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15586         }
15587 
15588         mAttachInfo = null;
15589         if (mOverlay != null) {
15590             mOverlay.getOverlayView().dispatchDetachedFromWindow();
15591         }
15592     }
15593 
15594     /**
15595      * Cancel any deferred high-level input events that were previously posted to the event queue.
15596      *
15597      * <p>Many views post high-level events such as click handlers to the event queue
15598      * to run deferred in order to preserve a desired user experience - clearing visible
15599      * pressed states before executing, etc. This method will abort any events of this nature
15600      * that are currently in flight.</p>
15601      *
15602      * <p>Custom views that generate their own high-level deferred input events should override
15603      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15604      *
15605      * <p>This will also cancel pending input events for any child views.</p>
15606      *
15607      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15608      * This will not impact newer events posted after this call that may occur as a result of
15609      * lower-level input events still waiting in the queue. If you are trying to prevent
15610      * double-submitted  events for the duration of some sort of asynchronous transaction
15611      * you should also take other steps to protect against unexpected double inputs e.g. calling
15612      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15613      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15614      */
cancelPendingInputEvents()15615     public final void cancelPendingInputEvents() {
15616         dispatchCancelPendingInputEvents();
15617     }
15618 
15619     /**
15620      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15621      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15622      */
dispatchCancelPendingInputEvents()15623     void dispatchCancelPendingInputEvents() {
15624         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15625         onCancelPendingInputEvents();
15626         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15627             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15628                     " did not call through to super.onCancelPendingInputEvents()");
15629         }
15630     }
15631 
15632     /**
15633      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15634      * a parent view.
15635      *
15636      * <p>This method is responsible for removing any pending high-level input events that were
15637      * posted to the event queue to run later. Custom view classes that post their own deferred
15638      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15639      * {@link android.os.Handler} should override this method, call
15640      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15641      * </p>
15642      */
onCancelPendingInputEvents()15643     public void onCancelPendingInputEvents() {
15644         removePerformClickCallback();
15645         cancelLongPress();
15646         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15647     }
15648 
15649     /**
15650      * Store this view hierarchy's frozen state into the given container.
15651      *
15652      * @param container The SparseArray in which to save the view's state.
15653      *
15654      * @see #restoreHierarchyState(android.util.SparseArray)
15655      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15656      * @see #onSaveInstanceState()
15657      */
saveHierarchyState(SparseArray<Parcelable> container)15658     public void saveHierarchyState(SparseArray<Parcelable> container) {
15659         dispatchSaveInstanceState(container);
15660     }
15661 
15662     /**
15663      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15664      * this view and its children. May be overridden to modify how freezing happens to a
15665      * view's children; for example, some views may want to not store state for their children.
15666      *
15667      * @param container The SparseArray in which to save the view's state.
15668      *
15669      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15670      * @see #saveHierarchyState(android.util.SparseArray)
15671      * @see #onSaveInstanceState()
15672      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)15673     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15674         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15675             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15676             Parcelable state = onSaveInstanceState();
15677             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15678                 throw new IllegalStateException(
15679                         "Derived class did not call super.onSaveInstanceState()");
15680             }
15681             if (state != null) {
15682                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15683                 // + ": " + state);
15684                 container.put(mID, state);
15685             }
15686         }
15687     }
15688 
15689     /**
15690      * Hook allowing a view to generate a representation of its internal state
15691      * that can later be used to create a new instance with that same state.
15692      * This state should only contain information that is not persistent or can
15693      * not be reconstructed later. For example, you will never store your
15694      * current position on screen because that will be computed again when a
15695      * new instance of the view is placed in its view hierarchy.
15696      * <p>
15697      * Some examples of things you may store here: the current cursor position
15698      * in a text view (but usually not the text itself since that is stored in a
15699      * content provider or other persistent storage), the currently selected
15700      * item in a list view.
15701      *
15702      * @return Returns a Parcelable object containing the view's current dynamic
15703      *         state, or null if there is nothing interesting to save. The
15704      *         default implementation returns null.
15705      * @see #onRestoreInstanceState(android.os.Parcelable)
15706      * @see #saveHierarchyState(android.util.SparseArray)
15707      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15708      * @see #setSaveEnabled(boolean)
15709      */
15710     @CallSuper
onSaveInstanceState()15711     protected Parcelable onSaveInstanceState() {
15712         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15713         if (mStartActivityRequestWho != null) {
15714             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15715             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15716             return state;
15717         }
15718         return BaseSavedState.EMPTY_STATE;
15719     }
15720 
15721     /**
15722      * Restore this view hierarchy's frozen state from the given container.
15723      *
15724      * @param container The SparseArray which holds previously frozen states.
15725      *
15726      * @see #saveHierarchyState(android.util.SparseArray)
15727      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15728      * @see #onRestoreInstanceState(android.os.Parcelable)
15729      */
restoreHierarchyState(SparseArray<Parcelable> container)15730     public void restoreHierarchyState(SparseArray<Parcelable> container) {
15731         dispatchRestoreInstanceState(container);
15732     }
15733 
15734     /**
15735      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15736      * state for this view and its children. May be overridden to modify how restoring
15737      * happens to a view's children; for example, some views may want to not store state
15738      * for their children.
15739      *
15740      * @param container The SparseArray which holds previously saved state.
15741      *
15742      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15743      * @see #restoreHierarchyState(android.util.SparseArray)
15744      * @see #onRestoreInstanceState(android.os.Parcelable)
15745      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)15746     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15747         if (mID != NO_ID) {
15748             Parcelable state = container.get(mID);
15749             if (state != null) {
15750                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15751                 // + ": " + state);
15752                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15753                 onRestoreInstanceState(state);
15754                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15755                     throw new IllegalStateException(
15756                             "Derived class did not call super.onRestoreInstanceState()");
15757                 }
15758             }
15759         }
15760     }
15761 
15762     /**
15763      * Hook allowing a view to re-apply a representation of its internal state that had previously
15764      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15765      * null state.
15766      *
15767      * @param state The frozen state that had previously been returned by
15768      *        {@link #onSaveInstanceState}.
15769      *
15770      * @see #onSaveInstanceState()
15771      * @see #restoreHierarchyState(android.util.SparseArray)
15772      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15773      */
15774     @CallSuper
onRestoreInstanceState(Parcelable state)15775     protected void onRestoreInstanceState(Parcelable state) {
15776         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15777         if (state != null && !(state instanceof AbsSavedState)) {
15778             throw new IllegalArgumentException("Wrong state class, expecting View State but "
15779                     + "received " + state.getClass().toString() + " instead. This usually happens "
15780                     + "when two views of different type have the same id in the same hierarchy. "
15781                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15782                     + "other views do not use the same id.");
15783         }
15784         if (state != null && state instanceof BaseSavedState) {
15785             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15786         }
15787     }
15788 
15789     /**
15790      * <p>Return the time at which the drawing of the view hierarchy started.</p>
15791      *
15792      * @return the drawing start time in milliseconds
15793      */
getDrawingTime()15794     public long getDrawingTime() {
15795         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15796     }
15797 
15798     /**
15799      * <p>Enables or disables the duplication of the parent's state into this view. When
15800      * duplication is enabled, this view gets its drawable state from its parent rather
15801      * than from its own internal properties.</p>
15802      *
15803      * <p>Note: in the current implementation, setting this property to true after the
15804      * view was added to a ViewGroup might have no effect at all. This property should
15805      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15806      *
15807      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15808      * property is enabled, an exception will be thrown.</p>
15809      *
15810      * <p>Note: if the child view uses and updates additional states which are unknown to the
15811      * parent, these states should not be affected by this method.</p>
15812      *
15813      * @param enabled True to enable duplication of the parent's drawable state, false
15814      *                to disable it.
15815      *
15816      * @see #getDrawableState()
15817      * @see #isDuplicateParentStateEnabled()
15818      */
setDuplicateParentStateEnabled(boolean enabled)15819     public void setDuplicateParentStateEnabled(boolean enabled) {
15820         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15821     }
15822 
15823     /**
15824      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15825      *
15826      * @return True if this view's drawable state is duplicated from the parent,
15827      *         false otherwise
15828      *
15829      * @see #getDrawableState()
15830      * @see #setDuplicateParentStateEnabled(boolean)
15831      */
isDuplicateParentStateEnabled()15832     public boolean isDuplicateParentStateEnabled() {
15833         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15834     }
15835 
15836     /**
15837      * <p>Specifies the type of layer backing this view. The layer can be
15838      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15839      * {@link #LAYER_TYPE_HARDWARE}.</p>
15840      *
15841      * <p>A layer is associated with an optional {@link android.graphics.Paint}
15842      * instance that controls how the layer is composed on screen. The following
15843      * properties of the paint are taken into account when composing the layer:</p>
15844      * <ul>
15845      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15846      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15847      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15848      * </ul>
15849      *
15850      * <p>If this view has an alpha value set to < 1.0 by calling
15851      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15852      * by this view's alpha value.</p>
15853      *
15854      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15855      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15856      * for more information on when and how to use layers.</p>
15857      *
15858      * @param layerType The type of layer to use with this view, must be one of
15859      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15860      *        {@link #LAYER_TYPE_HARDWARE}
15861      * @param paint The paint used to compose the layer. This argument is optional
15862      *        and can be null. It is ignored when the layer type is
15863      *        {@link #LAYER_TYPE_NONE}
15864      *
15865      * @see #getLayerType()
15866      * @see #LAYER_TYPE_NONE
15867      * @see #LAYER_TYPE_SOFTWARE
15868      * @see #LAYER_TYPE_HARDWARE
15869      * @see #setAlpha(float)
15870      *
15871      * @attr ref android.R.styleable#View_layerType
15872      */
setLayerType(int layerType, @Nullable Paint paint)15873     public void setLayerType(int layerType, @Nullable Paint paint) {
15874         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15875             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15876                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15877         }
15878 
15879         boolean typeChanged = mRenderNode.setLayerType(layerType);
15880 
15881         if (!typeChanged) {
15882             setLayerPaint(paint);
15883             return;
15884         }
15885 
15886         if (layerType != LAYER_TYPE_SOFTWARE) {
15887             // Destroy any previous software drawing cache if present
15888             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15889             // drawing cache created in View#draw when drawing to a SW canvas.
15890             destroyDrawingCache();
15891         }
15892 
15893         mLayerType = layerType;
15894         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15895         mRenderNode.setLayerPaint(mLayerPaint);
15896 
15897         // draw() behaves differently if we are on a layer, so we need to
15898         // invalidate() here
15899         invalidateParentCaches();
15900         invalidate(true);
15901     }
15902 
15903     /**
15904      * Updates the {@link Paint} object used with the current layer (used only if the current
15905      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15906      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15907      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15908      * ensure that the view gets redrawn immediately.
15909      *
15910      * <p>A layer is associated with an optional {@link android.graphics.Paint}
15911      * instance that controls how the layer is composed on screen. The following
15912      * properties of the paint are taken into account when composing the layer:</p>
15913      * <ul>
15914      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15915      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15916      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15917      * </ul>
15918      *
15919      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15920      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15921      *
15922      * @param paint The paint used to compose the layer. This argument is optional
15923      *        and can be null. It is ignored when the layer type is
15924      *        {@link #LAYER_TYPE_NONE}
15925      *
15926      * @see #setLayerType(int, android.graphics.Paint)
15927      */
setLayerPaint(@ullable Paint paint)15928     public void setLayerPaint(@Nullable Paint paint) {
15929         int layerType = getLayerType();
15930         if (layerType != LAYER_TYPE_NONE) {
15931             mLayerPaint = paint;
15932             if (layerType == LAYER_TYPE_HARDWARE) {
15933                 if (mRenderNode.setLayerPaint(paint)) {
15934                     invalidateViewProperty(false, false);
15935                 }
15936             } else {
15937                 invalidate();
15938             }
15939         }
15940     }
15941 
15942     /**
15943      * Indicates what type of layer is currently associated with this view. By default
15944      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15945      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15946      * for more information on the different types of layers.
15947      *
15948      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15949      *         {@link #LAYER_TYPE_HARDWARE}
15950      *
15951      * @see #setLayerType(int, android.graphics.Paint)
15952      * @see #buildLayer()
15953      * @see #LAYER_TYPE_NONE
15954      * @see #LAYER_TYPE_SOFTWARE
15955      * @see #LAYER_TYPE_HARDWARE
15956      */
getLayerType()15957     public int getLayerType() {
15958         return mLayerType;
15959     }
15960 
15961     /**
15962      * Forces this view's layer to be created and this view to be rendered
15963      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15964      * invoking this method will have no effect.
15965      *
15966      * This method can for instance be used to render a view into its layer before
15967      * starting an animation. If this view is complex, rendering into the layer
15968      * before starting the animation will avoid skipping frames.
15969      *
15970      * @throws IllegalStateException If this view is not attached to a window
15971      *
15972      * @see #setLayerType(int, android.graphics.Paint)
15973      */
buildLayer()15974     public void buildLayer() {
15975         if (mLayerType == LAYER_TYPE_NONE) return;
15976 
15977         final AttachInfo attachInfo = mAttachInfo;
15978         if (attachInfo == null) {
15979             throw new IllegalStateException("This view must be attached to a window first");
15980         }
15981 
15982         if (getWidth() == 0 || getHeight() == 0) {
15983             return;
15984         }
15985 
15986         switch (mLayerType) {
15987             case LAYER_TYPE_HARDWARE:
15988                 updateDisplayListIfDirty();
15989                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15990                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15991                 }
15992                 break;
15993             case LAYER_TYPE_SOFTWARE:
15994                 buildDrawingCache(true);
15995                 break;
15996         }
15997     }
15998 
15999     /**
16000      * Destroys all hardware rendering resources. This method is invoked
16001      * when the system needs to reclaim resources. Upon execution of this
16002      * method, you should free any OpenGL resources created by the view.
16003      *
16004      * Note: you <strong>must</strong> call
16005      * <code>super.destroyHardwareResources()</code> when overriding
16006      * this method.
16007      *
16008      * @hide
16009      */
16010     @CallSuper
destroyHardwareResources()16011     protected void destroyHardwareResources() {
16012         // Although the Layer will be destroyed by RenderNode, we want to release
16013         // the staging display list, which is also a signal to RenderNode that it's
16014         // safe to free its copy of the display list as it knows that we will
16015         // push an updated DisplayList if we try to draw again
16016         resetDisplayList();
16017     }
16018 
16019     /**
16020      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16021      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16022      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16023      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16024      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16025      * null.</p>
16026      *
16027      * <p>Enabling the drawing cache is similar to
16028      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16029      * acceleration is turned off. When hardware acceleration is turned on, enabling the
16030      * drawing cache has no effect on rendering because the system uses a different mechanism
16031      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16032      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16033      * for information on how to enable software and hardware layers.</p>
16034      *
16035      * <p>This API can be used to manually generate
16036      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16037      * {@link #getDrawingCache()}.</p>
16038      *
16039      * @param enabled true to enable the drawing cache, false otherwise
16040      *
16041      * @see #isDrawingCacheEnabled()
16042      * @see #getDrawingCache()
16043      * @see #buildDrawingCache()
16044      * @see #setLayerType(int, android.graphics.Paint)
16045      */
setDrawingCacheEnabled(boolean enabled)16046     public void setDrawingCacheEnabled(boolean enabled) {
16047         mCachingFailed = false;
16048         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16049     }
16050 
16051     /**
16052      * <p>Indicates whether the drawing cache is enabled for this view.</p>
16053      *
16054      * @return true if the drawing cache is enabled
16055      *
16056      * @see #setDrawingCacheEnabled(boolean)
16057      * @see #getDrawingCache()
16058      */
16059     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()16060     public boolean isDrawingCacheEnabled() {
16061         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16062     }
16063 
16064     /**
16065      * Debugging utility which recursively outputs the dirty state of a view and its
16066      * descendants.
16067      *
16068      * @hide
16069      */
16070     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)16071     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16072         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16073                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16074                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16075                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16076         if (clear) {
16077             mPrivateFlags &= clearMask;
16078         }
16079         if (this instanceof ViewGroup) {
16080             ViewGroup parent = (ViewGroup) this;
16081             final int count = parent.getChildCount();
16082             for (int i = 0; i < count; i++) {
16083                 final View child = parent.getChildAt(i);
16084                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
16085             }
16086         }
16087     }
16088 
16089     /**
16090      * This method is used by ViewGroup to cause its children to restore or recreate their
16091      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16092      * to recreate its own display list, which would happen if it went through the normal
16093      * draw/dispatchDraw mechanisms.
16094      *
16095      * @hide
16096      */
dispatchGetDisplayList()16097     protected void dispatchGetDisplayList() {}
16098 
16099     /**
16100      * A view that is not attached or hardware accelerated cannot create a display list.
16101      * This method checks these conditions and returns the appropriate result.
16102      *
16103      * @return true if view has the ability to create a display list, false otherwise.
16104      *
16105      * @hide
16106      */
canHaveDisplayList()16107     public boolean canHaveDisplayList() {
16108         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
16109     }
16110 
16111     /**
16112      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16113      * @hide
16114      */
16115     @NonNull
updateDisplayListIfDirty()16116     public RenderNode updateDisplayListIfDirty() {
16117         final RenderNode renderNode = mRenderNode;
16118         if (!canHaveDisplayList()) {
16119             // can't populate RenderNode, don't try
16120             return renderNode;
16121         }
16122 
16123         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16124                 || !renderNode.isValid()
16125                 || (mRecreateDisplayList)) {
16126             // Don't need to recreate the display list, just need to tell our
16127             // children to restore/recreate theirs
16128             if (renderNode.isValid()
16129                     && !mRecreateDisplayList) {
16130                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16131                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16132                 dispatchGetDisplayList();
16133 
16134                 return renderNode; // no work needed
16135             }
16136 
16137             // If we got here, we're recreating it. Mark it as such to ensure that
16138             // we copy in child display lists into ours in drawChild()
16139             mRecreateDisplayList = true;
16140 
16141             int width = mRight - mLeft;
16142             int height = mBottom - mTop;
16143             int layerType = getLayerType();
16144 
16145             final DisplayListCanvas canvas = renderNode.start(width, height);
16146             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16147 
16148             try {
16149                 if (layerType == LAYER_TYPE_SOFTWARE) {
16150                     buildDrawingCache(true);
16151                     Bitmap cache = getDrawingCache(true);
16152                     if (cache != null) {
16153                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16154                     }
16155                 } else {
16156                     computeScroll();
16157 
16158                     canvas.translate(-mScrollX, -mScrollY);
16159                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16160                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16161 
16162                     // Fast path for layouts with no backgrounds
16163                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16164                         dispatchDraw(canvas);
16165                         if (mOverlay != null && !mOverlay.isEmpty()) {
16166                             mOverlay.getOverlayView().draw(canvas);
16167                         }
16168                     } else {
16169                         draw(canvas);
16170                     }
16171                 }
16172             } finally {
16173                 renderNode.end(canvas);
16174                 setDisplayListProperties(renderNode);
16175             }
16176         } else {
16177             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16178             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16179         }
16180         return renderNode;
16181     }
16182 
resetDisplayList()16183     private void resetDisplayList() {
16184         if (mRenderNode.isValid()) {
16185             mRenderNode.discardDisplayList();
16186         }
16187 
16188         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16189             mBackgroundRenderNode.discardDisplayList();
16190         }
16191     }
16192 
16193     /**
16194      * Called when the passed RenderNode is removed from the draw tree
16195      * @hide
16196      */
onRenderNodeDetached(RenderNode renderNode)16197     public void onRenderNodeDetached(RenderNode renderNode) {
16198     }
16199 
16200     /**
16201      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16202      *
16203      * @return A non-scaled bitmap representing this view or null if cache is disabled.
16204      *
16205      * @see #getDrawingCache(boolean)
16206      */
getDrawingCache()16207     public Bitmap getDrawingCache() {
16208         return getDrawingCache(false);
16209     }
16210 
16211     /**
16212      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16213      * is null when caching is disabled. If caching is enabled and the cache is not ready,
16214      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16215      * draw from the cache when the cache is enabled. To benefit from the cache, you must
16216      * request the drawing cache by calling this method and draw it on screen if the
16217      * returned bitmap is not null.</p>
16218      *
16219      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16220      * this method will create a bitmap of the same size as this view. Because this bitmap
16221      * will be drawn scaled by the parent ViewGroup, the result on screen might show
16222      * scaling artifacts. To avoid such artifacts, you should call this method by setting
16223      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16224      * size than the view. This implies that your application must be able to handle this
16225      * size.</p>
16226      *
16227      * @param autoScale Indicates whether the generated bitmap should be scaled based on
16228      *        the current density of the screen when the application is in compatibility
16229      *        mode.
16230      *
16231      * @return A bitmap representing this view or null if cache is disabled.
16232      *
16233      * @see #setDrawingCacheEnabled(boolean)
16234      * @see #isDrawingCacheEnabled()
16235      * @see #buildDrawingCache(boolean)
16236      * @see #destroyDrawingCache()
16237      */
getDrawingCache(boolean autoScale)16238     public Bitmap getDrawingCache(boolean autoScale) {
16239         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16240             return null;
16241         }
16242         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16243             buildDrawingCache(autoScale);
16244         }
16245         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16246     }
16247 
16248     /**
16249      * <p>Frees the resources used by the drawing cache. If you call
16250      * {@link #buildDrawingCache()} manually without calling
16251      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16252      * should cleanup the cache with this method afterwards.</p>
16253      *
16254      * @see #setDrawingCacheEnabled(boolean)
16255      * @see #buildDrawingCache()
16256      * @see #getDrawingCache()
16257      */
destroyDrawingCache()16258     public void destroyDrawingCache() {
16259         if (mDrawingCache != null) {
16260             mDrawingCache.recycle();
16261             mDrawingCache = null;
16262         }
16263         if (mUnscaledDrawingCache != null) {
16264             mUnscaledDrawingCache.recycle();
16265             mUnscaledDrawingCache = null;
16266         }
16267     }
16268 
16269     /**
16270      * Setting a solid background color for the drawing cache's bitmaps will improve
16271      * performance and memory usage. Note, though that this should only be used if this
16272      * view will always be drawn on top of a solid color.
16273      *
16274      * @param color The background color to use for the drawing cache's bitmap
16275      *
16276      * @see #setDrawingCacheEnabled(boolean)
16277      * @see #buildDrawingCache()
16278      * @see #getDrawingCache()
16279      */
setDrawingCacheBackgroundColor(@olorInt int color)16280     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16281         if (color != mDrawingCacheBackgroundColor) {
16282             mDrawingCacheBackgroundColor = color;
16283             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16284         }
16285     }
16286 
16287     /**
16288      * @see #setDrawingCacheBackgroundColor(int)
16289      *
16290      * @return The background color to used for the drawing cache's bitmap
16291      */
16292     @ColorInt
getDrawingCacheBackgroundColor()16293     public int getDrawingCacheBackgroundColor() {
16294         return mDrawingCacheBackgroundColor;
16295     }
16296 
16297     /**
16298      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16299      *
16300      * @see #buildDrawingCache(boolean)
16301      */
buildDrawingCache()16302     public void buildDrawingCache() {
16303         buildDrawingCache(false);
16304     }
16305 
16306     /**
16307      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16308      *
16309      * <p>If you call {@link #buildDrawingCache()} manually without calling
16310      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16311      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16312      *
16313      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16314      * this method will create a bitmap of the same size as this view. Because this bitmap
16315      * will be drawn scaled by the parent ViewGroup, the result on screen might show
16316      * scaling artifacts. To avoid such artifacts, you should call this method by setting
16317      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16318      * size than the view. This implies that your application must be able to handle this
16319      * size.</p>
16320      *
16321      * <p>You should avoid calling this method when hardware acceleration is enabled. If
16322      * you do not need the drawing cache bitmap, calling this method will increase memory
16323      * usage and cause the view to be rendered in software once, thus negatively impacting
16324      * performance.</p>
16325      *
16326      * @see #getDrawingCache()
16327      * @see #destroyDrawingCache()
16328      */
buildDrawingCache(boolean autoScale)16329     public void buildDrawingCache(boolean autoScale) {
16330         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16331                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
16332             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16333                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16334                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16335             }
16336             try {
16337                 buildDrawingCacheImpl(autoScale);
16338             } finally {
16339                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16340             }
16341         }
16342     }
16343 
16344     /**
16345      * private, internal implementation of buildDrawingCache, used to enable tracing
16346      */
buildDrawingCacheImpl(boolean autoScale)16347     private void buildDrawingCacheImpl(boolean autoScale) {
16348         mCachingFailed = false;
16349 
16350         int width = mRight - mLeft;
16351         int height = mBottom - mTop;
16352 
16353         final AttachInfo attachInfo = mAttachInfo;
16354         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16355 
16356         if (autoScale && scalingRequired) {
16357             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16358             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16359         }
16360 
16361         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16362         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16363         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16364 
16365         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16366         final long drawingCacheSize =
16367                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16368         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16369             if (width > 0 && height > 0) {
16370                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16371                         + " too large to fit into a software layer (or drawing cache), needs "
16372                         + projectedBitmapSize + " bytes, only "
16373                         + drawingCacheSize + " available");
16374             }
16375             destroyDrawingCache();
16376             mCachingFailed = true;
16377             return;
16378         }
16379 
16380         boolean clear = true;
16381         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16382 
16383         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16384             Bitmap.Config quality;
16385             if (!opaque) {
16386                 // Never pick ARGB_4444 because it looks awful
16387                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16388                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16389                     case DRAWING_CACHE_QUALITY_AUTO:
16390                     case DRAWING_CACHE_QUALITY_LOW:
16391                     case DRAWING_CACHE_QUALITY_HIGH:
16392                     default:
16393                         quality = Bitmap.Config.ARGB_8888;
16394                         break;
16395                 }
16396             } else {
16397                 // Optimization for translucent windows
16398                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16399                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16400             }
16401 
16402             // Try to cleanup memory
16403             if (bitmap != null) bitmap.recycle();
16404 
16405             try {
16406                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16407                         width, height, quality);
16408                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16409                 if (autoScale) {
16410                     mDrawingCache = bitmap;
16411                 } else {
16412                     mUnscaledDrawingCache = bitmap;
16413                 }
16414                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16415             } catch (OutOfMemoryError e) {
16416                 // If there is not enough memory to create the bitmap cache, just
16417                 // ignore the issue as bitmap caches are not required to draw the
16418                 // view hierarchy
16419                 if (autoScale) {
16420                     mDrawingCache = null;
16421                 } else {
16422                     mUnscaledDrawingCache = null;
16423                 }
16424                 mCachingFailed = true;
16425                 return;
16426             }
16427 
16428             clear = drawingCacheBackgroundColor != 0;
16429         }
16430 
16431         Canvas canvas;
16432         if (attachInfo != null) {
16433             canvas = attachInfo.mCanvas;
16434             if (canvas == null) {
16435                 canvas = new Canvas();
16436             }
16437             canvas.setBitmap(bitmap);
16438             // Temporarily clobber the cached Canvas in case one of our children
16439             // is also using a drawing cache. Without this, the children would
16440             // steal the canvas by attaching their own bitmap to it and bad, bad
16441             // thing would happen (invisible views, corrupted drawings, etc.)
16442             attachInfo.mCanvas = null;
16443         } else {
16444             // This case should hopefully never or seldom happen
16445             canvas = new Canvas(bitmap);
16446         }
16447 
16448         if (clear) {
16449             bitmap.eraseColor(drawingCacheBackgroundColor);
16450         }
16451 
16452         computeScroll();
16453         final int restoreCount = canvas.save();
16454 
16455         if (autoScale && scalingRequired) {
16456             final float scale = attachInfo.mApplicationScale;
16457             canvas.scale(scale, scale);
16458         }
16459 
16460         canvas.translate(-mScrollX, -mScrollY);
16461 
16462         mPrivateFlags |= PFLAG_DRAWN;
16463         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16464                 mLayerType != LAYER_TYPE_NONE) {
16465             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16466         }
16467 
16468         // Fast path for layouts with no backgrounds
16469         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16470             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16471             dispatchDraw(canvas);
16472             if (mOverlay != null && !mOverlay.isEmpty()) {
16473                 mOverlay.getOverlayView().draw(canvas);
16474             }
16475         } else {
16476             draw(canvas);
16477         }
16478 
16479         canvas.restoreToCount(restoreCount);
16480         canvas.setBitmap(null);
16481 
16482         if (attachInfo != null) {
16483             // Restore the cached Canvas for our siblings
16484             attachInfo.mCanvas = canvas;
16485         }
16486     }
16487 
16488     /**
16489      * Create a snapshot of the view into a bitmap.  We should probably make
16490      * some form of this public, but should think about the API.
16491      *
16492      * @hide
16493      */
createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren)16494     public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16495         int width = mRight - mLeft;
16496         int height = mBottom - mTop;
16497 
16498         final AttachInfo attachInfo = mAttachInfo;
16499         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16500         width = (int) ((width * scale) + 0.5f);
16501         height = (int) ((height * scale) + 0.5f);
16502 
16503         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16504                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
16505         if (bitmap == null) {
16506             throw new OutOfMemoryError();
16507         }
16508 
16509         Resources resources = getResources();
16510         if (resources != null) {
16511             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16512         }
16513 
16514         Canvas canvas;
16515         if (attachInfo != null) {
16516             canvas = attachInfo.mCanvas;
16517             if (canvas == null) {
16518                 canvas = new Canvas();
16519             }
16520             canvas.setBitmap(bitmap);
16521             // Temporarily clobber the cached Canvas in case one of our children
16522             // is also using a drawing cache. Without this, the children would
16523             // steal the canvas by attaching their own bitmap to it and bad, bad
16524             // things would happen (invisible views, corrupted drawings, etc.)
16525             attachInfo.mCanvas = null;
16526         } else {
16527             // This case should hopefully never or seldom happen
16528             canvas = new Canvas(bitmap);
16529         }
16530 
16531         if ((backgroundColor & 0xff000000) != 0) {
16532             bitmap.eraseColor(backgroundColor);
16533         }
16534 
16535         computeScroll();
16536         final int restoreCount = canvas.save();
16537         canvas.scale(scale, scale);
16538         canvas.translate(-mScrollX, -mScrollY);
16539 
16540         // Temporarily remove the dirty mask
16541         int flags = mPrivateFlags;
16542         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16543 
16544         // Fast path for layouts with no backgrounds
16545         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16546             dispatchDraw(canvas);
16547             if (mOverlay != null && !mOverlay.isEmpty()) {
16548                 mOverlay.getOverlayView().draw(canvas);
16549             }
16550         } else {
16551             draw(canvas);
16552         }
16553 
16554         mPrivateFlags = flags;
16555 
16556         canvas.restoreToCount(restoreCount);
16557         canvas.setBitmap(null);
16558 
16559         if (attachInfo != null) {
16560             // Restore the cached Canvas for our siblings
16561             attachInfo.mCanvas = canvas;
16562         }
16563 
16564         return bitmap;
16565     }
16566 
16567     /**
16568      * Indicates whether this View is currently in edit mode. A View is usually
16569      * in edit mode when displayed within a developer tool. For instance, if
16570      * this View is being drawn by a visual user interface builder, this method
16571      * should return true.
16572      *
16573      * Subclasses should check the return value of this method to provide
16574      * different behaviors if their normal behavior might interfere with the
16575      * host environment. For instance: the class spawns a thread in its
16576      * constructor, the drawing code relies on device-specific features, etc.
16577      *
16578      * This method is usually checked in the drawing code of custom widgets.
16579      *
16580      * @return True if this View is in edit mode, false otherwise.
16581      */
isInEditMode()16582     public boolean isInEditMode() {
16583         return false;
16584     }
16585 
16586     /**
16587      * If the View draws content inside its padding and enables fading edges,
16588      * it needs to support padding offsets. Padding offsets are added to the
16589      * fading edges to extend the length of the fade so that it covers pixels
16590      * drawn inside the padding.
16591      *
16592      * Subclasses of this class should override this method if they need
16593      * to draw content inside the padding.
16594      *
16595      * @return True if padding offset must be applied, false otherwise.
16596      *
16597      * @see #getLeftPaddingOffset()
16598      * @see #getRightPaddingOffset()
16599      * @see #getTopPaddingOffset()
16600      * @see #getBottomPaddingOffset()
16601      *
16602      * @since CURRENT
16603      */
isPaddingOffsetRequired()16604     protected boolean isPaddingOffsetRequired() {
16605         return false;
16606     }
16607 
16608     /**
16609      * Amount by which to extend the left fading region. Called only when
16610      * {@link #isPaddingOffsetRequired()} returns true.
16611      *
16612      * @return The left padding offset in pixels.
16613      *
16614      * @see #isPaddingOffsetRequired()
16615      *
16616      * @since CURRENT
16617      */
getLeftPaddingOffset()16618     protected int getLeftPaddingOffset() {
16619         return 0;
16620     }
16621 
16622     /**
16623      * Amount by which to extend the right fading region. Called only when
16624      * {@link #isPaddingOffsetRequired()} returns true.
16625      *
16626      * @return The right padding offset in pixels.
16627      *
16628      * @see #isPaddingOffsetRequired()
16629      *
16630      * @since CURRENT
16631      */
getRightPaddingOffset()16632     protected int getRightPaddingOffset() {
16633         return 0;
16634     }
16635 
16636     /**
16637      * Amount by which to extend the top fading region. Called only when
16638      * {@link #isPaddingOffsetRequired()} returns true.
16639      *
16640      * @return The top padding offset in pixels.
16641      *
16642      * @see #isPaddingOffsetRequired()
16643      *
16644      * @since CURRENT
16645      */
getTopPaddingOffset()16646     protected int getTopPaddingOffset() {
16647         return 0;
16648     }
16649 
16650     /**
16651      * Amount by which to extend the bottom fading region. Called only when
16652      * {@link #isPaddingOffsetRequired()} returns true.
16653      *
16654      * @return The bottom padding offset in pixels.
16655      *
16656      * @see #isPaddingOffsetRequired()
16657      *
16658      * @since CURRENT
16659      */
getBottomPaddingOffset()16660     protected int getBottomPaddingOffset() {
16661         return 0;
16662     }
16663 
16664     /**
16665      * @hide
16666      * @param offsetRequired
16667      */
getFadeTop(boolean offsetRequired)16668     protected int getFadeTop(boolean offsetRequired) {
16669         int top = mPaddingTop;
16670         if (offsetRequired) top += getTopPaddingOffset();
16671         return top;
16672     }
16673 
16674     /**
16675      * @hide
16676      * @param offsetRequired
16677      */
getFadeHeight(boolean offsetRequired)16678     protected int getFadeHeight(boolean offsetRequired) {
16679         int padding = mPaddingTop;
16680         if (offsetRequired) padding += getTopPaddingOffset();
16681         return mBottom - mTop - mPaddingBottom - padding;
16682     }
16683 
16684     /**
16685      * <p>Indicates whether this view is attached to a hardware accelerated
16686      * window or not.</p>
16687      *
16688      * <p>Even if this method returns true, it does not mean that every call
16689      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16690      * accelerated {@link android.graphics.Canvas}. For instance, if this view
16691      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16692      * window is hardware accelerated,
16693      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16694      * return false, and this method will return true.</p>
16695      *
16696      * @return True if the view is attached to a window and the window is
16697      *         hardware accelerated; false in any other case.
16698      */
16699     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()16700     public boolean isHardwareAccelerated() {
16701         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16702     }
16703 
16704     /**
16705      * Sets a rectangular area on this view to which the view will be clipped
16706      * when it is drawn. Setting the value to null will remove the clip bounds
16707      * and the view will draw normally, using its full bounds.
16708      *
16709      * @param clipBounds The rectangular area, in the local coordinates of
16710      * this view, to which future drawing operations will be clipped.
16711      */
setClipBounds(Rect clipBounds)16712     public void setClipBounds(Rect clipBounds) {
16713         if (clipBounds == mClipBounds
16714                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16715             return;
16716         }
16717         if (clipBounds != null) {
16718             if (mClipBounds == null) {
16719                 mClipBounds = new Rect(clipBounds);
16720             } else {
16721                 mClipBounds.set(clipBounds);
16722             }
16723         } else {
16724             mClipBounds = null;
16725         }
16726         mRenderNode.setClipBounds(mClipBounds);
16727         invalidateViewProperty(false, false);
16728     }
16729 
16730     /**
16731      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16732      *
16733      * @return A copy of the current clip bounds if clip bounds are set,
16734      * otherwise null.
16735      */
getClipBounds()16736     public Rect getClipBounds() {
16737         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16738     }
16739 
16740 
16741     /**
16742      * Populates an output rectangle with the clip bounds of the view,
16743      * returning {@code true} if successful or {@code false} if the view's
16744      * clip bounds are {@code null}.
16745      *
16746      * @param outRect rectangle in which to place the clip bounds of the view
16747      * @return {@code true} if successful or {@code false} if the view's
16748      *         clip bounds are {@code null}
16749      */
getClipBounds(Rect outRect)16750     public boolean getClipBounds(Rect outRect) {
16751         if (mClipBounds != null) {
16752             outRect.set(mClipBounds);
16753             return true;
16754         }
16755         return false;
16756     }
16757 
16758     /**
16759      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16760      * case of an active Animation being run on the view.
16761      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)16762     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16763             Animation a, boolean scalingRequired) {
16764         Transformation invalidationTransform;
16765         final int flags = parent.mGroupFlags;
16766         final boolean initialized = a.isInitialized();
16767         if (!initialized) {
16768             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16769             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16770             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16771             onAnimationStart();
16772         }
16773 
16774         final Transformation t = parent.getChildTransformation();
16775         boolean more = a.getTransformation(drawingTime, t, 1f);
16776         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16777             if (parent.mInvalidationTransformation == null) {
16778                 parent.mInvalidationTransformation = new Transformation();
16779             }
16780             invalidationTransform = parent.mInvalidationTransformation;
16781             a.getTransformation(drawingTime, invalidationTransform, 1f);
16782         } else {
16783             invalidationTransform = t;
16784         }
16785 
16786         if (more) {
16787             if (!a.willChangeBounds()) {
16788                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16789                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16790                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16791                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16792                     // The child need to draw an animation, potentially offscreen, so
16793                     // make sure we do not cancel invalidate requests
16794                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16795                     parent.invalidate(mLeft, mTop, mRight, mBottom);
16796                 }
16797             } else {
16798                 if (parent.mInvalidateRegion == null) {
16799                     parent.mInvalidateRegion = new RectF();
16800                 }
16801                 final RectF region = parent.mInvalidateRegion;
16802                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16803                         invalidationTransform);
16804 
16805                 // The child need to draw an animation, potentially offscreen, so
16806                 // make sure we do not cancel invalidate requests
16807                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16808 
16809                 final int left = mLeft + (int) region.left;
16810                 final int top = mTop + (int) region.top;
16811                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
16812                         top + (int) (region.height() + .5f));
16813             }
16814         }
16815         return more;
16816     }
16817 
16818     /**
16819      * This method is called by getDisplayList() when a display list is recorded for a View.
16820      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16821      */
setDisplayListProperties(RenderNode renderNode)16822     void setDisplayListProperties(RenderNode renderNode) {
16823         if (renderNode != null) {
16824             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16825             renderNode.setClipToBounds(mParent instanceof ViewGroup
16826                     && ((ViewGroup) mParent).getClipChildren());
16827 
16828             float alpha = 1;
16829             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16830                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16831                 ViewGroup parentVG = (ViewGroup) mParent;
16832                 final Transformation t = parentVG.getChildTransformation();
16833                 if (parentVG.getChildStaticTransformation(this, t)) {
16834                     final int transformType = t.getTransformationType();
16835                     if (transformType != Transformation.TYPE_IDENTITY) {
16836                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16837                             alpha = t.getAlpha();
16838                         }
16839                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16840                             renderNode.setStaticMatrix(t.getMatrix());
16841                         }
16842                     }
16843                 }
16844             }
16845             if (mTransformationInfo != null) {
16846                 alpha *= getFinalAlpha();
16847                 if (alpha < 1) {
16848                     final int multipliedAlpha = (int) (255 * alpha);
16849                     if (onSetAlpha(multipliedAlpha)) {
16850                         alpha = 1;
16851                     }
16852                 }
16853                 renderNode.setAlpha(alpha);
16854             } else if (alpha < 1) {
16855                 renderNode.setAlpha(alpha);
16856             }
16857         }
16858     }
16859 
16860     /**
16861      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16862      *
16863      * This is where the View specializes rendering behavior based on layer type,
16864      * and hardware acceleration.
16865      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)16866     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16867         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16868         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16869          *
16870          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16871          * HW accelerated, it can't handle drawing RenderNodes.
16872          */
16873         boolean drawingWithRenderNode = mAttachInfo != null
16874                 && mAttachInfo.mHardwareAccelerated
16875                 && hardwareAcceleratedCanvas;
16876 
16877         boolean more = false;
16878         final boolean childHasIdentityMatrix = hasIdentityMatrix();
16879         final int parentFlags = parent.mGroupFlags;
16880 
16881         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16882             parent.getChildTransformation().clear();
16883             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16884         }
16885 
16886         Transformation transformToApply = null;
16887         boolean concatMatrix = false;
16888         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16889         final Animation a = getAnimation();
16890         if (a != null) {
16891             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16892             concatMatrix = a.willChangeTransformationMatrix();
16893             if (concatMatrix) {
16894                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16895             }
16896             transformToApply = parent.getChildTransformation();
16897         } else {
16898             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16899                 // No longer animating: clear out old animation matrix
16900                 mRenderNode.setAnimationMatrix(null);
16901                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16902             }
16903             if (!drawingWithRenderNode
16904                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16905                 final Transformation t = parent.getChildTransformation();
16906                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16907                 if (hasTransform) {
16908                     final int transformType = t.getTransformationType();
16909                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16910                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16911                 }
16912             }
16913         }
16914 
16915         concatMatrix |= !childHasIdentityMatrix;
16916 
16917         // Sets the flag as early as possible to allow draw() implementations
16918         // to call invalidate() successfully when doing animations
16919         mPrivateFlags |= PFLAG_DRAWN;
16920 
16921         if (!concatMatrix &&
16922                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16923                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16924                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16925                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16926             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16927             return more;
16928         }
16929         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16930 
16931         if (hardwareAcceleratedCanvas) {
16932             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16933             // retain the flag's value temporarily in the mRecreateDisplayList flag
16934             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16935             mPrivateFlags &= ~PFLAG_INVALIDATED;
16936         }
16937 
16938         RenderNode renderNode = null;
16939         Bitmap cache = null;
16940         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16941         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16942              if (layerType != LAYER_TYPE_NONE) {
16943                  // If not drawing with RenderNode, treat HW layers as SW
16944                  layerType = LAYER_TYPE_SOFTWARE;
16945                  buildDrawingCache(true);
16946             }
16947             cache = getDrawingCache(true);
16948         }
16949 
16950         if (drawingWithRenderNode) {
16951             // Delay getting the display list until animation-driven alpha values are
16952             // set up and possibly passed on to the view
16953             renderNode = updateDisplayListIfDirty();
16954             if (!renderNode.isValid()) {
16955                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
16956                 // to getDisplayList(), the display list will be marked invalid and we should not
16957                 // try to use it again.
16958                 renderNode = null;
16959                 drawingWithRenderNode = false;
16960             }
16961         }
16962 
16963         int sx = 0;
16964         int sy = 0;
16965         if (!drawingWithRenderNode) {
16966             computeScroll();
16967             sx = mScrollX;
16968             sy = mScrollY;
16969         }
16970 
16971         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16972         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16973 
16974         int restoreTo = -1;
16975         if (!drawingWithRenderNode || transformToApply != null) {
16976             restoreTo = canvas.save();
16977         }
16978         if (offsetForScroll) {
16979             canvas.translate(mLeft - sx, mTop - sy);
16980         } else {
16981             if (!drawingWithRenderNode) {
16982                 canvas.translate(mLeft, mTop);
16983             }
16984             if (scalingRequired) {
16985                 if (drawingWithRenderNode) {
16986                     // TODO: Might not need this if we put everything inside the DL
16987                     restoreTo = canvas.save();
16988                 }
16989                 // mAttachInfo cannot be null, otherwise scalingRequired == false
16990                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
16991                 canvas.scale(scale, scale);
16992             }
16993         }
16994 
16995         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16996         if (transformToApply != null
16997                 || alpha < 1
16998                 || !hasIdentityMatrix()
16999                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17000             if (transformToApply != null || !childHasIdentityMatrix) {
17001                 int transX = 0;
17002                 int transY = 0;
17003 
17004                 if (offsetForScroll) {
17005                     transX = -sx;
17006                     transY = -sy;
17007                 }
17008 
17009                 if (transformToApply != null) {
17010                     if (concatMatrix) {
17011                         if (drawingWithRenderNode) {
17012                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
17013                         } else {
17014                             // Undo the scroll translation, apply the transformation matrix,
17015                             // then redo the scroll translate to get the correct result.
17016                             canvas.translate(-transX, -transY);
17017                             canvas.concat(transformToApply.getMatrix());
17018                             canvas.translate(transX, transY);
17019                         }
17020                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17021                     }
17022 
17023                     float transformAlpha = transformToApply.getAlpha();
17024                     if (transformAlpha < 1) {
17025                         alpha *= transformAlpha;
17026                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17027                     }
17028                 }
17029 
17030                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17031                     canvas.translate(-transX, -transY);
17032                     canvas.concat(getMatrix());
17033                     canvas.translate(transX, transY);
17034                 }
17035             }
17036 
17037             // Deal with alpha if it is or used to be <1
17038             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17039                 if (alpha < 1) {
17040                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17041                 } else {
17042                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17043                 }
17044                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17045                 if (!drawingWithDrawingCache) {
17046                     final int multipliedAlpha = (int) (255 * alpha);
17047                     if (!onSetAlpha(multipliedAlpha)) {
17048                         if (drawingWithRenderNode) {
17049                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17050                         } else if (layerType == LAYER_TYPE_NONE) {
17051                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17052                                     multipliedAlpha);
17053                         }
17054                     } else {
17055                         // Alpha is handled by the child directly, clobber the layer's alpha
17056                         mPrivateFlags |= PFLAG_ALPHA_SET;
17057                     }
17058                 }
17059             }
17060         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17061             onSetAlpha(255);
17062             mPrivateFlags &= ~PFLAG_ALPHA_SET;
17063         }
17064 
17065         if (!drawingWithRenderNode) {
17066             // apply clips directly, since RenderNode won't do it for this draw
17067             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17068                 if (offsetForScroll) {
17069                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17070                 } else {
17071                     if (!scalingRequired || cache == null) {
17072                         canvas.clipRect(0, 0, getWidth(), getHeight());
17073                     } else {
17074                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17075                     }
17076                 }
17077             }
17078 
17079             if (mClipBounds != null) {
17080                 // clip bounds ignore scroll
17081                 canvas.clipRect(mClipBounds);
17082             }
17083         }
17084 
17085         if (!drawingWithDrawingCache) {
17086             if (drawingWithRenderNode) {
17087                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17088                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17089             } else {
17090                 // Fast path for layouts with no backgrounds
17091                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17092                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17093                     dispatchDraw(canvas);
17094                 } else {
17095                     draw(canvas);
17096                 }
17097             }
17098         } else if (cache != null) {
17099             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17100             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17101                 // no layer paint, use temporary paint to draw bitmap
17102                 Paint cachePaint = parent.mCachePaint;
17103                 if (cachePaint == null) {
17104                     cachePaint = new Paint();
17105                     cachePaint.setDither(false);
17106                     parent.mCachePaint = cachePaint;
17107                 }
17108                 cachePaint.setAlpha((int) (alpha * 255));
17109                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17110             } else {
17111                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
17112                 int layerPaintAlpha = mLayerPaint.getAlpha();
17113                 if (alpha < 1) {
17114                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17115                 }
17116                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17117                 if (alpha < 1) {
17118                     mLayerPaint.setAlpha(layerPaintAlpha);
17119                 }
17120             }
17121         }
17122 
17123         if (restoreTo >= 0) {
17124             canvas.restoreToCount(restoreTo);
17125         }
17126 
17127         if (a != null && !more) {
17128             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17129                 onSetAlpha(255);
17130             }
17131             parent.finishAnimatingView(this, a);
17132         }
17133 
17134         if (more && hardwareAcceleratedCanvas) {
17135             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17136                 // alpha animations should cause the child to recreate its display list
17137                 invalidate(true);
17138             }
17139         }
17140 
17141         mRecreateDisplayList = false;
17142 
17143         return more;
17144     }
17145 
17146     /**
17147      * Manually render this view (and all of its children) to the given Canvas.
17148      * The view must have already done a full layout before this function is
17149      * called.  When implementing a view, implement
17150      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17151      * If you do need to override this method, call the superclass version.
17152      *
17153      * @param canvas The Canvas to which the View is rendered.
17154      */
17155     @CallSuper
draw(Canvas canvas)17156     public void draw(Canvas canvas) {
17157         final int privateFlags = mPrivateFlags;
17158         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17159                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17160         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17161 
17162         /*
17163          * Draw traversal performs several drawing steps which must be executed
17164          * in the appropriate order:
17165          *
17166          *      1. Draw the background
17167          *      2. If necessary, save the canvas' layers to prepare for fading
17168          *      3. Draw view's content
17169          *      4. Draw children
17170          *      5. If necessary, draw the fading edges and restore layers
17171          *      6. Draw decorations (scrollbars for instance)
17172          */
17173 
17174         // Step 1, draw the background, if needed
17175         int saveCount;
17176 
17177         if (!dirtyOpaque) {
17178             drawBackground(canvas);
17179         }
17180 
17181         // skip step 2 & 5 if possible (common case)
17182         final int viewFlags = mViewFlags;
17183         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17184         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17185         if (!verticalEdges && !horizontalEdges) {
17186             // Step 3, draw the content
17187             if (!dirtyOpaque) onDraw(canvas);
17188 
17189             // Step 4, draw the children
17190             dispatchDraw(canvas);
17191 
17192             // Overlay is part of the content and draws beneath Foreground
17193             if (mOverlay != null && !mOverlay.isEmpty()) {
17194                 mOverlay.getOverlayView().dispatchDraw(canvas);
17195             }
17196 
17197             // Step 6, draw decorations (foreground, scrollbars)
17198             onDrawForeground(canvas);
17199 
17200             // we're done...
17201             return;
17202         }
17203 
17204         /*
17205          * Here we do the full fledged routine...
17206          * (this is an uncommon case where speed matters less,
17207          * this is why we repeat some of the tests that have been
17208          * done above)
17209          */
17210 
17211         boolean drawTop = false;
17212         boolean drawBottom = false;
17213         boolean drawLeft = false;
17214         boolean drawRight = false;
17215 
17216         float topFadeStrength = 0.0f;
17217         float bottomFadeStrength = 0.0f;
17218         float leftFadeStrength = 0.0f;
17219         float rightFadeStrength = 0.0f;
17220 
17221         // Step 2, save the canvas' layers
17222         int paddingLeft = mPaddingLeft;
17223 
17224         final boolean offsetRequired = isPaddingOffsetRequired();
17225         if (offsetRequired) {
17226             paddingLeft += getLeftPaddingOffset();
17227         }
17228 
17229         int left = mScrollX + paddingLeft;
17230         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17231         int top = mScrollY + getFadeTop(offsetRequired);
17232         int bottom = top + getFadeHeight(offsetRequired);
17233 
17234         if (offsetRequired) {
17235             right += getRightPaddingOffset();
17236             bottom += getBottomPaddingOffset();
17237         }
17238 
17239         final ScrollabilityCache scrollabilityCache = mScrollCache;
17240         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17241         int length = (int) fadeHeight;
17242 
17243         // clip the fade length if top and bottom fades overlap
17244         // overlapping fades produce odd-looking artifacts
17245         if (verticalEdges && (top + length > bottom - length)) {
17246             length = (bottom - top) / 2;
17247         }
17248 
17249         // also clip horizontal fades if necessary
17250         if (horizontalEdges && (left + length > right - length)) {
17251             length = (right - left) / 2;
17252         }
17253 
17254         if (verticalEdges) {
17255             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17256             drawTop = topFadeStrength * fadeHeight > 1.0f;
17257             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17258             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17259         }
17260 
17261         if (horizontalEdges) {
17262             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17263             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17264             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17265             drawRight = rightFadeStrength * fadeHeight > 1.0f;
17266         }
17267 
17268         saveCount = canvas.getSaveCount();
17269 
17270         int solidColor = getSolidColor();
17271         if (solidColor == 0) {
17272             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17273 
17274             if (drawTop) {
17275                 canvas.saveLayer(left, top, right, top + length, null, flags);
17276             }
17277 
17278             if (drawBottom) {
17279                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17280             }
17281 
17282             if (drawLeft) {
17283                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
17284             }
17285 
17286             if (drawRight) {
17287                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
17288             }
17289         } else {
17290             scrollabilityCache.setFadeColor(solidColor);
17291         }
17292 
17293         // Step 3, draw the content
17294         if (!dirtyOpaque) onDraw(canvas);
17295 
17296         // Step 4, draw the children
17297         dispatchDraw(canvas);
17298 
17299         // Step 5, draw the fade effect and restore layers
17300         final Paint p = scrollabilityCache.paint;
17301         final Matrix matrix = scrollabilityCache.matrix;
17302         final Shader fade = scrollabilityCache.shader;
17303 
17304         if (drawTop) {
17305             matrix.setScale(1, fadeHeight * topFadeStrength);
17306             matrix.postTranslate(left, top);
17307             fade.setLocalMatrix(matrix);
17308             p.setShader(fade);
17309             canvas.drawRect(left, top, right, top + length, p);
17310         }
17311 
17312         if (drawBottom) {
17313             matrix.setScale(1, fadeHeight * bottomFadeStrength);
17314             matrix.postRotate(180);
17315             matrix.postTranslate(left, bottom);
17316             fade.setLocalMatrix(matrix);
17317             p.setShader(fade);
17318             canvas.drawRect(left, bottom - length, right, bottom, p);
17319         }
17320 
17321         if (drawLeft) {
17322             matrix.setScale(1, fadeHeight * leftFadeStrength);
17323             matrix.postRotate(-90);
17324             matrix.postTranslate(left, top);
17325             fade.setLocalMatrix(matrix);
17326             p.setShader(fade);
17327             canvas.drawRect(left, top, left + length, bottom, p);
17328         }
17329 
17330         if (drawRight) {
17331             matrix.setScale(1, fadeHeight * rightFadeStrength);
17332             matrix.postRotate(90);
17333             matrix.postTranslate(right, top);
17334             fade.setLocalMatrix(matrix);
17335             p.setShader(fade);
17336             canvas.drawRect(right - length, top, right, bottom, p);
17337         }
17338 
17339         canvas.restoreToCount(saveCount);
17340 
17341         // Overlay is part of the content and draws beneath Foreground
17342         if (mOverlay != null && !mOverlay.isEmpty()) {
17343             mOverlay.getOverlayView().dispatchDraw(canvas);
17344         }
17345 
17346         // Step 6, draw decorations (foreground, scrollbars)
17347         onDrawForeground(canvas);
17348     }
17349 
17350     /**
17351      * Draws the background onto the specified canvas.
17352      *
17353      * @param canvas Canvas on which to draw the background
17354      */
drawBackground(Canvas canvas)17355     private void drawBackground(Canvas canvas) {
17356         final Drawable background = mBackground;
17357         if (background == null) {
17358             return;
17359         }
17360 
17361         setBackgroundBounds();
17362 
17363         // Attempt to use a display list if requested.
17364         if (canvas.isHardwareAccelerated() && mAttachInfo != null
17365                 && mAttachInfo.mHardwareRenderer != null) {
17366             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17367 
17368             final RenderNode renderNode = mBackgroundRenderNode;
17369             if (renderNode != null && renderNode.isValid()) {
17370                 setBackgroundRenderNodeProperties(renderNode);
17371                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17372                 return;
17373             }
17374         }
17375 
17376         final int scrollX = mScrollX;
17377         final int scrollY = mScrollY;
17378         if ((scrollX | scrollY) == 0) {
17379             background.draw(canvas);
17380         } else {
17381             canvas.translate(scrollX, scrollY);
17382             background.draw(canvas);
17383             canvas.translate(-scrollX, -scrollY);
17384         }
17385     }
17386 
17387     /**
17388      * Sets the correct background bounds and rebuilds the outline, if needed.
17389      * <p/>
17390      * This is called by LayoutLib.
17391      */
setBackgroundBounds()17392     void setBackgroundBounds() {
17393         if (mBackgroundSizeChanged && mBackground != null) {
17394             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17395             mBackgroundSizeChanged = false;
17396             rebuildOutline();
17397         }
17398     }
17399 
setBackgroundRenderNodeProperties(RenderNode renderNode)17400     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17401         renderNode.setTranslationX(mScrollX);
17402         renderNode.setTranslationY(mScrollY);
17403     }
17404 
17405     /**
17406      * Creates a new display list or updates the existing display list for the
17407      * specified Drawable.
17408      *
17409      * @param drawable Drawable for which to create a display list
17410      * @param renderNode Existing RenderNode, or {@code null}
17411      * @return A valid display list for the specified drawable
17412      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)17413     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17414         if (renderNode == null) {
17415             renderNode = RenderNode.create(drawable.getClass().getName(), this);
17416         }
17417 
17418         final Rect bounds = drawable.getBounds();
17419         final int width = bounds.width();
17420         final int height = bounds.height();
17421         final DisplayListCanvas canvas = renderNode.start(width, height);
17422 
17423         // Reverse left/top translation done by drawable canvas, which will
17424         // instead be applied by rendernode's LTRB bounds below. This way, the
17425         // drawable's bounds match with its rendernode bounds and its content
17426         // will lie within those bounds in the rendernode tree.
17427         canvas.translate(-bounds.left, -bounds.top);
17428 
17429         try {
17430             drawable.draw(canvas);
17431         } finally {
17432             renderNode.end(canvas);
17433         }
17434 
17435         // Set up drawable properties that are view-independent.
17436         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17437         renderNode.setProjectBackwards(drawable.isProjected());
17438         renderNode.setProjectionReceiver(true);
17439         renderNode.setClipToBounds(false);
17440         return renderNode;
17441     }
17442 
17443     /**
17444      * Returns the overlay for this view, creating it if it does not yet exist.
17445      * Adding drawables to the overlay will cause them to be displayed whenever
17446      * the view itself is redrawn. Objects in the overlay should be actively
17447      * managed: remove them when they should not be displayed anymore. The
17448      * overlay will always have the same size as its host view.
17449      *
17450      * <p>Note: Overlays do not currently work correctly with {@link
17451      * SurfaceView} or {@link TextureView}; contents in overlays for these
17452      * types of views may not display correctly.</p>
17453      *
17454      * @return The ViewOverlay object for this view.
17455      * @see ViewOverlay
17456      */
getOverlay()17457     public ViewOverlay getOverlay() {
17458         if (mOverlay == null) {
17459             mOverlay = new ViewOverlay(mContext, this);
17460         }
17461         return mOverlay;
17462     }
17463 
17464     /**
17465      * Override this if your view is known to always be drawn on top of a solid color background,
17466      * and needs to draw fading edges. Returning a non-zero color enables the view system to
17467      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17468      * should be set to 0xFF.
17469      *
17470      * @see #setVerticalFadingEdgeEnabled(boolean)
17471      * @see #setHorizontalFadingEdgeEnabled(boolean)
17472      *
17473      * @return The known solid color background for this view, or 0 if the color may vary
17474      */
17475     @ViewDebug.ExportedProperty(category = "drawing")
17476     @ColorInt
getSolidColor()17477     public int getSolidColor() {
17478         return 0;
17479     }
17480 
17481     /**
17482      * Build a human readable string representation of the specified view flags.
17483      *
17484      * @param flags the view flags to convert to a string
17485      * @return a String representing the supplied flags
17486      */
printFlags(int flags)17487     private static String printFlags(int flags) {
17488         String output = "";
17489         int numFlags = 0;
17490         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17491             output += "TAKES_FOCUS";
17492             numFlags++;
17493         }
17494 
17495         switch (flags & VISIBILITY_MASK) {
17496         case INVISIBLE:
17497             if (numFlags > 0) {
17498                 output += " ";
17499             }
17500             output += "INVISIBLE";
17501             // USELESS HERE numFlags++;
17502             break;
17503         case GONE:
17504             if (numFlags > 0) {
17505                 output += " ";
17506             }
17507             output += "GONE";
17508             // USELESS HERE numFlags++;
17509             break;
17510         default:
17511             break;
17512         }
17513         return output;
17514     }
17515 
17516     /**
17517      * Build a human readable string representation of the specified private
17518      * view flags.
17519      *
17520      * @param privateFlags the private view flags to convert to a string
17521      * @return a String representing the supplied flags
17522      */
printPrivateFlags(int privateFlags)17523     private static String printPrivateFlags(int privateFlags) {
17524         String output = "";
17525         int numFlags = 0;
17526 
17527         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17528             output += "WANTS_FOCUS";
17529             numFlags++;
17530         }
17531 
17532         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17533             if (numFlags > 0) {
17534                 output += " ";
17535             }
17536             output += "FOCUSED";
17537             numFlags++;
17538         }
17539 
17540         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17541             if (numFlags > 0) {
17542                 output += " ";
17543             }
17544             output += "SELECTED";
17545             numFlags++;
17546         }
17547 
17548         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17549             if (numFlags > 0) {
17550                 output += " ";
17551             }
17552             output += "IS_ROOT_NAMESPACE";
17553             numFlags++;
17554         }
17555 
17556         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17557             if (numFlags > 0) {
17558                 output += " ";
17559             }
17560             output += "HAS_BOUNDS";
17561             numFlags++;
17562         }
17563 
17564         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17565             if (numFlags > 0) {
17566                 output += " ";
17567             }
17568             output += "DRAWN";
17569             // USELESS HERE numFlags++;
17570         }
17571         return output;
17572     }
17573 
17574     /**
17575      * <p>Indicates whether or not this view's layout will be requested during
17576      * the next hierarchy layout pass.</p>
17577      *
17578      * @return true if the layout will be forced during next layout pass
17579      */
isLayoutRequested()17580     public boolean isLayoutRequested() {
17581         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17582     }
17583 
17584     /**
17585      * Return true if o is a ViewGroup that is laying out using optical bounds.
17586      * @hide
17587      */
isLayoutModeOptical(Object o)17588     public static boolean isLayoutModeOptical(Object o) {
17589         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17590     }
17591 
setOpticalFrame(int left, int top, int right, int bottom)17592     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17593         Insets parentInsets = mParent instanceof View ?
17594                 ((View) mParent).getOpticalInsets() : Insets.NONE;
17595         Insets childInsets = getOpticalInsets();
17596         return setFrame(
17597                 left   + parentInsets.left - childInsets.left,
17598                 top    + parentInsets.top  - childInsets.top,
17599                 right  + parentInsets.left + childInsets.right,
17600                 bottom + parentInsets.top  + childInsets.bottom);
17601     }
17602 
17603     /**
17604      * Assign a size and position to a view and all of its
17605      * descendants
17606      *
17607      * <p>This is the second phase of the layout mechanism.
17608      * (The first is measuring). In this phase, each parent calls
17609      * layout on all of its children to position them.
17610      * This is typically done using the child measurements
17611      * that were stored in the measure pass().</p>
17612      *
17613      * <p>Derived classes should not override this method.
17614      * Derived classes with children should override
17615      * onLayout. In that method, they should
17616      * call layout on each of their children.</p>
17617      *
17618      * @param l Left position, relative to parent
17619      * @param t Top position, relative to parent
17620      * @param r Right position, relative to parent
17621      * @param b Bottom position, relative to parent
17622      */
17623     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)17624     public void layout(int l, int t, int r, int b) {
17625         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17626             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17627             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17628         }
17629 
17630         int oldL = mLeft;
17631         int oldT = mTop;
17632         int oldB = mBottom;
17633         int oldR = mRight;
17634 
17635         boolean changed = isLayoutModeOptical(mParent) ?
17636                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17637 
17638         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17639             onLayout(changed, l, t, r, b);
17640 
17641             if (shouldDrawRoundScrollbar()) {
17642                 if(mRoundScrollbarRenderer == null) {
17643                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
17644                 }
17645             } else {
17646                 mRoundScrollbarRenderer = null;
17647             }
17648 
17649             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17650 
17651             ListenerInfo li = mListenerInfo;
17652             if (li != null && li.mOnLayoutChangeListeners != null) {
17653                 ArrayList<OnLayoutChangeListener> listenersCopy =
17654                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17655                 int numListeners = listenersCopy.size();
17656                 for (int i = 0; i < numListeners; ++i) {
17657                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17658                 }
17659             }
17660         }
17661 
17662         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17663         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17664     }
17665 
17666     /**
17667      * Called from layout when this view should
17668      * assign a size and position to each of its children.
17669      *
17670      * Derived classes with children should override
17671      * this method and call layout on each of
17672      * their children.
17673      * @param changed This is a new size or position for this view
17674      * @param left Left position, relative to parent
17675      * @param top Top position, relative to parent
17676      * @param right Right position, relative to parent
17677      * @param bottom Bottom position, relative to parent
17678      */
onLayout(boolean changed, int left, int top, int right, int bottom)17679     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17680     }
17681 
17682     /**
17683      * Assign a size and position to this view.
17684      *
17685      * This is called from layout.
17686      *
17687      * @param left Left position, relative to parent
17688      * @param top Top position, relative to parent
17689      * @param right Right position, relative to parent
17690      * @param bottom Bottom position, relative to parent
17691      * @return true if the new size and position are different than the
17692      *         previous ones
17693      * {@hide}
17694      */
setFrame(int left, int top, int right, int bottom)17695     protected boolean setFrame(int left, int top, int right, int bottom) {
17696         boolean changed = false;
17697 
17698         if (DBG) {
17699             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17700                     + right + "," + bottom + ")");
17701         }
17702 
17703         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17704             changed = true;
17705 
17706             // Remember our drawn bit
17707             int drawn = mPrivateFlags & PFLAG_DRAWN;
17708 
17709             int oldWidth = mRight - mLeft;
17710             int oldHeight = mBottom - mTop;
17711             int newWidth = right - left;
17712             int newHeight = bottom - top;
17713             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17714 
17715             // Invalidate our old position
17716             invalidate(sizeChanged);
17717 
17718             mLeft = left;
17719             mTop = top;
17720             mRight = right;
17721             mBottom = bottom;
17722             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17723 
17724             mPrivateFlags |= PFLAG_HAS_BOUNDS;
17725 
17726 
17727             if (sizeChanged) {
17728                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17729             }
17730 
17731             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17732                 // If we are visible, force the DRAWN bit to on so that
17733                 // this invalidate will go through (at least to our parent).
17734                 // This is because someone may have invalidated this view
17735                 // before this call to setFrame came in, thereby clearing
17736                 // the DRAWN bit.
17737                 mPrivateFlags |= PFLAG_DRAWN;
17738                 invalidate(sizeChanged);
17739                 // parent display list may need to be recreated based on a change in the bounds
17740                 // of any child
17741                 invalidateParentCaches();
17742             }
17743 
17744             // Reset drawn bit to original value (invalidate turns it off)
17745             mPrivateFlags |= drawn;
17746 
17747             mBackgroundSizeChanged = true;
17748             if (mForegroundInfo != null) {
17749                 mForegroundInfo.mBoundsChanged = true;
17750             }
17751 
17752             notifySubtreeAccessibilityStateChangedIfNeeded();
17753         }
17754         return changed;
17755     }
17756 
17757     /**
17758      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17759      * @hide
17760      */
setLeftTopRightBottom(int left, int top, int right, int bottom)17761     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17762         setFrame(left, top, right, bottom);
17763     }
17764 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)17765     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17766         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17767         if (mOverlay != null) {
17768             mOverlay.getOverlayView().setRight(newWidth);
17769             mOverlay.getOverlayView().setBottom(newHeight);
17770         }
17771         rebuildOutline();
17772     }
17773 
17774     /**
17775      * Finalize inflating a view from XML.  This is called as the last phase
17776      * of inflation, after all child views have been added.
17777      *
17778      * <p>Even if the subclass overrides onFinishInflate, they should always be
17779      * sure to call the super method, so that we get called.
17780      */
17781     @CallSuper
onFinishInflate()17782     protected void onFinishInflate() {
17783     }
17784 
17785     /**
17786      * Returns the resources associated with this view.
17787      *
17788      * @return Resources object.
17789      */
getResources()17790     public Resources getResources() {
17791         return mResources;
17792     }
17793 
17794     /**
17795      * Invalidates the specified Drawable.
17796      *
17797      * @param drawable the drawable to invalidate
17798      */
17799     @Override
invalidateDrawable(@onNull Drawable drawable)17800     public void invalidateDrawable(@NonNull Drawable drawable) {
17801         if (verifyDrawable(drawable)) {
17802             final Rect dirty = drawable.getDirtyBounds();
17803             final int scrollX = mScrollX;
17804             final int scrollY = mScrollY;
17805 
17806             invalidate(dirty.left + scrollX, dirty.top + scrollY,
17807                     dirty.right + scrollX, dirty.bottom + scrollY);
17808             rebuildOutline();
17809         }
17810     }
17811 
17812     /**
17813      * Schedules an action on a drawable to occur at a specified time.
17814      *
17815      * @param who the recipient of the action
17816      * @param what the action to run on the drawable
17817      * @param when the time at which the action must occur. Uses the
17818      *        {@link SystemClock#uptimeMillis} timebase.
17819      */
17820     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)17821     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17822         if (verifyDrawable(who) && what != null) {
17823             final long delay = when - SystemClock.uptimeMillis();
17824             if (mAttachInfo != null) {
17825                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17826                         Choreographer.CALLBACK_ANIMATION, what, who,
17827                         Choreographer.subtractFrameDelay(delay));
17828             } else {
17829                 // Postpone the runnable until we know
17830                 // on which thread it needs to run.
17831                 getRunQueue().postDelayed(what, delay);
17832             }
17833         }
17834     }
17835 
17836     /**
17837      * Cancels a scheduled action on a drawable.
17838      *
17839      * @param who the recipient of the action
17840      * @param what the action to cancel
17841      */
17842     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)17843     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17844         if (verifyDrawable(who) && what != null) {
17845             if (mAttachInfo != null) {
17846                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17847                         Choreographer.CALLBACK_ANIMATION, what, who);
17848             }
17849             getRunQueue().removeCallbacks(what);
17850         }
17851     }
17852 
17853     /**
17854      * Unschedule any events associated with the given Drawable.  This can be
17855      * used when selecting a new Drawable into a view, so that the previous
17856      * one is completely unscheduled.
17857      *
17858      * @param who The Drawable to unschedule.
17859      *
17860      * @see #drawableStateChanged
17861      */
unscheduleDrawable(Drawable who)17862     public void unscheduleDrawable(Drawable who) {
17863         if (mAttachInfo != null && who != null) {
17864             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17865                     Choreographer.CALLBACK_ANIMATION, null, who);
17866         }
17867     }
17868 
17869     /**
17870      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17871      * that the View directionality can and will be resolved before its Drawables.
17872      *
17873      * Will call {@link View#onResolveDrawables} when resolution is done.
17874      *
17875      * @hide
17876      */
resolveDrawables()17877     protected void resolveDrawables() {
17878         // Drawables resolution may need to happen before resolving the layout direction (which is
17879         // done only during the measure() call).
17880         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17881         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17882         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17883         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17884         // direction to be resolved as its resolved value will be the same as its raw value.
17885         if (!isLayoutDirectionResolved() &&
17886                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17887             return;
17888         }
17889 
17890         final int layoutDirection = isLayoutDirectionResolved() ?
17891                 getLayoutDirection() : getRawLayoutDirection();
17892 
17893         if (mBackground != null) {
17894             mBackground.setLayoutDirection(layoutDirection);
17895         }
17896         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17897             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17898         }
17899         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17900         onResolveDrawables(layoutDirection);
17901     }
17902 
areDrawablesResolved()17903     boolean areDrawablesResolved() {
17904         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17905     }
17906 
17907     /**
17908      * Called when layout direction has been resolved.
17909      *
17910      * The default implementation does nothing.
17911      *
17912      * @param layoutDirection The resolved layout direction.
17913      *
17914      * @see #LAYOUT_DIRECTION_LTR
17915      * @see #LAYOUT_DIRECTION_RTL
17916      *
17917      * @hide
17918      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)17919     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17920     }
17921 
17922     /**
17923      * @hide
17924      */
resetResolvedDrawables()17925     protected void resetResolvedDrawables() {
17926         resetResolvedDrawablesInternal();
17927     }
17928 
resetResolvedDrawablesInternal()17929     void resetResolvedDrawablesInternal() {
17930         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17931     }
17932 
17933     /**
17934      * If your view subclass is displaying its own Drawable objects, it should
17935      * override this function and return true for any Drawable it is
17936      * displaying.  This allows animations for those drawables to be
17937      * scheduled.
17938      *
17939      * <p>Be sure to call through to the super class when overriding this
17940      * function.
17941      *
17942      * @param who The Drawable to verify.  Return true if it is one you are
17943      *            displaying, else return the result of calling through to the
17944      *            super class.
17945      *
17946      * @return boolean If true than the Drawable is being displayed in the
17947      *         view; else false and it is not allowed to animate.
17948      *
17949      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17950      * @see #drawableStateChanged()
17951      */
17952     @CallSuper
verifyDrawable(@onNull Drawable who)17953     protected boolean verifyDrawable(@NonNull Drawable who) {
17954         // Avoid verifying the scroll bar drawable so that we don't end up in
17955         // an invalidation loop. This effectively prevents the scroll bar
17956         // drawable from triggering invalidations and scheduling runnables.
17957         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17958     }
17959 
17960     /**
17961      * This function is called whenever the state of the view changes in such
17962      * a way that it impacts the state of drawables being shown.
17963      * <p>
17964      * If the View has a StateListAnimator, it will also be called to run necessary state
17965      * change animations.
17966      * <p>
17967      * Be sure to call through to the superclass when overriding this function.
17968      *
17969      * @see Drawable#setState(int[])
17970      */
17971     @CallSuper
drawableStateChanged()17972     protected void drawableStateChanged() {
17973         final int[] state = getDrawableState();
17974         boolean changed = false;
17975 
17976         final Drawable bg = mBackground;
17977         if (bg != null && bg.isStateful()) {
17978             changed |= bg.setState(state);
17979         }
17980 
17981         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17982         if (fg != null && fg.isStateful()) {
17983             changed |= fg.setState(state);
17984         }
17985 
17986         if (mScrollCache != null) {
17987             final Drawable scrollBar = mScrollCache.scrollBar;
17988             if (scrollBar != null && scrollBar.isStateful()) {
17989                 changed |= scrollBar.setState(state)
17990                         && mScrollCache.state != ScrollabilityCache.OFF;
17991             }
17992         }
17993 
17994         if (mStateListAnimator != null) {
17995             mStateListAnimator.setState(state);
17996         }
17997 
17998         if (changed) {
17999             invalidate();
18000         }
18001     }
18002 
18003     /**
18004      * This function is called whenever the view hotspot changes and needs to
18005      * be propagated to drawables or child views managed by the view.
18006      * <p>
18007      * Dispatching to child views is handled by
18008      * {@link #dispatchDrawableHotspotChanged(float, float)}.
18009      * <p>
18010      * Be sure to call through to the superclass when overriding this function.
18011      *
18012      * @param x hotspot x coordinate
18013      * @param y hotspot y coordinate
18014      */
18015     @CallSuper
drawableHotspotChanged(float x, float y)18016     public void drawableHotspotChanged(float x, float y) {
18017         if (mBackground != null) {
18018             mBackground.setHotspot(x, y);
18019         }
18020         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18021             mForegroundInfo.mDrawable.setHotspot(x, y);
18022         }
18023 
18024         dispatchDrawableHotspotChanged(x, y);
18025     }
18026 
18027     /**
18028      * Dispatches drawableHotspotChanged to all of this View's children.
18029      *
18030      * @param x hotspot x coordinate
18031      * @param y hotspot y coordinate
18032      * @see #drawableHotspotChanged(float, float)
18033      */
dispatchDrawableHotspotChanged(float x, float y)18034     public void dispatchDrawableHotspotChanged(float x, float y) {
18035     }
18036 
18037     /**
18038      * Call this to force a view to update its drawable state. This will cause
18039      * drawableStateChanged to be called on this view. Views that are interested
18040      * in the new state should call getDrawableState.
18041      *
18042      * @see #drawableStateChanged
18043      * @see #getDrawableState
18044      */
refreshDrawableState()18045     public void refreshDrawableState() {
18046         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18047         drawableStateChanged();
18048 
18049         ViewParent parent = mParent;
18050         if (parent != null) {
18051             parent.childDrawableStateChanged(this);
18052         }
18053     }
18054 
18055     /**
18056      * Return an array of resource IDs of the drawable states representing the
18057      * current state of the view.
18058      *
18059      * @return The current drawable state
18060      *
18061      * @see Drawable#setState(int[])
18062      * @see #drawableStateChanged()
18063      * @see #onCreateDrawableState(int)
18064      */
getDrawableState()18065     public final int[] getDrawableState() {
18066         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18067             return mDrawableState;
18068         } else {
18069             mDrawableState = onCreateDrawableState(0);
18070             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18071             return mDrawableState;
18072         }
18073     }
18074 
18075     /**
18076      * Generate the new {@link android.graphics.drawable.Drawable} state for
18077      * this view. This is called by the view
18078      * system when the cached Drawable state is determined to be invalid.  To
18079      * retrieve the current state, you should use {@link #getDrawableState}.
18080      *
18081      * @param extraSpace if non-zero, this is the number of extra entries you
18082      * would like in the returned array in which you can place your own
18083      * states.
18084      *
18085      * @return Returns an array holding the current {@link Drawable} state of
18086      * the view.
18087      *
18088      * @see #mergeDrawableStates(int[], int[])
18089      */
onCreateDrawableState(int extraSpace)18090     protected int[] onCreateDrawableState(int extraSpace) {
18091         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18092                 mParent instanceof View) {
18093             return ((View) mParent).onCreateDrawableState(extraSpace);
18094         }
18095 
18096         int[] drawableState;
18097 
18098         int privateFlags = mPrivateFlags;
18099 
18100         int viewStateIndex = 0;
18101         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18102         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18103         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18104         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18105         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18106         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18107         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18108                 ThreadedRenderer.isAvailable()) {
18109             // This is set if HW acceleration is requested, even if the current
18110             // process doesn't allow it.  This is just to allow app preview
18111             // windows to better match their app.
18112             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18113         }
18114         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18115 
18116         final int privateFlags2 = mPrivateFlags2;
18117         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18118             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18119         }
18120         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18121             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18122         }
18123 
18124         drawableState = StateSet.get(viewStateIndex);
18125 
18126         //noinspection ConstantIfStatement
18127         if (false) {
18128             Log.i("View", "drawableStateIndex=" + viewStateIndex);
18129             Log.i("View", toString()
18130                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18131                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18132                     + " fo=" + hasFocus()
18133                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18134                     + " wf=" + hasWindowFocus()
18135                     + ": " + Arrays.toString(drawableState));
18136         }
18137 
18138         if (extraSpace == 0) {
18139             return drawableState;
18140         }
18141 
18142         final int[] fullState;
18143         if (drawableState != null) {
18144             fullState = new int[drawableState.length + extraSpace];
18145             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18146         } else {
18147             fullState = new int[extraSpace];
18148         }
18149 
18150         return fullState;
18151     }
18152 
18153     /**
18154      * Merge your own state values in <var>additionalState</var> into the base
18155      * state values <var>baseState</var> that were returned by
18156      * {@link #onCreateDrawableState(int)}.
18157      *
18158      * @param baseState The base state values returned by
18159      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18160      * own additional state values.
18161      *
18162      * @param additionalState The additional state values you would like
18163      * added to <var>baseState</var>; this array is not modified.
18164      *
18165      * @return As a convenience, the <var>baseState</var> array you originally
18166      * passed into the function is returned.
18167      *
18168      * @see #onCreateDrawableState(int)
18169      */
mergeDrawableStates(int[] baseState, int[] additionalState)18170     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18171         final int N = baseState.length;
18172         int i = N - 1;
18173         while (i >= 0 && baseState[i] == 0) {
18174             i--;
18175         }
18176         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18177         return baseState;
18178     }
18179 
18180     /**
18181      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18182      * on all Drawable objects associated with this view.
18183      * <p>
18184      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18185      * attached to this view.
18186      */
18187     @CallSuper
jumpDrawablesToCurrentState()18188     public void jumpDrawablesToCurrentState() {
18189         if (mBackground != null) {
18190             mBackground.jumpToCurrentState();
18191         }
18192         if (mStateListAnimator != null) {
18193             mStateListAnimator.jumpToCurrentState();
18194         }
18195         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18196             mForegroundInfo.mDrawable.jumpToCurrentState();
18197         }
18198     }
18199 
18200     /**
18201      * Sets the background color for this view.
18202      * @param color the color of the background
18203      */
18204     @RemotableViewMethod
setBackgroundColor(@olorInt int color)18205     public void setBackgroundColor(@ColorInt int color) {
18206         if (mBackground instanceof ColorDrawable) {
18207             ((ColorDrawable) mBackground.mutate()).setColor(color);
18208             computeOpaqueFlags();
18209             mBackgroundResource = 0;
18210         } else {
18211             setBackground(new ColorDrawable(color));
18212         }
18213     }
18214 
18215     /**
18216      * Set the background to a given resource. The resource should refer to
18217      * a Drawable object or 0 to remove the background.
18218      * @param resid The identifier of the resource.
18219      *
18220      * @attr ref android.R.styleable#View_background
18221      */
18222     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)18223     public void setBackgroundResource(@DrawableRes int resid) {
18224         if (resid != 0 && resid == mBackgroundResource) {
18225             return;
18226         }
18227 
18228         Drawable d = null;
18229         if (resid != 0) {
18230             d = mContext.getDrawable(resid);
18231         }
18232         setBackground(d);
18233 
18234         mBackgroundResource = resid;
18235     }
18236 
18237     /**
18238      * Set the background to a given Drawable, or remove the background. If the
18239      * background has padding, this View's padding is set to the background's
18240      * padding. However, when a background is removed, this View's padding isn't
18241      * touched. If setting the padding is desired, please use
18242      * {@link #setPadding(int, int, int, int)}.
18243      *
18244      * @param background The Drawable to use as the background, or null to remove the
18245      *        background
18246      */
setBackground(Drawable background)18247     public void setBackground(Drawable background) {
18248         //noinspection deprecation
18249         setBackgroundDrawable(background);
18250     }
18251 
18252     /**
18253      * @deprecated use {@link #setBackground(Drawable)} instead
18254      */
18255     @Deprecated
setBackgroundDrawable(Drawable background)18256     public void setBackgroundDrawable(Drawable background) {
18257         computeOpaqueFlags();
18258 
18259         if (background == mBackground) {
18260             return;
18261         }
18262 
18263         boolean requestLayout = false;
18264 
18265         mBackgroundResource = 0;
18266 
18267         /*
18268          * Regardless of whether we're setting a new background or not, we want
18269          * to clear the previous drawable. setVisible first while we still have the callback set.
18270          */
18271         if (mBackground != null) {
18272             if (isAttachedToWindow()) {
18273                 mBackground.setVisible(false, false);
18274             }
18275             mBackground.setCallback(null);
18276             unscheduleDrawable(mBackground);
18277         }
18278 
18279         if (background != null) {
18280             Rect padding = sThreadLocal.get();
18281             if (padding == null) {
18282                 padding = new Rect();
18283                 sThreadLocal.set(padding);
18284             }
18285             resetResolvedDrawablesInternal();
18286             background.setLayoutDirection(getLayoutDirection());
18287             if (background.getPadding(padding)) {
18288                 resetResolvedPaddingInternal();
18289                 switch (background.getLayoutDirection()) {
18290                     case LAYOUT_DIRECTION_RTL:
18291                         mUserPaddingLeftInitial = padding.right;
18292                         mUserPaddingRightInitial = padding.left;
18293                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18294                         break;
18295                     case LAYOUT_DIRECTION_LTR:
18296                     default:
18297                         mUserPaddingLeftInitial = padding.left;
18298                         mUserPaddingRightInitial = padding.right;
18299                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18300                 }
18301                 mLeftPaddingDefined = false;
18302                 mRightPaddingDefined = false;
18303             }
18304 
18305             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18306             // if it has a different minimum size, we should layout again
18307             if (mBackground == null
18308                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
18309                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18310                 requestLayout = true;
18311             }
18312 
18313             // Set mBackground before we set this as the callback and start making other
18314             // background drawable state change calls. In particular, the setVisible call below
18315             // can result in drawables attempting to start animations or otherwise invalidate,
18316             // which requires the view set as the callback (us) to recognize the drawable as
18317             // belonging to it as per verifyDrawable.
18318             mBackground = background;
18319             if (background.isStateful()) {
18320                 background.setState(getDrawableState());
18321             }
18322             if (isAttachedToWindow()) {
18323                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18324             }
18325 
18326             applyBackgroundTint();
18327 
18328             // Set callback last, since the view may still be initializing.
18329             background.setCallback(this);
18330 
18331             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18332                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18333                 requestLayout = true;
18334             }
18335         } else {
18336             /* Remove the background */
18337             mBackground = null;
18338             if ((mViewFlags & WILL_NOT_DRAW) != 0
18339                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18340                 mPrivateFlags |= PFLAG_SKIP_DRAW;
18341             }
18342 
18343             /*
18344              * When the background is set, we try to apply its padding to this
18345              * View. When the background is removed, we don't touch this View's
18346              * padding. This is noted in the Javadocs. Hence, we don't need to
18347              * requestLayout(), the invalidate() below is sufficient.
18348              */
18349 
18350             // The old background's minimum size could have affected this
18351             // View's layout, so let's requestLayout
18352             requestLayout = true;
18353         }
18354 
18355         computeOpaqueFlags();
18356 
18357         if (requestLayout) {
18358             requestLayout();
18359         }
18360 
18361         mBackgroundSizeChanged = true;
18362         invalidate(true);
18363         invalidateOutline();
18364     }
18365 
18366     /**
18367      * Gets the background drawable
18368      *
18369      * @return The drawable used as the background for this view, if any.
18370      *
18371      * @see #setBackground(Drawable)
18372      *
18373      * @attr ref android.R.styleable#View_background
18374      */
getBackground()18375     public Drawable getBackground() {
18376         return mBackground;
18377     }
18378 
18379     /**
18380      * Applies a tint to the background drawable. Does not modify the current tint
18381      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18382      * <p>
18383      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18384      * mutate the drawable and apply the specified tint and tint mode using
18385      * {@link Drawable#setTintList(ColorStateList)}.
18386      *
18387      * @param tint the tint to apply, may be {@code null} to clear tint
18388      *
18389      * @attr ref android.R.styleable#View_backgroundTint
18390      * @see #getBackgroundTintList()
18391      * @see Drawable#setTintList(ColorStateList)
18392      */
setBackgroundTintList(@ullable ColorStateList tint)18393     public void setBackgroundTintList(@Nullable ColorStateList tint) {
18394         if (mBackgroundTint == null) {
18395             mBackgroundTint = new TintInfo();
18396         }
18397         mBackgroundTint.mTintList = tint;
18398         mBackgroundTint.mHasTintList = true;
18399 
18400         applyBackgroundTint();
18401     }
18402 
18403     /**
18404      * Return the tint applied to the background drawable, if specified.
18405      *
18406      * @return the tint applied to the background drawable
18407      * @attr ref android.R.styleable#View_backgroundTint
18408      * @see #setBackgroundTintList(ColorStateList)
18409      */
18410     @Nullable
getBackgroundTintList()18411     public ColorStateList getBackgroundTintList() {
18412         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18413     }
18414 
18415     /**
18416      * Specifies the blending mode used to apply the tint specified by
18417      * {@link #setBackgroundTintList(ColorStateList)}} to the background
18418      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18419      *
18420      * @param tintMode the blending mode used to apply the tint, may be
18421      *                 {@code null} to clear tint
18422      * @attr ref android.R.styleable#View_backgroundTintMode
18423      * @see #getBackgroundTintMode()
18424      * @see Drawable#setTintMode(PorterDuff.Mode)
18425      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)18426     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18427         if (mBackgroundTint == null) {
18428             mBackgroundTint = new TintInfo();
18429         }
18430         mBackgroundTint.mTintMode = tintMode;
18431         mBackgroundTint.mHasTintMode = true;
18432 
18433         applyBackgroundTint();
18434     }
18435 
18436     /**
18437      * Return the blending mode used to apply the tint to the background
18438      * drawable, if specified.
18439      *
18440      * @return the blending mode used to apply the tint to the background
18441      *         drawable
18442      * @attr ref android.R.styleable#View_backgroundTintMode
18443      * @see #setBackgroundTintMode(PorterDuff.Mode)
18444      */
18445     @Nullable
getBackgroundTintMode()18446     public PorterDuff.Mode getBackgroundTintMode() {
18447         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18448     }
18449 
applyBackgroundTint()18450     private void applyBackgroundTint() {
18451         if (mBackground != null && mBackgroundTint != null) {
18452             final TintInfo tintInfo = mBackgroundTint;
18453             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18454                 mBackground = mBackground.mutate();
18455 
18456                 if (tintInfo.mHasTintList) {
18457                     mBackground.setTintList(tintInfo.mTintList);
18458                 }
18459 
18460                 if (tintInfo.mHasTintMode) {
18461                     mBackground.setTintMode(tintInfo.mTintMode);
18462                 }
18463 
18464                 // The drawable (or one of its children) may not have been
18465                 // stateful before applying the tint, so let's try again.
18466                 if (mBackground.isStateful()) {
18467                     mBackground.setState(getDrawableState());
18468                 }
18469             }
18470         }
18471     }
18472 
18473     /**
18474      * Returns the drawable used as the foreground of this View. The
18475      * foreground drawable, if non-null, is always drawn on top of the view's content.
18476      *
18477      * @return a Drawable or null if no foreground was set
18478      *
18479      * @see #onDrawForeground(Canvas)
18480      */
getForeground()18481     public Drawable getForeground() {
18482         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18483     }
18484 
18485     /**
18486      * Supply a Drawable that is to be rendered on top of all of the content in the view.
18487      *
18488      * @param foreground the Drawable to be drawn on top of the children
18489      *
18490      * @attr ref android.R.styleable#View_foreground
18491      */
setForeground(Drawable foreground)18492     public void setForeground(Drawable foreground) {
18493         if (mForegroundInfo == null) {
18494             if (foreground == null) {
18495                 // Nothing to do.
18496                 return;
18497             }
18498             mForegroundInfo = new ForegroundInfo();
18499         }
18500 
18501         if (foreground == mForegroundInfo.mDrawable) {
18502             // Nothing to do
18503             return;
18504         }
18505 
18506         if (mForegroundInfo.mDrawable != null) {
18507             if (isAttachedToWindow()) {
18508                 mForegroundInfo.mDrawable.setVisible(false, false);
18509             }
18510             mForegroundInfo.mDrawable.setCallback(null);
18511             unscheduleDrawable(mForegroundInfo.mDrawable);
18512         }
18513 
18514         mForegroundInfo.mDrawable = foreground;
18515         mForegroundInfo.mBoundsChanged = true;
18516         if (foreground != null) {
18517             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18518                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18519             }
18520             foreground.setLayoutDirection(getLayoutDirection());
18521             if (foreground.isStateful()) {
18522                 foreground.setState(getDrawableState());
18523             }
18524             applyForegroundTint();
18525             if (isAttachedToWindow()) {
18526                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18527             }
18528             // Set callback last, since the view may still be initializing.
18529             foreground.setCallback(this);
18530         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18531             mPrivateFlags |= PFLAG_SKIP_DRAW;
18532         }
18533         requestLayout();
18534         invalidate();
18535     }
18536 
18537     /**
18538      * Magic bit used to support features of framework-internal window decor implementation details.
18539      * This used to live exclusively in FrameLayout.
18540      *
18541      * @return true if the foreground should draw inside the padding region or false
18542      *         if it should draw inset by the view's padding
18543      * @hide internal use only; only used by FrameLayout and internal screen layouts.
18544      */
isForegroundInsidePadding()18545     public boolean isForegroundInsidePadding() {
18546         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18547     }
18548 
18549     /**
18550      * Describes how the foreground is positioned.
18551      *
18552      * @return foreground gravity.
18553      *
18554      * @see #setForegroundGravity(int)
18555      *
18556      * @attr ref android.R.styleable#View_foregroundGravity
18557      */
getForegroundGravity()18558     public int getForegroundGravity() {
18559         return mForegroundInfo != null ? mForegroundInfo.mGravity
18560                 : Gravity.START | Gravity.TOP;
18561     }
18562 
18563     /**
18564      * Describes how the foreground is positioned. Defaults to START and TOP.
18565      *
18566      * @param gravity see {@link android.view.Gravity}
18567      *
18568      * @see #getForegroundGravity()
18569      *
18570      * @attr ref android.R.styleable#View_foregroundGravity
18571      */
setForegroundGravity(int gravity)18572     public void setForegroundGravity(int gravity) {
18573         if (mForegroundInfo == null) {
18574             mForegroundInfo = new ForegroundInfo();
18575         }
18576 
18577         if (mForegroundInfo.mGravity != gravity) {
18578             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18579                 gravity |= Gravity.START;
18580             }
18581 
18582             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18583                 gravity |= Gravity.TOP;
18584             }
18585 
18586             mForegroundInfo.mGravity = gravity;
18587             requestLayout();
18588         }
18589     }
18590 
18591     /**
18592      * Applies a tint to the foreground drawable. Does not modify the current tint
18593      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18594      * <p>
18595      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18596      * mutate the drawable and apply the specified tint and tint mode using
18597      * {@link Drawable#setTintList(ColorStateList)}.
18598      *
18599      * @param tint the tint to apply, may be {@code null} to clear tint
18600      *
18601      * @attr ref android.R.styleable#View_foregroundTint
18602      * @see #getForegroundTintList()
18603      * @see Drawable#setTintList(ColorStateList)
18604      */
setForegroundTintList(@ullable ColorStateList tint)18605     public void setForegroundTintList(@Nullable ColorStateList tint) {
18606         if (mForegroundInfo == null) {
18607             mForegroundInfo = new ForegroundInfo();
18608         }
18609         if (mForegroundInfo.mTintInfo == null) {
18610             mForegroundInfo.mTintInfo = new TintInfo();
18611         }
18612         mForegroundInfo.mTintInfo.mTintList = tint;
18613         mForegroundInfo.mTintInfo.mHasTintList = true;
18614 
18615         applyForegroundTint();
18616     }
18617 
18618     /**
18619      * Return the tint applied to the foreground drawable, if specified.
18620      *
18621      * @return the tint applied to the foreground drawable
18622      * @attr ref android.R.styleable#View_foregroundTint
18623      * @see #setForegroundTintList(ColorStateList)
18624      */
18625     @Nullable
getForegroundTintList()18626     public ColorStateList getForegroundTintList() {
18627         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18628                 ? mForegroundInfo.mTintInfo.mTintList : null;
18629     }
18630 
18631     /**
18632      * Specifies the blending mode used to apply the tint specified by
18633      * {@link #setForegroundTintList(ColorStateList)}} to the background
18634      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18635      *
18636      * @param tintMode the blending mode used to apply the tint, may be
18637      *                 {@code null} to clear tint
18638      * @attr ref android.R.styleable#View_foregroundTintMode
18639      * @see #getForegroundTintMode()
18640      * @see Drawable#setTintMode(PorterDuff.Mode)
18641      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)18642     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18643         if (mForegroundInfo == null) {
18644             mForegroundInfo = new ForegroundInfo();
18645         }
18646         if (mForegroundInfo.mTintInfo == null) {
18647             mForegroundInfo.mTintInfo = new TintInfo();
18648         }
18649         mForegroundInfo.mTintInfo.mTintMode = tintMode;
18650         mForegroundInfo.mTintInfo.mHasTintMode = true;
18651 
18652         applyForegroundTint();
18653     }
18654 
18655     /**
18656      * Return the blending mode used to apply the tint to the foreground
18657      * drawable, if specified.
18658      *
18659      * @return the blending mode used to apply the tint to the foreground
18660      *         drawable
18661      * @attr ref android.R.styleable#View_foregroundTintMode
18662      * @see #setForegroundTintMode(PorterDuff.Mode)
18663      */
18664     @Nullable
getForegroundTintMode()18665     public PorterDuff.Mode getForegroundTintMode() {
18666         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18667                 ? mForegroundInfo.mTintInfo.mTintMode : null;
18668     }
18669 
applyForegroundTint()18670     private void applyForegroundTint() {
18671         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18672                 && mForegroundInfo.mTintInfo != null) {
18673             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18674             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18675                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18676 
18677                 if (tintInfo.mHasTintList) {
18678                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18679                 }
18680 
18681                 if (tintInfo.mHasTintMode) {
18682                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18683                 }
18684 
18685                 // The drawable (or one of its children) may not have been
18686                 // stateful before applying the tint, so let's try again.
18687                 if (mForegroundInfo.mDrawable.isStateful()) {
18688                     mForegroundInfo.mDrawable.setState(getDrawableState());
18689                 }
18690             }
18691         }
18692     }
18693 
18694     /**
18695      * Draw any foreground content for this view.
18696      *
18697      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18698      * drawable or other view-specific decorations. The foreground is drawn on top of the
18699      * primary view content.</p>
18700      *
18701      * @param canvas canvas to draw into
18702      */
onDrawForeground(Canvas canvas)18703     public void onDrawForeground(Canvas canvas) {
18704         onDrawScrollIndicators(canvas);
18705         onDrawScrollBars(canvas);
18706 
18707         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18708         if (foreground != null) {
18709             if (mForegroundInfo.mBoundsChanged) {
18710                 mForegroundInfo.mBoundsChanged = false;
18711                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
18712                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18713 
18714                 if (mForegroundInfo.mInsidePadding) {
18715                     selfBounds.set(0, 0, getWidth(), getHeight());
18716                 } else {
18717                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
18718                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18719                 }
18720 
18721                 final int ld = getLayoutDirection();
18722                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18723                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18724                 foreground.setBounds(overlayBounds);
18725             }
18726 
18727             foreground.draw(canvas);
18728         }
18729     }
18730 
18731     /**
18732      * Sets the padding. The view may add on the space required to display
18733      * the scrollbars, depending on the style and visibility of the scrollbars.
18734      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18735      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18736      * from the values set in this call.
18737      *
18738      * @attr ref android.R.styleable#View_padding
18739      * @attr ref android.R.styleable#View_paddingBottom
18740      * @attr ref android.R.styleable#View_paddingLeft
18741      * @attr ref android.R.styleable#View_paddingRight
18742      * @attr ref android.R.styleable#View_paddingTop
18743      * @param left the left padding in pixels
18744      * @param top the top padding in pixels
18745      * @param right the right padding in pixels
18746      * @param bottom the bottom padding in pixels
18747      */
setPadding(int left, int top, int right, int bottom)18748     public void setPadding(int left, int top, int right, int bottom) {
18749         resetResolvedPaddingInternal();
18750 
18751         mUserPaddingStart = UNDEFINED_PADDING;
18752         mUserPaddingEnd = UNDEFINED_PADDING;
18753 
18754         mUserPaddingLeftInitial = left;
18755         mUserPaddingRightInitial = right;
18756 
18757         mLeftPaddingDefined = true;
18758         mRightPaddingDefined = true;
18759 
18760         internalSetPadding(left, top, right, bottom);
18761     }
18762 
18763     /**
18764      * @hide
18765      */
internalSetPadding(int left, int top, int right, int bottom)18766     protected void internalSetPadding(int left, int top, int right, int bottom) {
18767         mUserPaddingLeft = left;
18768         mUserPaddingRight = right;
18769         mUserPaddingBottom = bottom;
18770 
18771         final int viewFlags = mViewFlags;
18772         boolean changed = false;
18773 
18774         // Common case is there are no scroll bars.
18775         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18776             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18777                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18778                         ? 0 : getVerticalScrollbarWidth();
18779                 switch (mVerticalScrollbarPosition) {
18780                     case SCROLLBAR_POSITION_DEFAULT:
18781                         if (isLayoutRtl()) {
18782                             left += offset;
18783                         } else {
18784                             right += offset;
18785                         }
18786                         break;
18787                     case SCROLLBAR_POSITION_RIGHT:
18788                         right += offset;
18789                         break;
18790                     case SCROLLBAR_POSITION_LEFT:
18791                         left += offset;
18792                         break;
18793                 }
18794             }
18795             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18796                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18797                         ? 0 : getHorizontalScrollbarHeight();
18798             }
18799         }
18800 
18801         if (mPaddingLeft != left) {
18802             changed = true;
18803             mPaddingLeft = left;
18804         }
18805         if (mPaddingTop != top) {
18806             changed = true;
18807             mPaddingTop = top;
18808         }
18809         if (mPaddingRight != right) {
18810             changed = true;
18811             mPaddingRight = right;
18812         }
18813         if (mPaddingBottom != bottom) {
18814             changed = true;
18815             mPaddingBottom = bottom;
18816         }
18817 
18818         if (changed) {
18819             requestLayout();
18820             invalidateOutline();
18821         }
18822     }
18823 
18824     /**
18825      * Sets the relative padding. The view may add on the space required to display
18826      * the scrollbars, depending on the style and visibility of the scrollbars.
18827      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18828      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18829      * from the values set in this call.
18830      *
18831      * @attr ref android.R.styleable#View_padding
18832      * @attr ref android.R.styleable#View_paddingBottom
18833      * @attr ref android.R.styleable#View_paddingStart
18834      * @attr ref android.R.styleable#View_paddingEnd
18835      * @attr ref android.R.styleable#View_paddingTop
18836      * @param start the start padding in pixels
18837      * @param top the top padding in pixels
18838      * @param end the end padding in pixels
18839      * @param bottom the bottom padding in pixels
18840      */
setPaddingRelative(int start, int top, int end, int bottom)18841     public void setPaddingRelative(int start, int top, int end, int bottom) {
18842         resetResolvedPaddingInternal();
18843 
18844         mUserPaddingStart = start;
18845         mUserPaddingEnd = end;
18846         mLeftPaddingDefined = true;
18847         mRightPaddingDefined = true;
18848 
18849         switch(getLayoutDirection()) {
18850             case LAYOUT_DIRECTION_RTL:
18851                 mUserPaddingLeftInitial = end;
18852                 mUserPaddingRightInitial = start;
18853                 internalSetPadding(end, top, start, bottom);
18854                 break;
18855             case LAYOUT_DIRECTION_LTR:
18856             default:
18857                 mUserPaddingLeftInitial = start;
18858                 mUserPaddingRightInitial = end;
18859                 internalSetPadding(start, top, end, bottom);
18860         }
18861     }
18862 
18863     /**
18864      * Returns the top padding of this view.
18865      *
18866      * @return the top padding in pixels
18867      */
getPaddingTop()18868     public int getPaddingTop() {
18869         return mPaddingTop;
18870     }
18871 
18872     /**
18873      * Returns the bottom padding of this view. If there are inset and enabled
18874      * scrollbars, this value may include the space required to display the
18875      * scrollbars as well.
18876      *
18877      * @return the bottom padding in pixels
18878      */
getPaddingBottom()18879     public int getPaddingBottom() {
18880         return mPaddingBottom;
18881     }
18882 
18883     /**
18884      * Returns the left padding of this view. If there are inset and enabled
18885      * scrollbars, this value may include the space required to display the
18886      * scrollbars as well.
18887      *
18888      * @return the left padding in pixels
18889      */
getPaddingLeft()18890     public int getPaddingLeft() {
18891         if (!isPaddingResolved()) {
18892             resolvePadding();
18893         }
18894         return mPaddingLeft;
18895     }
18896 
18897     /**
18898      * Returns the start padding of this view depending on its resolved layout direction.
18899      * If there are inset and enabled scrollbars, this value may include the space
18900      * required to display the scrollbars as well.
18901      *
18902      * @return the start padding in pixels
18903      */
getPaddingStart()18904     public int getPaddingStart() {
18905         if (!isPaddingResolved()) {
18906             resolvePadding();
18907         }
18908         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18909                 mPaddingRight : mPaddingLeft;
18910     }
18911 
18912     /**
18913      * Returns the right padding of this view. If there are inset and enabled
18914      * scrollbars, this value may include the space required to display the
18915      * scrollbars as well.
18916      *
18917      * @return the right padding in pixels
18918      */
getPaddingRight()18919     public int getPaddingRight() {
18920         if (!isPaddingResolved()) {
18921             resolvePadding();
18922         }
18923         return mPaddingRight;
18924     }
18925 
18926     /**
18927      * Returns the end padding of this view depending on its resolved layout direction.
18928      * If there are inset and enabled scrollbars, this value may include the space
18929      * required to display the scrollbars as well.
18930      *
18931      * @return the end padding in pixels
18932      */
getPaddingEnd()18933     public int getPaddingEnd() {
18934         if (!isPaddingResolved()) {
18935             resolvePadding();
18936         }
18937         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18938                 mPaddingLeft : mPaddingRight;
18939     }
18940 
18941     /**
18942      * Return if the padding has been set through relative values
18943      * {@link #setPaddingRelative(int, int, int, int)} or through
18944      * @attr ref android.R.styleable#View_paddingStart or
18945      * @attr ref android.R.styleable#View_paddingEnd
18946      *
18947      * @return true if the padding is relative or false if it is not.
18948      */
isPaddingRelative()18949     public boolean isPaddingRelative() {
18950         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18951     }
18952 
computeOpticalInsets()18953     Insets computeOpticalInsets() {
18954         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18955     }
18956 
18957     /**
18958      * @hide
18959      */
resetPaddingToInitialValues()18960     public void resetPaddingToInitialValues() {
18961         if (isRtlCompatibilityMode()) {
18962             mPaddingLeft = mUserPaddingLeftInitial;
18963             mPaddingRight = mUserPaddingRightInitial;
18964             return;
18965         }
18966         if (isLayoutRtl()) {
18967             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18968             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18969         } else {
18970             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18971             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18972         }
18973     }
18974 
18975     /**
18976      * @hide
18977      */
getOpticalInsets()18978     public Insets getOpticalInsets() {
18979         if (mLayoutInsets == null) {
18980             mLayoutInsets = computeOpticalInsets();
18981         }
18982         return mLayoutInsets;
18983     }
18984 
18985     /**
18986      * Set this view's optical insets.
18987      *
18988      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18989      * property. Views that compute their own optical insets should call it as part of measurement.
18990      * This method does not request layout. If you are setting optical insets outside of
18991      * measure/layout itself you will want to call requestLayout() yourself.
18992      * </p>
18993      * @hide
18994      */
setOpticalInsets(Insets insets)18995     public void setOpticalInsets(Insets insets) {
18996         mLayoutInsets = insets;
18997     }
18998 
18999     /**
19000      * Changes the selection state of this view. A view can be selected or not.
19001      * Note that selection is not the same as focus. Views are typically
19002      * selected in the context of an AdapterView like ListView or GridView;
19003      * the selected view is the view that is highlighted.
19004      *
19005      * @param selected true if the view must be selected, false otherwise
19006      */
setSelected(boolean selected)19007     public void setSelected(boolean selected) {
19008         //noinspection DoubleNegation
19009         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19010             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19011             if (!selected) resetPressedState();
19012             invalidate(true);
19013             refreshDrawableState();
19014             dispatchSetSelected(selected);
19015             if (selected) {
19016                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19017             } else {
19018                 notifyViewAccessibilityStateChangedIfNeeded(
19019                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19020             }
19021         }
19022     }
19023 
19024     /**
19025      * Dispatch setSelected to all of this View's children.
19026      *
19027      * @see #setSelected(boolean)
19028      *
19029      * @param selected The new selected state
19030      */
dispatchSetSelected(boolean selected)19031     protected void dispatchSetSelected(boolean selected) {
19032     }
19033 
19034     /**
19035      * Indicates the selection state of this view.
19036      *
19037      * @return true if the view is selected, false otherwise
19038      */
19039     @ViewDebug.ExportedProperty
isSelected()19040     public boolean isSelected() {
19041         return (mPrivateFlags & PFLAG_SELECTED) != 0;
19042     }
19043 
19044     /**
19045      * Changes the activated state of this view. A view can be activated or not.
19046      * Note that activation is not the same as selection.  Selection is
19047      * a transient property, representing the view (hierarchy) the user is
19048      * currently interacting with.  Activation is a longer-term state that the
19049      * user can move views in and out of.  For example, in a list view with
19050      * single or multiple selection enabled, the views in the current selection
19051      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19052      * here.)  The activated state is propagated down to children of the view it
19053      * is set on.
19054      *
19055      * @param activated true if the view must be activated, false otherwise
19056      */
setActivated(boolean activated)19057     public void setActivated(boolean activated) {
19058         //noinspection DoubleNegation
19059         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19060             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19061             invalidate(true);
19062             refreshDrawableState();
19063             dispatchSetActivated(activated);
19064         }
19065     }
19066 
19067     /**
19068      * Dispatch setActivated to all of this View's children.
19069      *
19070      * @see #setActivated(boolean)
19071      *
19072      * @param activated The new activated state
19073      */
dispatchSetActivated(boolean activated)19074     protected void dispatchSetActivated(boolean activated) {
19075     }
19076 
19077     /**
19078      * Indicates the activation state of this view.
19079      *
19080      * @return true if the view is activated, false otherwise
19081      */
19082     @ViewDebug.ExportedProperty
isActivated()19083     public boolean isActivated() {
19084         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19085     }
19086 
19087     /**
19088      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19089      * observer can be used to get notifications when global events, like
19090      * layout, happen.
19091      *
19092      * The returned ViewTreeObserver observer is not guaranteed to remain
19093      * valid for the lifetime of this View. If the caller of this method keeps
19094      * a long-lived reference to ViewTreeObserver, it should always check for
19095      * the return value of {@link ViewTreeObserver#isAlive()}.
19096      *
19097      * @return The ViewTreeObserver for this view's hierarchy.
19098      */
getViewTreeObserver()19099     public ViewTreeObserver getViewTreeObserver() {
19100         if (mAttachInfo != null) {
19101             return mAttachInfo.mTreeObserver;
19102         }
19103         if (mFloatingTreeObserver == null) {
19104             mFloatingTreeObserver = new ViewTreeObserver();
19105         }
19106         return mFloatingTreeObserver;
19107     }
19108 
19109     /**
19110      * <p>Finds the topmost view in the current view hierarchy.</p>
19111      *
19112      * @return the topmost view containing this view
19113      */
getRootView()19114     public View getRootView() {
19115         if (mAttachInfo != null) {
19116             final View v = mAttachInfo.mRootView;
19117             if (v != null) {
19118                 return v;
19119             }
19120         }
19121 
19122         View parent = this;
19123 
19124         while (parent.mParent != null && parent.mParent instanceof View) {
19125             parent = (View) parent.mParent;
19126         }
19127 
19128         return parent;
19129     }
19130 
19131     /**
19132      * Transforms a motion event from view-local coordinates to on-screen
19133      * coordinates.
19134      *
19135      * @param ev the view-local motion event
19136      * @return false if the transformation could not be applied
19137      * @hide
19138      */
toGlobalMotionEvent(MotionEvent ev)19139     public boolean toGlobalMotionEvent(MotionEvent ev) {
19140         final AttachInfo info = mAttachInfo;
19141         if (info == null) {
19142             return false;
19143         }
19144 
19145         final Matrix m = info.mTmpMatrix;
19146         m.set(Matrix.IDENTITY_MATRIX);
19147         transformMatrixToGlobal(m);
19148         ev.transform(m);
19149         return true;
19150     }
19151 
19152     /**
19153      * Transforms a motion event from on-screen coordinates to view-local
19154      * coordinates.
19155      *
19156      * @param ev the on-screen motion event
19157      * @return false if the transformation could not be applied
19158      * @hide
19159      */
toLocalMotionEvent(MotionEvent ev)19160     public boolean toLocalMotionEvent(MotionEvent ev) {
19161         final AttachInfo info = mAttachInfo;
19162         if (info == null) {
19163             return false;
19164         }
19165 
19166         final Matrix m = info.mTmpMatrix;
19167         m.set(Matrix.IDENTITY_MATRIX);
19168         transformMatrixToLocal(m);
19169         ev.transform(m);
19170         return true;
19171     }
19172 
19173     /**
19174      * Modifies the input matrix such that it maps view-local coordinates to
19175      * on-screen coordinates.
19176      *
19177      * @param m input matrix to modify
19178      * @hide
19179      */
transformMatrixToGlobal(Matrix m)19180     public void transformMatrixToGlobal(Matrix m) {
19181         final ViewParent parent = mParent;
19182         if (parent instanceof View) {
19183             final View vp = (View) parent;
19184             vp.transformMatrixToGlobal(m);
19185             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19186         } else if (parent instanceof ViewRootImpl) {
19187             final ViewRootImpl vr = (ViewRootImpl) parent;
19188             vr.transformMatrixToGlobal(m);
19189             m.preTranslate(0, -vr.mCurScrollY);
19190         }
19191 
19192         m.preTranslate(mLeft, mTop);
19193 
19194         if (!hasIdentityMatrix()) {
19195             m.preConcat(getMatrix());
19196         }
19197     }
19198 
19199     /**
19200      * Modifies the input matrix such that it maps on-screen coordinates to
19201      * view-local coordinates.
19202      *
19203      * @param m input matrix to modify
19204      * @hide
19205      */
transformMatrixToLocal(Matrix m)19206     public void transformMatrixToLocal(Matrix m) {
19207         final ViewParent parent = mParent;
19208         if (parent instanceof View) {
19209             final View vp = (View) parent;
19210             vp.transformMatrixToLocal(m);
19211             m.postTranslate(vp.mScrollX, vp.mScrollY);
19212         } else if (parent instanceof ViewRootImpl) {
19213             final ViewRootImpl vr = (ViewRootImpl) parent;
19214             vr.transformMatrixToLocal(m);
19215             m.postTranslate(0, vr.mCurScrollY);
19216         }
19217 
19218         m.postTranslate(-mLeft, -mTop);
19219 
19220         if (!hasIdentityMatrix()) {
19221             m.postConcat(getInverseMatrix());
19222         }
19223     }
19224 
19225     /**
19226      * @hide
19227      */
19228     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19229             @ViewDebug.IntToString(from = 0, to = "x"),
19230             @ViewDebug.IntToString(from = 1, to = "y")
19231     })
getLocationOnScreen()19232     public int[] getLocationOnScreen() {
19233         int[] location = new int[2];
19234         getLocationOnScreen(location);
19235         return location;
19236     }
19237 
19238     /**
19239      * <p>Computes the coordinates of this view on the screen. The argument
19240      * must be an array of two integers. After the method returns, the array
19241      * contains the x and y location in that order.</p>
19242      *
19243      * @param outLocation an array of two integers in which to hold the coordinates
19244      */
getLocationOnScreen(@ize2) int[] outLocation)19245     public void getLocationOnScreen(@Size(2) int[] outLocation) {
19246         getLocationInWindow(outLocation);
19247 
19248         final AttachInfo info = mAttachInfo;
19249         if (info != null) {
19250             outLocation[0] += info.mWindowLeft;
19251             outLocation[1] += info.mWindowTop;
19252         }
19253     }
19254 
19255     /**
19256      * <p>Computes the coordinates of this view in its window. The argument
19257      * must be an array of two integers. After the method returns, the array
19258      * contains the x and y location in that order.</p>
19259      *
19260      * @param outLocation an array of two integers in which to hold the coordinates
19261      */
getLocationInWindow(@ize2) int[] outLocation)19262     public void getLocationInWindow(@Size(2) int[] outLocation) {
19263         if (outLocation == null || outLocation.length < 2) {
19264             throw new IllegalArgumentException("outLocation must be an array of two integers");
19265         }
19266 
19267         outLocation[0] = 0;
19268         outLocation[1] = 0;
19269 
19270         transformFromViewToWindowSpace(outLocation);
19271     }
19272 
19273     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)19274     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19275         if (inOutLocation == null || inOutLocation.length < 2) {
19276             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19277         }
19278 
19279         if (mAttachInfo == null) {
19280             // When the view is not attached to a window, this method does not make sense
19281             inOutLocation[0] = inOutLocation[1] = 0;
19282             return;
19283         }
19284 
19285         float position[] = mAttachInfo.mTmpTransformLocation;
19286         position[0] = inOutLocation[0];
19287         position[1] = inOutLocation[1];
19288 
19289         if (!hasIdentityMatrix()) {
19290             getMatrix().mapPoints(position);
19291         }
19292 
19293         position[0] += mLeft;
19294         position[1] += mTop;
19295 
19296         ViewParent viewParent = mParent;
19297         while (viewParent instanceof View) {
19298             final View view = (View) viewParent;
19299 
19300             position[0] -= view.mScrollX;
19301             position[1] -= view.mScrollY;
19302 
19303             if (!view.hasIdentityMatrix()) {
19304                 view.getMatrix().mapPoints(position);
19305             }
19306 
19307             position[0] += view.mLeft;
19308             position[1] += view.mTop;
19309 
19310             viewParent = view.mParent;
19311          }
19312 
19313         if (viewParent instanceof ViewRootImpl) {
19314             // *cough*
19315             final ViewRootImpl vr = (ViewRootImpl) viewParent;
19316             position[1] -= vr.mCurScrollY;
19317         }
19318 
19319         inOutLocation[0] = Math.round(position[0]);
19320         inOutLocation[1] = Math.round(position[1]);
19321     }
19322 
19323     /**
19324      * {@hide}
19325      * @param id the id of the view to be found
19326      * @return the view of the specified id, null if cannot be found
19327      */
findViewTraversal(@dRes int id)19328     protected View findViewTraversal(@IdRes int id) {
19329         if (id == mID) {
19330             return this;
19331         }
19332         return null;
19333     }
19334 
19335     /**
19336      * {@hide}
19337      * @param tag the tag of the view to be found
19338      * @return the view of specified tag, null if cannot be found
19339      */
findViewWithTagTraversal(Object tag)19340     protected View findViewWithTagTraversal(Object tag) {
19341         if (tag != null && tag.equals(mTag)) {
19342             return this;
19343         }
19344         return null;
19345     }
19346 
19347     /**
19348      * {@hide}
19349      * @param predicate The predicate to evaluate.
19350      * @param childToSkip If not null, ignores this child during the recursive traversal.
19351      * @return The first view that matches the predicate or null.
19352      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)19353     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19354         if (predicate.apply(this)) {
19355             return this;
19356         }
19357         return null;
19358     }
19359 
19360     /**
19361      * Look for a child view with the given id.  If this view has the given
19362      * id, return this view.
19363      *
19364      * @param id The id to search for.
19365      * @return The view that has the given id in the hierarchy or null
19366      */
19367     @Nullable
findViewById(@dRes int id)19368     public final View findViewById(@IdRes int id) {
19369         if (id < 0) {
19370             return null;
19371         }
19372         return findViewTraversal(id);
19373     }
19374 
19375     /**
19376      * Finds a view by its unuque and stable accessibility id.
19377      *
19378      * @param accessibilityId The searched accessibility id.
19379      * @return The found view.
19380      */
findViewByAccessibilityId(int accessibilityId)19381     final View findViewByAccessibilityId(int accessibilityId) {
19382         if (accessibilityId < 0) {
19383             return null;
19384         }
19385         View view = findViewByAccessibilityIdTraversal(accessibilityId);
19386         if (view != null) {
19387             return view.includeForAccessibility() ? view : null;
19388         }
19389         return null;
19390     }
19391 
19392     /**
19393      * Performs the traversal to find a view by its unuque and stable accessibility id.
19394      *
19395      * <strong>Note:</strong>This method does not stop at the root namespace
19396      * boundary since the user can touch the screen at an arbitrary location
19397      * potentially crossing the root namespace bounday which will send an
19398      * accessibility event to accessibility services and they should be able
19399      * to obtain the event source. Also accessibility ids are guaranteed to be
19400      * unique in the window.
19401      *
19402      * @param accessibilityId The accessibility id.
19403      * @return The found view.
19404      *
19405      * @hide
19406      */
findViewByAccessibilityIdTraversal(int accessibilityId)19407     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19408         if (getAccessibilityViewId() == accessibilityId) {
19409             return this;
19410         }
19411         return null;
19412     }
19413 
19414     /**
19415      * Look for a child view with the given tag.  If this view has the given
19416      * tag, return this view.
19417      *
19418      * @param tag The tag to search for, using "tag.equals(getTag())".
19419      * @return The View that has the given tag in the hierarchy or null
19420      */
findViewWithTag(Object tag)19421     public final View findViewWithTag(Object tag) {
19422         if (tag == null) {
19423             return null;
19424         }
19425         return findViewWithTagTraversal(tag);
19426     }
19427 
19428     /**
19429      * {@hide}
19430      * Look for a child view that matches the specified predicate.
19431      * If this view matches the predicate, return this view.
19432      *
19433      * @param predicate The predicate to evaluate.
19434      * @return The first view that matches the predicate or null.
19435      */
findViewByPredicate(Predicate<View> predicate)19436     public final View findViewByPredicate(Predicate<View> predicate) {
19437         return findViewByPredicateTraversal(predicate, null);
19438     }
19439 
19440     /**
19441      * {@hide}
19442      * Look for a child view that matches the specified predicate,
19443      * starting with the specified view and its descendents and then
19444      * recusively searching the ancestors and siblings of that view
19445      * until this view is reached.
19446      *
19447      * This method is useful in cases where the predicate does not match
19448      * a single unique view (perhaps multiple views use the same id)
19449      * and we are trying to find the view that is "closest" in scope to the
19450      * starting view.
19451      *
19452      * @param start The view to start from.
19453      * @param predicate The predicate to evaluate.
19454      * @return The first view that matches the predicate or null.
19455      */
findViewByPredicateInsideOut(View start, Predicate<View> predicate)19456     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19457         View childToSkip = null;
19458         for (;;) {
19459             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19460             if (view != null || start == this) {
19461                 return view;
19462             }
19463 
19464             ViewParent parent = start.getParent();
19465             if (parent == null || !(parent instanceof View)) {
19466                 return null;
19467             }
19468 
19469             childToSkip = start;
19470             start = (View) parent;
19471         }
19472     }
19473 
19474     /**
19475      * Sets the identifier for this view. The identifier does not have to be
19476      * unique in this view's hierarchy. The identifier should be a positive
19477      * number.
19478      *
19479      * @see #NO_ID
19480      * @see #getId()
19481      * @see #findViewById(int)
19482      *
19483      * @param id a number used to identify the view
19484      *
19485      * @attr ref android.R.styleable#View_id
19486      */
setId(@dRes int id)19487     public void setId(@IdRes int id) {
19488         mID = id;
19489         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19490             mID = generateViewId();
19491         }
19492     }
19493 
19494     /**
19495      * {@hide}
19496      *
19497      * @param isRoot true if the view belongs to the root namespace, false
19498      *        otherwise
19499      */
setIsRootNamespace(boolean isRoot)19500     public void setIsRootNamespace(boolean isRoot) {
19501         if (isRoot) {
19502             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19503         } else {
19504             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19505         }
19506     }
19507 
19508     /**
19509      * {@hide}
19510      *
19511      * @return true if the view belongs to the root namespace, false otherwise
19512      */
isRootNamespace()19513     public boolean isRootNamespace() {
19514         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19515     }
19516 
19517     /**
19518      * Returns this view's identifier.
19519      *
19520      * @return a positive integer used to identify the view or {@link #NO_ID}
19521      *         if the view has no ID
19522      *
19523      * @see #setId(int)
19524      * @see #findViewById(int)
19525      * @attr ref android.R.styleable#View_id
19526      */
19527     @IdRes
19528     @ViewDebug.CapturedViewProperty
getId()19529     public int getId() {
19530         return mID;
19531     }
19532 
19533     /**
19534      * Returns this view's tag.
19535      *
19536      * @return the Object stored in this view as a tag, or {@code null} if not
19537      *         set
19538      *
19539      * @see #setTag(Object)
19540      * @see #getTag(int)
19541      */
19542     @ViewDebug.ExportedProperty
getTag()19543     public Object getTag() {
19544         return mTag;
19545     }
19546 
19547     /**
19548      * Sets the tag associated with this view. A tag can be used to mark
19549      * a view in its hierarchy and does not have to be unique within the
19550      * hierarchy. Tags can also be used to store data within a view without
19551      * resorting to another data structure.
19552      *
19553      * @param tag an Object to tag the view with
19554      *
19555      * @see #getTag()
19556      * @see #setTag(int, Object)
19557      */
setTag(final Object tag)19558     public void setTag(final Object tag) {
19559         mTag = tag;
19560     }
19561 
19562     /**
19563      * Returns the tag associated with this view and the specified key.
19564      *
19565      * @param key The key identifying the tag
19566      *
19567      * @return the Object stored in this view as a tag, or {@code null} if not
19568      *         set
19569      *
19570      * @see #setTag(int, Object)
19571      * @see #getTag()
19572      */
getTag(int key)19573     public Object getTag(int key) {
19574         if (mKeyedTags != null) return mKeyedTags.get(key);
19575         return null;
19576     }
19577 
19578     /**
19579      * Sets a tag associated with this view and a key. A tag can be used
19580      * to mark a view in its hierarchy and does not have to be unique within
19581      * the hierarchy. Tags can also be used to store data within a view
19582      * without resorting to another data structure.
19583      *
19584      * The specified key should be an id declared in the resources of the
19585      * application to ensure it is unique (see the <a
19586      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19587      * Keys identified as belonging to
19588      * the Android framework or not associated with any package will cause
19589      * an {@link IllegalArgumentException} to be thrown.
19590      *
19591      * @param key The key identifying the tag
19592      * @param tag An Object to tag the view with
19593      *
19594      * @throws IllegalArgumentException If they specified key is not valid
19595      *
19596      * @see #setTag(Object)
19597      * @see #getTag(int)
19598      */
setTag(int key, final Object tag)19599     public void setTag(int key, final Object tag) {
19600         // If the package id is 0x00 or 0x01, it's either an undefined package
19601         // or a framework id
19602         if ((key >>> 24) < 2) {
19603             throw new IllegalArgumentException("The key must be an application-specific "
19604                     + "resource id.");
19605         }
19606 
19607         setKeyedTag(key, tag);
19608     }
19609 
19610     /**
19611      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19612      * framework id.
19613      *
19614      * @hide
19615      */
setTagInternal(int key, Object tag)19616     public void setTagInternal(int key, Object tag) {
19617         if ((key >>> 24) != 0x1) {
19618             throw new IllegalArgumentException("The key must be a framework-specific "
19619                     + "resource id.");
19620         }
19621 
19622         setKeyedTag(key, tag);
19623     }
19624 
setKeyedTag(int key, Object tag)19625     private void setKeyedTag(int key, Object tag) {
19626         if (mKeyedTags == null) {
19627             mKeyedTags = new SparseArray<Object>(2);
19628         }
19629 
19630         mKeyedTags.put(key, tag);
19631     }
19632 
19633     /**
19634      * Prints information about this view in the log output, with the tag
19635      * {@link #VIEW_LOG_TAG}.
19636      *
19637      * @hide
19638      */
debug()19639     public void debug() {
19640         debug(0);
19641     }
19642 
19643     /**
19644      * Prints information about this view in the log output, with the tag
19645      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19646      * indentation defined by the <code>depth</code>.
19647      *
19648      * @param depth the indentation level
19649      *
19650      * @hide
19651      */
debug(int depth)19652     protected void debug(int depth) {
19653         String output = debugIndent(depth - 1);
19654 
19655         output += "+ " + this;
19656         int id = getId();
19657         if (id != -1) {
19658             output += " (id=" + id + ")";
19659         }
19660         Object tag = getTag();
19661         if (tag != null) {
19662             output += " (tag=" + tag + ")";
19663         }
19664         Log.d(VIEW_LOG_TAG, output);
19665 
19666         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19667             output = debugIndent(depth) + " FOCUSED";
19668             Log.d(VIEW_LOG_TAG, output);
19669         }
19670 
19671         output = debugIndent(depth);
19672         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19673                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19674                 + "} ";
19675         Log.d(VIEW_LOG_TAG, output);
19676 
19677         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19678                 || mPaddingBottom != 0) {
19679             output = debugIndent(depth);
19680             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19681                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19682             Log.d(VIEW_LOG_TAG, output);
19683         }
19684 
19685         output = debugIndent(depth);
19686         output += "mMeasureWidth=" + mMeasuredWidth +
19687                 " mMeasureHeight=" + mMeasuredHeight;
19688         Log.d(VIEW_LOG_TAG, output);
19689 
19690         output = debugIndent(depth);
19691         if (mLayoutParams == null) {
19692             output += "BAD! no layout params";
19693         } else {
19694             output = mLayoutParams.debug(output);
19695         }
19696         Log.d(VIEW_LOG_TAG, output);
19697 
19698         output = debugIndent(depth);
19699         output += "flags={";
19700         output += View.printFlags(mViewFlags);
19701         output += "}";
19702         Log.d(VIEW_LOG_TAG, output);
19703 
19704         output = debugIndent(depth);
19705         output += "privateFlags={";
19706         output += View.printPrivateFlags(mPrivateFlags);
19707         output += "}";
19708         Log.d(VIEW_LOG_TAG, output);
19709     }
19710 
19711     /**
19712      * Creates a string of whitespaces used for indentation.
19713      *
19714      * @param depth the indentation level
19715      * @return a String containing (depth * 2 + 3) * 2 white spaces
19716      *
19717      * @hide
19718      */
debugIndent(int depth)19719     protected static String debugIndent(int depth) {
19720         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19721         for (int i = 0; i < (depth * 2) + 3; i++) {
19722             spaces.append(' ').append(' ');
19723         }
19724         return spaces.toString();
19725     }
19726 
19727     /**
19728      * <p>Return the offset of the widget's text baseline from the widget's top
19729      * boundary. If this widget does not support baseline alignment, this
19730      * method returns -1. </p>
19731      *
19732      * @return the offset of the baseline within the widget's bounds or -1
19733      *         if baseline alignment is not supported
19734      */
19735     @ViewDebug.ExportedProperty(category = "layout")
getBaseline()19736     public int getBaseline() {
19737         return -1;
19738     }
19739 
19740     /**
19741      * Returns whether the view hierarchy is currently undergoing a layout pass. This
19742      * information is useful to avoid situations such as calling {@link #requestLayout()} during
19743      * a layout pass.
19744      *
19745      * @return whether the view hierarchy is currently undergoing a layout pass
19746      */
isInLayout()19747     public boolean isInLayout() {
19748         ViewRootImpl viewRoot = getViewRootImpl();
19749         return (viewRoot != null && viewRoot.isInLayout());
19750     }
19751 
19752     /**
19753      * Call this when something has changed which has invalidated the
19754      * layout of this view. This will schedule a layout pass of the view
19755      * tree. This should not be called while the view hierarchy is currently in a layout
19756      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19757      * end of the current layout pass (and then layout will run again) or after the current
19758      * frame is drawn and the next layout occurs.
19759      *
19760      * <p>Subclasses which override this method should call the superclass method to
19761      * handle possible request-during-layout errors correctly.</p>
19762      */
19763     @CallSuper
requestLayout()19764     public void requestLayout() {
19765         if (mMeasureCache != null) mMeasureCache.clear();
19766 
19767         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19768             // Only trigger request-during-layout logic if this is the view requesting it,
19769             // not the views in its parent hierarchy
19770             ViewRootImpl viewRoot = getViewRootImpl();
19771             if (viewRoot != null && viewRoot.isInLayout()) {
19772                 if (!viewRoot.requestLayoutDuringLayout(this)) {
19773                     return;
19774                 }
19775             }
19776             mAttachInfo.mViewRequestingLayout = this;
19777         }
19778 
19779         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19780         mPrivateFlags |= PFLAG_INVALIDATED;
19781 
19782         if (mParent != null && !mParent.isLayoutRequested()) {
19783             mParent.requestLayout();
19784         }
19785         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19786             mAttachInfo.mViewRequestingLayout = null;
19787         }
19788     }
19789 
19790     /**
19791      * Forces this view to be laid out during the next layout pass.
19792      * This method does not call requestLayout() or forceLayout()
19793      * on the parent.
19794      */
forceLayout()19795     public void forceLayout() {
19796         if (mMeasureCache != null) mMeasureCache.clear();
19797 
19798         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19799         mPrivateFlags |= PFLAG_INVALIDATED;
19800     }
19801 
19802     /**
19803      * <p>
19804      * This is called to find out how big a view should be. The parent
19805      * supplies constraint information in the width and height parameters.
19806      * </p>
19807      *
19808      * <p>
19809      * The actual measurement work of a view is performed in
19810      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19811      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19812      * </p>
19813      *
19814      *
19815      * @param widthMeasureSpec Horizontal space requirements as imposed by the
19816      *        parent
19817      * @param heightMeasureSpec Vertical space requirements as imposed by the
19818      *        parent
19819      *
19820      * @see #onMeasure(int, int)
19821      */
measure(int widthMeasureSpec, int heightMeasureSpec)19822     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19823         boolean optical = isLayoutModeOptical(this);
19824         if (optical != isLayoutModeOptical(mParent)) {
19825             Insets insets = getOpticalInsets();
19826             int oWidth  = insets.left + insets.right;
19827             int oHeight = insets.top  + insets.bottom;
19828             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19829             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19830         }
19831 
19832         // Suppress sign extension for the low bytes
19833         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19834         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19835 
19836         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19837 
19838         // Optimize layout by avoiding an extra EXACTLY pass when the view is
19839         // already measured as the correct size. In API 23 and below, this
19840         // extra pass is required to make LinearLayout re-distribute weight.
19841         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19842                 || heightMeasureSpec != mOldHeightMeasureSpec;
19843         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19844                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19845         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19846                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19847         final boolean needsLayout = specChanged
19848                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19849 
19850         if (forceLayout || needsLayout) {
19851             // first clears the measured dimension flag
19852             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19853 
19854             resolveRtlPropertiesIfNeeded();
19855 
19856             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19857             if (cacheIndex < 0 || sIgnoreMeasureCache) {
19858                 // measure ourselves, this should set the measured dimension flag back
19859                 onMeasure(widthMeasureSpec, heightMeasureSpec);
19860                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19861             } else {
19862                 long value = mMeasureCache.valueAt(cacheIndex);
19863                 // Casting a long to int drops the high 32 bits, no mask needed
19864                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19865                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19866             }
19867 
19868             // flag not set, setMeasuredDimension() was not invoked, we raise
19869             // an exception to warn the developer
19870             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19871                 throw new IllegalStateException("View with id " + getId() + ": "
19872                         + getClass().getName() + "#onMeasure() did not set the"
19873                         + " measured dimension by calling"
19874                         + " setMeasuredDimension()");
19875             }
19876 
19877             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19878         }
19879 
19880         mOldWidthMeasureSpec = widthMeasureSpec;
19881         mOldHeightMeasureSpec = heightMeasureSpec;
19882 
19883         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19884                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19885     }
19886 
19887     /**
19888      * <p>
19889      * Measure the view and its content to determine the measured width and the
19890      * measured height. This method is invoked by {@link #measure(int, int)} and
19891      * should be overridden by subclasses to provide accurate and efficient
19892      * measurement of their contents.
19893      * </p>
19894      *
19895      * <p>
19896      * <strong>CONTRACT:</strong> When overriding this method, you
19897      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19898      * measured width and height of this view. Failure to do so will trigger an
19899      * <code>IllegalStateException</code>, thrown by
19900      * {@link #measure(int, int)}. Calling the superclass'
19901      * {@link #onMeasure(int, int)} is a valid use.
19902      * </p>
19903      *
19904      * <p>
19905      * The base class implementation of measure defaults to the background size,
19906      * unless a larger size is allowed by the MeasureSpec. Subclasses should
19907      * override {@link #onMeasure(int, int)} to provide better measurements of
19908      * their content.
19909      * </p>
19910      *
19911      * <p>
19912      * If this method is overridden, it is the subclass's responsibility to make
19913      * sure the measured height and width are at least the view's minimum height
19914      * and width ({@link #getSuggestedMinimumHeight()} and
19915      * {@link #getSuggestedMinimumWidth()}).
19916      * </p>
19917      *
19918      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19919      *                         The requirements are encoded with
19920      *                         {@link android.view.View.MeasureSpec}.
19921      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19922      *                         The requirements are encoded with
19923      *                         {@link android.view.View.MeasureSpec}.
19924      *
19925      * @see #getMeasuredWidth()
19926      * @see #getMeasuredHeight()
19927      * @see #setMeasuredDimension(int, int)
19928      * @see #getSuggestedMinimumHeight()
19929      * @see #getSuggestedMinimumWidth()
19930      * @see android.view.View.MeasureSpec#getMode(int)
19931      * @see android.view.View.MeasureSpec#getSize(int)
19932      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)19933     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19934         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19935                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19936     }
19937 
19938     /**
19939      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19940      * measured width and measured height. Failing to do so will trigger an
19941      * exception at measurement time.</p>
19942      *
19943      * @param measuredWidth The measured width of this view.  May be a complex
19944      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19945      * {@link #MEASURED_STATE_TOO_SMALL}.
19946      * @param measuredHeight The measured height of this view.  May be a complex
19947      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19948      * {@link #MEASURED_STATE_TOO_SMALL}.
19949      */
setMeasuredDimension(int measuredWidth, int measuredHeight)19950     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19951         boolean optical = isLayoutModeOptical(this);
19952         if (optical != isLayoutModeOptical(mParent)) {
19953             Insets insets = getOpticalInsets();
19954             int opticalWidth  = insets.left + insets.right;
19955             int opticalHeight = insets.top  + insets.bottom;
19956 
19957             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19958             measuredHeight += optical ? opticalHeight : -opticalHeight;
19959         }
19960         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19961     }
19962 
19963     /**
19964      * Sets the measured dimension without extra processing for things like optical bounds.
19965      * Useful for reapplying consistent values that have already been cooked with adjustments
19966      * for optical bounds, etc. such as those from the measurement cache.
19967      *
19968      * @param measuredWidth The measured width of this view.  May be a complex
19969      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19970      * {@link #MEASURED_STATE_TOO_SMALL}.
19971      * @param measuredHeight The measured height of this view.  May be a complex
19972      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19973      * {@link #MEASURED_STATE_TOO_SMALL}.
19974      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)19975     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19976         mMeasuredWidth = measuredWidth;
19977         mMeasuredHeight = measuredHeight;
19978 
19979         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19980     }
19981 
19982     /**
19983      * Merge two states as returned by {@link #getMeasuredState()}.
19984      * @param curState The current state as returned from a view or the result
19985      * of combining multiple views.
19986      * @param newState The new view state to combine.
19987      * @return Returns a new integer reflecting the combination of the two
19988      * states.
19989      */
combineMeasuredStates(int curState, int newState)19990     public static int combineMeasuredStates(int curState, int newState) {
19991         return curState | newState;
19992     }
19993 
19994     /**
19995      * Version of {@link #resolveSizeAndState(int, int, int)}
19996      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19997      */
resolveSize(int size, int measureSpec)19998     public static int resolveSize(int size, int measureSpec) {
19999         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
20000     }
20001 
20002     /**
20003      * Utility to reconcile a desired size and state, with constraints imposed
20004      * by a MeasureSpec. Will take the desired size, unless a different size
20005      * is imposed by the constraints. The returned value is a compound integer,
20006      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20007      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20008      * resulting size is smaller than the size the view wants to be.
20009      *
20010      * @param size How big the view wants to be.
20011      * @param measureSpec Constraints imposed by the parent.
20012      * @param childMeasuredState Size information bit mask for the view's
20013      *                           children.
20014      * @return Size information bit mask as defined by
20015      *         {@link #MEASURED_SIZE_MASK} and
20016      *         {@link #MEASURED_STATE_TOO_SMALL}.
20017      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)20018     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20019         final int specMode = MeasureSpec.getMode(measureSpec);
20020         final int specSize = MeasureSpec.getSize(measureSpec);
20021         final int result;
20022         switch (specMode) {
20023             case MeasureSpec.AT_MOST:
20024                 if (specSize < size) {
20025                     result = specSize | MEASURED_STATE_TOO_SMALL;
20026                 } else {
20027                     result = size;
20028                 }
20029                 break;
20030             case MeasureSpec.EXACTLY:
20031                 result = specSize;
20032                 break;
20033             case MeasureSpec.UNSPECIFIED:
20034             default:
20035                 result = size;
20036         }
20037         return result | (childMeasuredState & MEASURED_STATE_MASK);
20038     }
20039 
20040     /**
20041      * Utility to return a default size. Uses the supplied size if the
20042      * MeasureSpec imposed no constraints. Will get larger if allowed
20043      * by the MeasureSpec.
20044      *
20045      * @param size Default size for this view
20046      * @param measureSpec Constraints imposed by the parent
20047      * @return The size this view should be.
20048      */
getDefaultSize(int size, int measureSpec)20049     public static int getDefaultSize(int size, int measureSpec) {
20050         int result = size;
20051         int specMode = MeasureSpec.getMode(measureSpec);
20052         int specSize = MeasureSpec.getSize(measureSpec);
20053 
20054         switch (specMode) {
20055         case MeasureSpec.UNSPECIFIED:
20056             result = size;
20057             break;
20058         case MeasureSpec.AT_MOST:
20059         case MeasureSpec.EXACTLY:
20060             result = specSize;
20061             break;
20062         }
20063         return result;
20064     }
20065 
20066     /**
20067      * Returns the suggested minimum height that the view should use. This
20068      * returns the maximum of the view's minimum height
20069      * and the background's minimum height
20070      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20071      * <p>
20072      * When being used in {@link #onMeasure(int, int)}, the caller should still
20073      * ensure the returned height is within the requirements of the parent.
20074      *
20075      * @return The suggested minimum height of the view.
20076      */
getSuggestedMinimumHeight()20077     protected int getSuggestedMinimumHeight() {
20078         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20079 
20080     }
20081 
20082     /**
20083      * Returns the suggested minimum width that the view should use. This
20084      * returns the maximum of the view's minimum width
20085      * and the background's minimum width
20086      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20087      * <p>
20088      * When being used in {@link #onMeasure(int, int)}, the caller should still
20089      * ensure the returned width is within the requirements of the parent.
20090      *
20091      * @return The suggested minimum width of the view.
20092      */
getSuggestedMinimumWidth()20093     protected int getSuggestedMinimumWidth() {
20094         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20095     }
20096 
20097     /**
20098      * Returns the minimum height of the view.
20099      *
20100      * @return the minimum height the view will try to be.
20101      *
20102      * @see #setMinimumHeight(int)
20103      *
20104      * @attr ref android.R.styleable#View_minHeight
20105      */
getMinimumHeight()20106     public int getMinimumHeight() {
20107         return mMinHeight;
20108     }
20109 
20110     /**
20111      * Sets the minimum height of the view. It is not guaranteed the view will
20112      * be able to achieve this minimum height (for example, if its parent layout
20113      * constrains it with less available height).
20114      *
20115      * @param minHeight The minimum height the view will try to be.
20116      *
20117      * @see #getMinimumHeight()
20118      *
20119      * @attr ref android.R.styleable#View_minHeight
20120      */
20121     @RemotableViewMethod
setMinimumHeight(int minHeight)20122     public void setMinimumHeight(int minHeight) {
20123         mMinHeight = minHeight;
20124         requestLayout();
20125     }
20126 
20127     /**
20128      * Returns the minimum width of the view.
20129      *
20130      * @return the minimum width the view will try to be.
20131      *
20132      * @see #setMinimumWidth(int)
20133      *
20134      * @attr ref android.R.styleable#View_minWidth
20135      */
getMinimumWidth()20136     public int getMinimumWidth() {
20137         return mMinWidth;
20138     }
20139 
20140     /**
20141      * Sets the minimum width of the view. It is not guaranteed the view will
20142      * be able to achieve this minimum width (for example, if its parent layout
20143      * constrains it with less available width).
20144      *
20145      * @param minWidth The minimum width the view will try to be.
20146      *
20147      * @see #getMinimumWidth()
20148      *
20149      * @attr ref android.R.styleable#View_minWidth
20150      */
setMinimumWidth(int minWidth)20151     public void setMinimumWidth(int minWidth) {
20152         mMinWidth = minWidth;
20153         requestLayout();
20154 
20155     }
20156 
20157     /**
20158      * Get the animation currently associated with this view.
20159      *
20160      * @return The animation that is currently playing or
20161      *         scheduled to play for this view.
20162      */
getAnimation()20163     public Animation getAnimation() {
20164         return mCurrentAnimation;
20165     }
20166 
20167     /**
20168      * Start the specified animation now.
20169      *
20170      * @param animation the animation to start now
20171      */
startAnimation(Animation animation)20172     public void startAnimation(Animation animation) {
20173         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20174         setAnimation(animation);
20175         invalidateParentCaches();
20176         invalidate(true);
20177     }
20178 
20179     /**
20180      * Cancels any animations for this view.
20181      */
clearAnimation()20182     public void clearAnimation() {
20183         if (mCurrentAnimation != null) {
20184             mCurrentAnimation.detach();
20185         }
20186         mCurrentAnimation = null;
20187         invalidateParentIfNeeded();
20188     }
20189 
20190     /**
20191      * Sets the next animation to play for this view.
20192      * If you want the animation to play immediately, use
20193      * {@link #startAnimation(android.view.animation.Animation)} instead.
20194      * This method provides allows fine-grained
20195      * control over the start time and invalidation, but you
20196      * must make sure that 1) the animation has a start time set, and
20197      * 2) the view's parent (which controls animations on its children)
20198      * will be invalidated when the animation is supposed to
20199      * start.
20200      *
20201      * @param animation The next animation, or null.
20202      */
setAnimation(Animation animation)20203     public void setAnimation(Animation animation) {
20204         mCurrentAnimation = animation;
20205 
20206         if (animation != null) {
20207             // If the screen is off assume the animation start time is now instead of
20208             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20209             // would cause the animation to start when the screen turns back on
20210             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20211                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20212                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20213             }
20214             animation.reset();
20215         }
20216     }
20217 
20218     /**
20219      * Invoked by a parent ViewGroup to notify the start of the animation
20220      * currently associated with this view. If you override this method,
20221      * always call super.onAnimationStart();
20222      *
20223      * @see #setAnimation(android.view.animation.Animation)
20224      * @see #getAnimation()
20225      */
20226     @CallSuper
onAnimationStart()20227     protected void onAnimationStart() {
20228         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20229     }
20230 
20231     /**
20232      * Invoked by a parent ViewGroup to notify the end of the animation
20233      * currently associated with this view. If you override this method,
20234      * always call super.onAnimationEnd();
20235      *
20236      * @see #setAnimation(android.view.animation.Animation)
20237      * @see #getAnimation()
20238      */
20239     @CallSuper
onAnimationEnd()20240     protected void onAnimationEnd() {
20241         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20242     }
20243 
20244     /**
20245      * Invoked if there is a Transform that involves alpha. Subclass that can
20246      * draw themselves with the specified alpha should return true, and then
20247      * respect that alpha when their onDraw() is called. If this returns false
20248      * then the view may be redirected to draw into an offscreen buffer to
20249      * fulfill the request, which will look fine, but may be slower than if the
20250      * subclass handles it internally. The default implementation returns false.
20251      *
20252      * @param alpha The alpha (0..255) to apply to the view's drawing
20253      * @return true if the view can draw with the specified alpha.
20254      */
onSetAlpha(int alpha)20255     protected boolean onSetAlpha(int alpha) {
20256         return false;
20257     }
20258 
20259     /**
20260      * This is used by the RootView to perform an optimization when
20261      * the view hierarchy contains one or several SurfaceView.
20262      * SurfaceView is always considered transparent, but its children are not,
20263      * therefore all View objects remove themselves from the global transparent
20264      * region (passed as a parameter to this function).
20265      *
20266      * @param region The transparent region for this ViewAncestor (window).
20267      *
20268      * @return Returns true if the effective visibility of the view at this
20269      * point is opaque, regardless of the transparent region; returns false
20270      * if it is possible for underlying windows to be seen behind the view.
20271      *
20272      * {@hide}
20273      */
gatherTransparentRegion(Region region)20274     public boolean gatherTransparentRegion(Region region) {
20275         final AttachInfo attachInfo = mAttachInfo;
20276         if (region != null && attachInfo != null) {
20277             final int pflags = mPrivateFlags;
20278             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20279                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20280                 // remove it from the transparent region.
20281                 final int[] location = attachInfo.mTransparentLocation;
20282                 getLocationInWindow(location);
20283                 region.op(location[0], location[1], location[0] + mRight - mLeft,
20284                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
20285             } else {
20286                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20287                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20288                     // the background drawable's non-transparent parts from this transparent region.
20289                     applyDrawableToTransparentRegion(mBackground, region);
20290                 }
20291                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20292                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20293                     // Similarly, we remove the foreground drawable's non-transparent parts.
20294                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20295                 }
20296             }
20297         }
20298         return true;
20299     }
20300 
20301     /**
20302      * Play a sound effect for this view.
20303      *
20304      * <p>The framework will play sound effects for some built in actions, such as
20305      * clicking, but you may wish to play these effects in your widget,
20306      * for instance, for internal navigation.
20307      *
20308      * <p>The sound effect will only be played if sound effects are enabled by the user, and
20309      * {@link #isSoundEffectsEnabled()} is true.
20310      *
20311      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20312      */
playSoundEffect(int soundConstant)20313     public void playSoundEffect(int soundConstant) {
20314         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20315             return;
20316         }
20317         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20318     }
20319 
20320     /**
20321      * BZZZTT!!1!
20322      *
20323      * <p>Provide haptic feedback to the user for this view.
20324      *
20325      * <p>The framework will provide haptic feedback for some built in actions,
20326      * such as long presses, but you may wish to provide feedback for your
20327      * own widget.
20328      *
20329      * <p>The feedback will only be performed if
20330      * {@link #isHapticFeedbackEnabled()} is true.
20331      *
20332      * @param feedbackConstant One of the constants defined in
20333      * {@link HapticFeedbackConstants}
20334      */
performHapticFeedback(int feedbackConstant)20335     public boolean performHapticFeedback(int feedbackConstant) {
20336         return performHapticFeedback(feedbackConstant, 0);
20337     }
20338 
20339     /**
20340      * BZZZTT!!1!
20341      *
20342      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20343      *
20344      * @param feedbackConstant One of the constants defined in
20345      * {@link HapticFeedbackConstants}
20346      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20347      */
performHapticFeedback(int feedbackConstant, int flags)20348     public boolean performHapticFeedback(int feedbackConstant, int flags) {
20349         if (mAttachInfo == null) {
20350             return false;
20351         }
20352         //noinspection SimplifiableIfStatement
20353         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20354                 && !isHapticFeedbackEnabled()) {
20355             return false;
20356         }
20357         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20358                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20359     }
20360 
20361     /**
20362      * Request that the visibility of the status bar or other screen/window
20363      * decorations be changed.
20364      *
20365      * <p>This method is used to put the over device UI into temporary modes
20366      * where the user's attention is focused more on the application content,
20367      * by dimming or hiding surrounding system affordances.  This is typically
20368      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20369      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20370      * to be placed behind the action bar (and with these flags other system
20371      * affordances) so that smooth transitions between hiding and showing them
20372      * can be done.
20373      *
20374      * <p>Two representative examples of the use of system UI visibility is
20375      * implementing a content browsing application (like a magazine reader)
20376      * and a video playing application.
20377      *
20378      * <p>The first code shows a typical implementation of a View in a content
20379      * browsing application.  In this implementation, the application goes
20380      * into a content-oriented mode by hiding the status bar and action bar,
20381      * and putting the navigation elements into lights out mode.  The user can
20382      * then interact with content while in this mode.  Such an application should
20383      * provide an easy way for the user to toggle out of the mode (such as to
20384      * check information in the status bar or access notifications).  In the
20385      * implementation here, this is done simply by tapping on the content.
20386      *
20387      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20388      *      content}
20389      *
20390      * <p>This second code sample shows a typical implementation of a View
20391      * in a video playing application.  In this situation, while the video is
20392      * playing the application would like to go into a complete full-screen mode,
20393      * to use as much of the display as possible for the video.  When in this state
20394      * the user can not interact with the application; the system intercepts
20395      * touching on the screen to pop the UI out of full screen mode.  See
20396      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20397      *
20398      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20399      *      content}
20400      *
20401      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20402      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20403      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20404      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20405      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20406      */
setSystemUiVisibility(int visibility)20407     public void setSystemUiVisibility(int visibility) {
20408         if (visibility != mSystemUiVisibility) {
20409             mSystemUiVisibility = visibility;
20410             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20411                 mParent.recomputeViewAttributes(this);
20412             }
20413         }
20414     }
20415 
20416     /**
20417      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20418      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20419      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20420      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20421      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20422      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20423      */
getSystemUiVisibility()20424     public int getSystemUiVisibility() {
20425         return mSystemUiVisibility;
20426     }
20427 
20428     /**
20429      * Returns the current system UI visibility that is currently set for
20430      * the entire window.  This is the combination of the
20431      * {@link #setSystemUiVisibility(int)} values supplied by all of the
20432      * views in the window.
20433      */
getWindowSystemUiVisibility()20434     public int getWindowSystemUiVisibility() {
20435         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20436     }
20437 
20438     /**
20439      * Override to find out when the window's requested system UI visibility
20440      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20441      * This is different from the callbacks received through
20442      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20443      * in that this is only telling you about the local request of the window,
20444      * not the actual values applied by the system.
20445      */
onWindowSystemUiVisibilityChanged(int visible)20446     public void onWindowSystemUiVisibilityChanged(int visible) {
20447     }
20448 
20449     /**
20450      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20451      * the view hierarchy.
20452      */
dispatchWindowSystemUiVisiblityChanged(int visible)20453     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20454         onWindowSystemUiVisibilityChanged(visible);
20455     }
20456 
20457     /**
20458      * Set a listener to receive callbacks when the visibility of the system bar changes.
20459      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20460      */
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)20461     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20462         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20463         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20464             mParent.recomputeViewAttributes(this);
20465         }
20466     }
20467 
20468     /**
20469      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20470      * the view hierarchy.
20471      */
dispatchSystemUiVisibilityChanged(int visibility)20472     public void dispatchSystemUiVisibilityChanged(int visibility) {
20473         ListenerInfo li = mListenerInfo;
20474         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20475             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20476                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20477         }
20478     }
20479 
updateLocalSystemUiVisibility(int localValue, int localChanges)20480     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20481         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20482         if (val != mSystemUiVisibility) {
20483             setSystemUiVisibility(val);
20484             return true;
20485         }
20486         return false;
20487     }
20488 
20489     /** @hide */
setDisabledSystemUiVisibility(int flags)20490     public void setDisabledSystemUiVisibility(int flags) {
20491         if (mAttachInfo != null) {
20492             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20493                 mAttachInfo.mDisabledSystemUiVisibility = flags;
20494                 if (mParent != null) {
20495                     mParent.recomputeViewAttributes(this);
20496                 }
20497             }
20498         }
20499     }
20500 
20501     /**
20502      * Creates an image that the system displays during the drag and drop
20503      * operation. This is called a &quot;drag shadow&quot;. The default implementation
20504      * for a DragShadowBuilder based on a View returns an image that has exactly the same
20505      * appearance as the given View. The default also positions the center of the drag shadow
20506      * directly under the touch point. If no View is provided (the constructor with no parameters
20507      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20508      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20509      * default is an invisible drag shadow.
20510      * <p>
20511      * You are not required to use the View you provide to the constructor as the basis of the
20512      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20513      * anything you want as the drag shadow.
20514      * </p>
20515      * <p>
20516      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20517      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20518      *  size and position of the drag shadow. It uses this data to construct a
20519      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20520      *  so that your application can draw the shadow image in the Canvas.
20521      * </p>
20522      *
20523      * <div class="special reference">
20524      * <h3>Developer Guides</h3>
20525      * <p>For a guide to implementing drag and drop features, read the
20526      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20527      * </div>
20528      */
20529     public static class DragShadowBuilder {
20530         private final WeakReference<View> mView;
20531 
20532         /**
20533          * Constructs a shadow image builder based on a View. By default, the resulting drag
20534          * shadow will have the same appearance and dimensions as the View, with the touch point
20535          * over the center of the View.
20536          * @param view A View. Any View in scope can be used.
20537          */
DragShadowBuilder(View view)20538         public DragShadowBuilder(View view) {
20539             mView = new WeakReference<View>(view);
20540         }
20541 
20542         /**
20543          * Construct a shadow builder object with no associated View.  This
20544          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20545          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20546          * to supply the drag shadow's dimensions and appearance without
20547          * reference to any View object. If they are not overridden, then the result is an
20548          * invisible drag shadow.
20549          */
DragShadowBuilder()20550         public DragShadowBuilder() {
20551             mView = new WeakReference<View>(null);
20552         }
20553 
20554         /**
20555          * Returns the View object that had been passed to the
20556          * {@link #View.DragShadowBuilder(View)}
20557          * constructor.  If that View parameter was {@code null} or if the
20558          * {@link #View.DragShadowBuilder()}
20559          * constructor was used to instantiate the builder object, this method will return
20560          * null.
20561          *
20562          * @return The View object associate with this builder object.
20563          */
20564         @SuppressWarnings({"JavadocReference"})
getView()20565         final public View getView() {
20566             return mView.get();
20567         }
20568 
20569         /**
20570          * Provides the metrics for the shadow image. These include the dimensions of
20571          * the shadow image, and the point within that shadow that should
20572          * be centered under the touch location while dragging.
20573          * <p>
20574          * The default implementation sets the dimensions of the shadow to be the
20575          * same as the dimensions of the View itself and centers the shadow under
20576          * the touch point.
20577          * </p>
20578          *
20579          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20580          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20581          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20582          * image.
20583          *
20584          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20585          * shadow image that should be underneath the touch point during the drag and drop
20586          * operation. Your application must set {@link android.graphics.Point#x} to the
20587          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20588          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)20589         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20590             final View view = mView.get();
20591             if (view != null) {
20592                 outShadowSize.set(view.getWidth(), view.getHeight());
20593                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20594             } else {
20595                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20596             }
20597         }
20598 
20599         /**
20600          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20601          * based on the dimensions it received from the
20602          * {@link #onProvideShadowMetrics(Point, Point)} callback.
20603          *
20604          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20605          */
onDrawShadow(Canvas canvas)20606         public void onDrawShadow(Canvas canvas) {
20607             final View view = mView.get();
20608             if (view != null) {
20609                 view.draw(canvas);
20610             } else {
20611                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20612             }
20613         }
20614     }
20615 
20616     /**
20617      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20618      * startDragAndDrop()} for newer platform versions.
20619      */
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20620     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20621                                    Object myLocalState, int flags) {
20622         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20623     }
20624 
20625     /**
20626      * Starts a drag and drop operation. When your application calls this method, it passes a
20627      * {@link android.view.View.DragShadowBuilder} object to the system. The
20628      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20629      * to get metrics for the drag shadow, and then calls the object's
20630      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20631      * <p>
20632      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
20633      *  drag events to all the View objects in your application that are currently visible. It does
20634      *  this either by calling the View object's drag listener (an implementation of
20635      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20636      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20637      *  Both are passed a {@link android.view.DragEvent} object that has a
20638      *  {@link android.view.DragEvent#getAction()} value of
20639      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20640      * </p>
20641      * <p>
20642      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20643      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20644      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20645      * to the View the user selected for dragging.
20646      * </p>
20647      * @param data A {@link android.content.ClipData} object pointing to the data to be
20648      * transferred by the drag and drop operation.
20649      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20650      * drag shadow.
20651      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20652      * drop operation. This Object is put into every DragEvent object sent by the system during the
20653      * current drag.
20654      * <p>
20655      * myLocalState is a lightweight mechanism for the sending information from the dragged View
20656      * to the target Views. For example, it can contain flags that differentiate between a
20657      * a copy operation and a move operation.
20658      * </p>
20659      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20660      * flags, or any combination of the following:
20661      *     <ul>
20662      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
20663      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20664      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20665      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20666      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20667      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
20668      *     </ul>
20669      * @return {@code true} if the method completes successfully, or
20670      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20671      * do a drag, and so no drag operation is in progress.
20672      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20673     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20674             Object myLocalState, int flags) {
20675         if (ViewDebug.DEBUG_DRAG) {
20676             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20677         }
20678         if (mAttachInfo == null) {
20679             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20680             return false;
20681         }
20682         boolean okay = false;
20683 
20684         Point shadowSize = new Point();
20685         Point shadowTouchPoint = new Point();
20686         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20687 
20688         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20689                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20690             throw new IllegalStateException("Drag shadow dimensions must not be negative");
20691         }
20692 
20693         if (ViewDebug.DEBUG_DRAG) {
20694             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20695                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20696         }
20697         if (mAttachInfo.mDragSurface != null) {
20698             mAttachInfo.mDragSurface.release();
20699         }
20700         mAttachInfo.mDragSurface = new Surface();
20701         try {
20702             mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20703                     flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20704             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20705                     + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20706             if (mAttachInfo.mDragToken != null) {
20707                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20708                 try {
20709                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20710                     shadowBuilder.onDrawShadow(canvas);
20711                 } finally {
20712                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20713                 }
20714 
20715                 final ViewRootImpl root = getViewRootImpl();
20716 
20717                 // Cache the local state object for delivery with DragEvents
20718                 root.setLocalDragState(myLocalState);
20719 
20720                 // repurpose 'shadowSize' for the last touch point
20721                 root.getLastTouchPoint(shadowSize);
20722 
20723                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20724                         root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20725                         shadowTouchPoint.x, shadowTouchPoint.y, data);
20726                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20727             }
20728         } catch (Exception e) {
20729             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20730             mAttachInfo.mDragSurface.destroy();
20731             mAttachInfo.mDragSurface = null;
20732         }
20733 
20734         return okay;
20735     }
20736 
20737     /**
20738      * Cancels an ongoing drag and drop operation.
20739      * <p>
20740      * A {@link android.view.DragEvent} object with
20741      * {@link android.view.DragEvent#getAction()} value of
20742      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20743      * {@link android.view.DragEvent#getResult()} value of {@code false}
20744      * will be sent to every
20745      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20746      * even if they are not currently visible.
20747      * </p>
20748      * <p>
20749      * This method can be called on any View in the same window as the View on which
20750      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20751      * was called.
20752      * </p>
20753      */
cancelDragAndDrop()20754     public final void cancelDragAndDrop() {
20755         if (ViewDebug.DEBUG_DRAG) {
20756             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20757         }
20758         if (mAttachInfo == null) {
20759             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20760             return;
20761         }
20762         if (mAttachInfo.mDragToken != null) {
20763             try {
20764                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20765             } catch (Exception e) {
20766                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20767             }
20768             mAttachInfo.mDragToken = null;
20769         } else {
20770             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20771         }
20772     }
20773 
20774     /**
20775      * Updates the drag shadow for the ongoing drag and drop operation.
20776      *
20777      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20778      * new drag shadow.
20779      */
updateDragShadow(DragShadowBuilder shadowBuilder)20780     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20781         if (ViewDebug.DEBUG_DRAG) {
20782             Log.d(VIEW_LOG_TAG, "updateDragShadow");
20783         }
20784         if (mAttachInfo == null) {
20785             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20786             return;
20787         }
20788         if (mAttachInfo.mDragToken != null) {
20789             try {
20790                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20791                 try {
20792                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20793                     shadowBuilder.onDrawShadow(canvas);
20794                 } finally {
20795                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20796                 }
20797             } catch (Exception e) {
20798                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20799             }
20800         } else {
20801             Log.e(VIEW_LOG_TAG, "No active drag");
20802         }
20803     }
20804 
20805     /**
20806      * Starts a move from {startX, startY}, the amount of the movement will be the offset
20807      * between {startX, startY} and the new cursor positon.
20808      * @param startX horizontal coordinate where the move started.
20809      * @param startY vertical coordinate where the move started.
20810      * @return whether moving was started successfully.
20811      * @hide
20812      */
startMovingTask(float startX, float startY)20813     public final boolean startMovingTask(float startX, float startY) {
20814         if (ViewDebug.DEBUG_POSITIONING) {
20815             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20816         }
20817         try {
20818             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20819         } catch (RemoteException e) {
20820             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20821         }
20822         return false;
20823     }
20824 
20825     /**
20826      * Handles drag events sent by the system following a call to
20827      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20828      * startDragAndDrop()}.
20829      *<p>
20830      * When the system calls this method, it passes a
20831      * {@link android.view.DragEvent} object. A call to
20832      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20833      * in DragEvent. The method uses these to determine what is happening in the drag and drop
20834      * operation.
20835      * @param event The {@link android.view.DragEvent} sent by the system.
20836      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20837      * in DragEvent, indicating the type of drag event represented by this object.
20838      * @return {@code true} if the method was successful, otherwise {@code false}.
20839      * <p>
20840      *  The method should return {@code true} in response to an action type of
20841      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20842      *  operation.
20843      * </p>
20844      * <p>
20845      *  The method should also return {@code true} in response to an action type of
20846      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20847      *  {@code false} if it didn't.
20848      * </p>
20849      */
onDragEvent(DragEvent event)20850     public boolean onDragEvent(DragEvent event) {
20851         return false;
20852     }
20853 
20854     /**
20855      * Detects if this View is enabled and has a drag event listener.
20856      * If both are true, then it calls the drag event listener with the
20857      * {@link android.view.DragEvent} it received. If the drag event listener returns
20858      * {@code true}, then dispatchDragEvent() returns {@code true}.
20859      * <p>
20860      * For all other cases, the method calls the
20861      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20862      * method and returns its result.
20863      * </p>
20864      * <p>
20865      * This ensures that a drag event is always consumed, even if the View does not have a drag
20866      * event listener. However, if the View has a listener and the listener returns true, then
20867      * onDragEvent() is not called.
20868      * </p>
20869      */
dispatchDragEvent(DragEvent event)20870     public boolean dispatchDragEvent(DragEvent event) {
20871         ListenerInfo li = mListenerInfo;
20872         //noinspection SimplifiableIfStatement
20873         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20874                 && li.mOnDragListener.onDrag(this, event)) {
20875             return true;
20876         }
20877         return onDragEvent(event);
20878     }
20879 
canAcceptDrag()20880     boolean canAcceptDrag() {
20881         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20882     }
20883 
20884     /**
20885      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20886      * it is ever exposed at all.
20887      * @hide
20888      */
onCloseSystemDialogs(String reason)20889     public void onCloseSystemDialogs(String reason) {
20890     }
20891 
20892     /**
20893      * Given a Drawable whose bounds have been set to draw into this view,
20894      * update a Region being computed for
20895      * {@link #gatherTransparentRegion(android.graphics.Region)} so
20896      * that any non-transparent parts of the Drawable are removed from the
20897      * given transparent region.
20898      *
20899      * @param dr The Drawable whose transparency is to be applied to the region.
20900      * @param region A Region holding the current transparency information,
20901      * where any parts of the region that are set are considered to be
20902      * transparent.  On return, this region will be modified to have the
20903      * transparency information reduced by the corresponding parts of the
20904      * Drawable that are not transparent.
20905      * {@hide}
20906      */
applyDrawableToTransparentRegion(Drawable dr, Region region)20907     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20908         if (DBG) {
20909             Log.i("View", "Getting transparent region for: " + this);
20910         }
20911         final Region r = dr.getTransparentRegion();
20912         final Rect db = dr.getBounds();
20913         final AttachInfo attachInfo = mAttachInfo;
20914         if (r != null && attachInfo != null) {
20915             final int w = getRight()-getLeft();
20916             final int h = getBottom()-getTop();
20917             if (db.left > 0) {
20918                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20919                 r.op(0, 0, db.left, h, Region.Op.UNION);
20920             }
20921             if (db.right < w) {
20922                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20923                 r.op(db.right, 0, w, h, Region.Op.UNION);
20924             }
20925             if (db.top > 0) {
20926                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20927                 r.op(0, 0, w, db.top, Region.Op.UNION);
20928             }
20929             if (db.bottom < h) {
20930                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20931                 r.op(0, db.bottom, w, h, Region.Op.UNION);
20932             }
20933             final int[] location = attachInfo.mTransparentLocation;
20934             getLocationInWindow(location);
20935             r.translate(location[0], location[1]);
20936             region.op(r, Region.Op.INTERSECT);
20937         } else {
20938             region.op(db, Region.Op.DIFFERENCE);
20939         }
20940     }
20941 
checkForLongClick(int delayOffset, float x, float y)20942     private void checkForLongClick(int delayOffset, float x, float y) {
20943         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20944             mHasPerformedLongPress = false;
20945 
20946             if (mPendingCheckForLongPress == null) {
20947                 mPendingCheckForLongPress = new CheckForLongPress();
20948             }
20949             mPendingCheckForLongPress.setAnchor(x, y);
20950             mPendingCheckForLongPress.rememberWindowAttachCount();
20951             postDelayed(mPendingCheckForLongPress,
20952                     ViewConfiguration.getLongPressTimeout() - delayOffset);
20953         }
20954     }
20955 
20956     /**
20957      * Inflate a view from an XML resource.  This convenience method wraps the {@link
20958      * LayoutInflater} class, which provides a full range of options for view inflation.
20959      *
20960      * @param context The Context object for your activity or application.
20961      * @param resource The resource ID to inflate
20962      * @param root A view group that will be the parent.  Used to properly inflate the
20963      * layout_* parameters.
20964      * @see LayoutInflater
20965      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)20966     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20967         LayoutInflater factory = LayoutInflater.from(context);
20968         return factory.inflate(resource, root);
20969     }
20970 
20971     /**
20972      * Scroll the view with standard behavior for scrolling beyond the normal
20973      * content boundaries. Views that call this method should override
20974      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20975      * results of an over-scroll operation.
20976      *
20977      * Views can use this method to handle any touch or fling-based scrolling.
20978      *
20979      * @param deltaX Change in X in pixels
20980      * @param deltaY Change in Y in pixels
20981      * @param scrollX Current X scroll value in pixels before applying deltaX
20982      * @param scrollY Current Y scroll value in pixels before applying deltaY
20983      * @param scrollRangeX Maximum content scroll range along the X axis
20984      * @param scrollRangeY Maximum content scroll range along the Y axis
20985      * @param maxOverScrollX Number of pixels to overscroll by in either direction
20986      *          along the X axis.
20987      * @param maxOverScrollY Number of pixels to overscroll by in either direction
20988      *          along the Y axis.
20989      * @param isTouchEvent true if this scroll operation is the result of a touch event.
20990      * @return true if scrolling was clamped to an over-scroll boundary along either
20991      *          axis, false otherwise.
20992      */
20993     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)20994     protected boolean overScrollBy(int deltaX, int deltaY,
20995             int scrollX, int scrollY,
20996             int scrollRangeX, int scrollRangeY,
20997             int maxOverScrollX, int maxOverScrollY,
20998             boolean isTouchEvent) {
20999         final int overScrollMode = mOverScrollMode;
21000         final boolean canScrollHorizontal =
21001                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21002         final boolean canScrollVertical =
21003                 computeVerticalScrollRange() > computeVerticalScrollExtent();
21004         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21005                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21006         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21007                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21008 
21009         int newScrollX = scrollX + deltaX;
21010         if (!overScrollHorizontal) {
21011             maxOverScrollX = 0;
21012         }
21013 
21014         int newScrollY = scrollY + deltaY;
21015         if (!overScrollVertical) {
21016             maxOverScrollY = 0;
21017         }
21018 
21019         // Clamp values if at the limits and record
21020         final int left = -maxOverScrollX;
21021         final int right = maxOverScrollX + scrollRangeX;
21022         final int top = -maxOverScrollY;
21023         final int bottom = maxOverScrollY + scrollRangeY;
21024 
21025         boolean clampedX = false;
21026         if (newScrollX > right) {
21027             newScrollX = right;
21028             clampedX = true;
21029         } else if (newScrollX < left) {
21030             newScrollX = left;
21031             clampedX = true;
21032         }
21033 
21034         boolean clampedY = false;
21035         if (newScrollY > bottom) {
21036             newScrollY = bottom;
21037             clampedY = true;
21038         } else if (newScrollY < top) {
21039             newScrollY = top;
21040             clampedY = true;
21041         }
21042 
21043         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21044 
21045         return clampedX || clampedY;
21046     }
21047 
21048     /**
21049      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21050      * respond to the results of an over-scroll operation.
21051      *
21052      * @param scrollX New X scroll value in pixels
21053      * @param scrollY New Y scroll value in pixels
21054      * @param clampedX True if scrollX was clamped to an over-scroll boundary
21055      * @param clampedY True if scrollY was clamped to an over-scroll boundary
21056      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)21057     protected void onOverScrolled(int scrollX, int scrollY,
21058             boolean clampedX, boolean clampedY) {
21059         // Intentionally empty.
21060     }
21061 
21062     /**
21063      * Returns the over-scroll mode for this view. The result will be
21064      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21065      * (allow over-scrolling only if the view content is larger than the container),
21066      * or {@link #OVER_SCROLL_NEVER}.
21067      *
21068      * @return This view's over-scroll mode.
21069      */
getOverScrollMode()21070     public int getOverScrollMode() {
21071         return mOverScrollMode;
21072     }
21073 
21074     /**
21075      * Set the over-scroll mode for this view. Valid over-scroll modes are
21076      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21077      * (allow over-scrolling only if the view content is larger than the container),
21078      * or {@link #OVER_SCROLL_NEVER}.
21079      *
21080      * Setting the over-scroll mode of a view will have an effect only if the
21081      * view is capable of scrolling.
21082      *
21083      * @param overScrollMode The new over-scroll mode for this view.
21084      */
setOverScrollMode(int overScrollMode)21085     public void setOverScrollMode(int overScrollMode) {
21086         if (overScrollMode != OVER_SCROLL_ALWAYS &&
21087                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21088                 overScrollMode != OVER_SCROLL_NEVER) {
21089             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21090         }
21091         mOverScrollMode = overScrollMode;
21092     }
21093 
21094     /**
21095      * Enable or disable nested scrolling for this view.
21096      *
21097      * <p>If this property is set to true the view will be permitted to initiate nested
21098      * scrolling operations with a compatible parent view in the current hierarchy. If this
21099      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21100      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21101      * the nested scroll.</p>
21102      *
21103      * @param enabled true to enable nested scrolling, false to disable
21104      *
21105      * @see #isNestedScrollingEnabled()
21106      */
setNestedScrollingEnabled(boolean enabled)21107     public void setNestedScrollingEnabled(boolean enabled) {
21108         if (enabled) {
21109             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21110         } else {
21111             stopNestedScroll();
21112             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21113         }
21114     }
21115 
21116     /**
21117      * Returns true if nested scrolling is enabled for this view.
21118      *
21119      * <p>If nested scrolling is enabled and this View class implementation supports it,
21120      * this view will act as a nested scrolling child view when applicable, forwarding data
21121      * about the scroll operation in progress to a compatible and cooperating nested scrolling
21122      * parent.</p>
21123      *
21124      * @return true if nested scrolling is enabled
21125      *
21126      * @see #setNestedScrollingEnabled(boolean)
21127      */
isNestedScrollingEnabled()21128     public boolean isNestedScrollingEnabled() {
21129         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21130                 PFLAG3_NESTED_SCROLLING_ENABLED;
21131     }
21132 
21133     /**
21134      * Begin a nestable scroll operation along the given axes.
21135      *
21136      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21137      *
21138      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21139      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21140      * In the case of touch scrolling the nested scroll will be terminated automatically in
21141      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21142      * In the event of programmatic scrolling the caller must explicitly call
21143      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21144      *
21145      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21146      * If it returns false the caller may ignore the rest of this contract until the next scroll.
21147      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21148      *
21149      * <p>At each incremental step of the scroll the caller should invoke
21150      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21151      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21152      * parent at least partially consumed the scroll and the caller should adjust the amount it
21153      * scrolls by.</p>
21154      *
21155      * <p>After applying the remainder of the scroll delta the caller should invoke
21156      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21157      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21158      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21159      * </p>
21160      *
21161      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21162      *             {@link #SCROLL_AXIS_VERTICAL}.
21163      * @return true if a cooperative parent was found and nested scrolling has been enabled for
21164      *         the current gesture.
21165      *
21166      * @see #stopNestedScroll()
21167      * @see #dispatchNestedPreScroll(int, int, int[], int[])
21168      * @see #dispatchNestedScroll(int, int, int, int, int[])
21169      */
startNestedScroll(int axes)21170     public boolean startNestedScroll(int axes) {
21171         if (hasNestedScrollingParent()) {
21172             // Already in progress
21173             return true;
21174         }
21175         if (isNestedScrollingEnabled()) {
21176             ViewParent p = getParent();
21177             View child = this;
21178             while (p != null) {
21179                 try {
21180                     if (p.onStartNestedScroll(child, this, axes)) {
21181                         mNestedScrollingParent = p;
21182                         p.onNestedScrollAccepted(child, this, axes);
21183                         return true;
21184                     }
21185                 } catch (AbstractMethodError e) {
21186                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21187                             "method onStartNestedScroll", e);
21188                     // Allow the search upward to continue
21189                 }
21190                 if (p instanceof View) {
21191                     child = (View) p;
21192                 }
21193                 p = p.getParent();
21194             }
21195         }
21196         return false;
21197     }
21198 
21199     /**
21200      * Stop a nested scroll in progress.
21201      *
21202      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21203      *
21204      * @see #startNestedScroll(int)
21205      */
stopNestedScroll()21206     public void stopNestedScroll() {
21207         if (mNestedScrollingParent != null) {
21208             mNestedScrollingParent.onStopNestedScroll(this);
21209             mNestedScrollingParent = null;
21210         }
21211     }
21212 
21213     /**
21214      * Returns true if this view has a nested scrolling parent.
21215      *
21216      * <p>The presence of a nested scrolling parent indicates that this view has initiated
21217      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21218      *
21219      * @return whether this view has a nested scrolling parent
21220      */
hasNestedScrollingParent()21221     public boolean hasNestedScrollingParent() {
21222         return mNestedScrollingParent != null;
21223     }
21224 
21225     /**
21226      * Dispatch one step of a nested scroll in progress.
21227      *
21228      * <p>Implementations of views that support nested scrolling should call this to report
21229      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21230      * is not currently in progress or nested scrolling is not
21231      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21232      *
21233      * <p>Compatible View implementations should also call
21234      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21235      * consuming a component of the scroll event themselves.</p>
21236      *
21237      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21238      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21239      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21240      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21241      * @param offsetInWindow Optional. If not null, on return this will contain the offset
21242      *                       in local view coordinates of this view from before this operation
21243      *                       to after it completes. View implementations may use this to adjust
21244      *                       expected input coordinate tracking.
21245      * @return true if the event was dispatched, false if it could not be dispatched.
21246      * @see #dispatchNestedPreScroll(int, int, int[], int[])
21247      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)21248     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21249             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21250         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21251             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21252                 int startX = 0;
21253                 int startY = 0;
21254                 if (offsetInWindow != null) {
21255                     getLocationInWindow(offsetInWindow);
21256                     startX = offsetInWindow[0];
21257                     startY = offsetInWindow[1];
21258                 }
21259 
21260                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21261                         dxUnconsumed, dyUnconsumed);
21262 
21263                 if (offsetInWindow != null) {
21264                     getLocationInWindow(offsetInWindow);
21265                     offsetInWindow[0] -= startX;
21266                     offsetInWindow[1] -= startY;
21267                 }
21268                 return true;
21269             } else if (offsetInWindow != null) {
21270                 // No motion, no dispatch. Keep offsetInWindow up to date.
21271                 offsetInWindow[0] = 0;
21272                 offsetInWindow[1] = 0;
21273             }
21274         }
21275         return false;
21276     }
21277 
21278     /**
21279      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21280      *
21281      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21282      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21283      * scrolling operation to consume some or all of the scroll operation before the child view
21284      * consumes it.</p>
21285      *
21286      * @param dx Horizontal scroll distance in pixels
21287      * @param dy Vertical scroll distance in pixels
21288      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21289      *                 and consumed[1] the consumed dy.
21290      * @param offsetInWindow Optional. If not null, on return this will contain the offset
21291      *                       in local view coordinates of this view from before this operation
21292      *                       to after it completes. View implementations may use this to adjust
21293      *                       expected input coordinate tracking.
21294      * @return true if the parent consumed some or all of the scroll delta
21295      * @see #dispatchNestedScroll(int, int, int, int, int[])
21296      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)21297     public boolean dispatchNestedPreScroll(int dx, int dy,
21298             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21299         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21300             if (dx != 0 || dy != 0) {
21301                 int startX = 0;
21302                 int startY = 0;
21303                 if (offsetInWindow != null) {
21304                     getLocationInWindow(offsetInWindow);
21305                     startX = offsetInWindow[0];
21306                     startY = offsetInWindow[1];
21307                 }
21308 
21309                 if (consumed == null) {
21310                     if (mTempNestedScrollConsumed == null) {
21311                         mTempNestedScrollConsumed = new int[2];
21312                     }
21313                     consumed = mTempNestedScrollConsumed;
21314                 }
21315                 consumed[0] = 0;
21316                 consumed[1] = 0;
21317                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21318 
21319                 if (offsetInWindow != null) {
21320                     getLocationInWindow(offsetInWindow);
21321                     offsetInWindow[0] -= startX;
21322                     offsetInWindow[1] -= startY;
21323                 }
21324                 return consumed[0] != 0 || consumed[1] != 0;
21325             } else if (offsetInWindow != null) {
21326                 offsetInWindow[0] = 0;
21327                 offsetInWindow[1] = 0;
21328             }
21329         }
21330         return false;
21331     }
21332 
21333     /**
21334      * Dispatch a fling to a nested scrolling parent.
21335      *
21336      * <p>This method should be used to indicate that a nested scrolling child has detected
21337      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21338      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21339      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21340      * along a scrollable axis.</p>
21341      *
21342      * <p>If a nested scrolling child view would normally fling but it is at the edge of
21343      * its own content, it can use this method to delegate the fling to its nested scrolling
21344      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21345      *
21346      * @param velocityX Horizontal fling velocity in pixels per second
21347      * @param velocityY Vertical fling velocity in pixels per second
21348      * @param consumed true if the child consumed the fling, false otherwise
21349      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21350      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)21351     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21352         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21353             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21354         }
21355         return false;
21356     }
21357 
21358     /**
21359      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21360      *
21361      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21362      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21363      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21364      * before the child view consumes it. If this method returns <code>true</code>, a nested
21365      * parent view consumed the fling and this view should not scroll as a result.</p>
21366      *
21367      * <p>For a better user experience, only one view in a nested scrolling chain should consume
21368      * the fling at a time. If a parent view consumed the fling this method will return false.
21369      * Custom view implementations should account for this in two ways:</p>
21370      *
21371      * <ul>
21372      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21373      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21374      *     position regardless.</li>
21375      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21376      *     even to settle back to a valid idle position.</li>
21377      * </ul>
21378      *
21379      * <p>Views should also not offer fling velocities to nested parent views along an axis
21380      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21381      * should not offer a horizontal fling velocity to its parents since scrolling along that
21382      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21383      *
21384      * @param velocityX Horizontal fling velocity in pixels per second
21385      * @param velocityY Vertical fling velocity in pixels per second
21386      * @return true if a nested scrolling parent consumed the fling
21387      */
dispatchNestedPreFling(float velocityX, float velocityY)21388     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21389         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21390             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21391         }
21392         return false;
21393     }
21394 
21395     /**
21396      * Gets a scale factor that determines the distance the view should scroll
21397      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21398      * @return The vertical scroll scale factor.
21399      * @hide
21400      */
getVerticalScrollFactor()21401     protected float getVerticalScrollFactor() {
21402         if (mVerticalScrollFactor == 0) {
21403             TypedValue outValue = new TypedValue();
21404             if (!mContext.getTheme().resolveAttribute(
21405                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21406                 throw new IllegalStateException(
21407                         "Expected theme to define listPreferredItemHeight.");
21408             }
21409             mVerticalScrollFactor = outValue.getDimension(
21410                     mContext.getResources().getDisplayMetrics());
21411         }
21412         return mVerticalScrollFactor;
21413     }
21414 
21415     /**
21416      * Gets a scale factor that determines the distance the view should scroll
21417      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21418      * @return The horizontal scroll scale factor.
21419      * @hide
21420      */
getHorizontalScrollFactor()21421     protected float getHorizontalScrollFactor() {
21422         // TODO: Should use something else.
21423         return getVerticalScrollFactor();
21424     }
21425 
21426     /**
21427      * Return the value specifying the text direction or policy that was set with
21428      * {@link #setTextDirection(int)}.
21429      *
21430      * @return the defined text direction. It can be one of:
21431      *
21432      * {@link #TEXT_DIRECTION_INHERIT},
21433      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21434      * {@link #TEXT_DIRECTION_ANY_RTL},
21435      * {@link #TEXT_DIRECTION_LTR},
21436      * {@link #TEXT_DIRECTION_RTL},
21437      * {@link #TEXT_DIRECTION_LOCALE},
21438      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21439      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21440      *
21441      * @attr ref android.R.styleable#View_textDirection
21442      *
21443      * @hide
21444      */
21445     @ViewDebug.ExportedProperty(category = "text", mapping = {
21446             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21447             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21448             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21449             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21450             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21451             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21452             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21453             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21454     })
getRawTextDirection()21455     public int getRawTextDirection() {
21456         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21457     }
21458 
21459     /**
21460      * Set the text direction.
21461      *
21462      * @param textDirection the direction to set. Should be one of:
21463      *
21464      * {@link #TEXT_DIRECTION_INHERIT},
21465      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21466      * {@link #TEXT_DIRECTION_ANY_RTL},
21467      * {@link #TEXT_DIRECTION_LTR},
21468      * {@link #TEXT_DIRECTION_RTL},
21469      * {@link #TEXT_DIRECTION_LOCALE}
21470      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21471      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21472      *
21473      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21474      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21475      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21476      *
21477      * @attr ref android.R.styleable#View_textDirection
21478      */
setTextDirection(int textDirection)21479     public void setTextDirection(int textDirection) {
21480         if (getRawTextDirection() != textDirection) {
21481             // Reset the current text direction and the resolved one
21482             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21483             resetResolvedTextDirection();
21484             // Set the new text direction
21485             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21486             // Do resolution
21487             resolveTextDirection();
21488             // Notify change
21489             onRtlPropertiesChanged(getLayoutDirection());
21490             // Refresh
21491             requestLayout();
21492             invalidate(true);
21493         }
21494     }
21495 
21496     /**
21497      * Return the resolved text direction.
21498      *
21499      * @return the resolved text direction. Returns one of:
21500      *
21501      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21502      * {@link #TEXT_DIRECTION_ANY_RTL},
21503      * {@link #TEXT_DIRECTION_LTR},
21504      * {@link #TEXT_DIRECTION_RTL},
21505      * {@link #TEXT_DIRECTION_LOCALE},
21506      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21507      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21508      *
21509      * @attr ref android.R.styleable#View_textDirection
21510      */
21511     @ViewDebug.ExportedProperty(category = "text", mapping = {
21512             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21513             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21514             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21515             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21516             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21517             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21518             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21519             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21520     })
getTextDirection()21521     public int getTextDirection() {
21522         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21523     }
21524 
21525     /**
21526      * Resolve the text direction.
21527      *
21528      * @return true if resolution has been done, false otherwise.
21529      *
21530      * @hide
21531      */
resolveTextDirection()21532     public boolean resolveTextDirection() {
21533         // Reset any previous text direction resolution
21534         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21535 
21536         if (hasRtlSupport()) {
21537             // Set resolved text direction flag depending on text direction flag
21538             final int textDirection = getRawTextDirection();
21539             switch(textDirection) {
21540                 case TEXT_DIRECTION_INHERIT:
21541                     if (!canResolveTextDirection()) {
21542                         // We cannot do the resolution if there is no parent, so use the default one
21543                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21544                         // Resolution will need to happen again later
21545                         return false;
21546                     }
21547 
21548                     // Parent has not yet resolved, so we still return the default
21549                     try {
21550                         if (!mParent.isTextDirectionResolved()) {
21551                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21552                             // Resolution will need to happen again later
21553                             return false;
21554                         }
21555                     } catch (AbstractMethodError e) {
21556                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21557                                 " does not fully implement ViewParent", e);
21558                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21559                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21560                         return true;
21561                     }
21562 
21563                     // Set current resolved direction to the same value as the parent's one
21564                     int parentResolvedDirection;
21565                     try {
21566                         parentResolvedDirection = mParent.getTextDirection();
21567                     } catch (AbstractMethodError e) {
21568                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21569                                 " does not fully implement ViewParent", e);
21570                         parentResolvedDirection = TEXT_DIRECTION_LTR;
21571                     }
21572                     switch (parentResolvedDirection) {
21573                         case TEXT_DIRECTION_FIRST_STRONG:
21574                         case TEXT_DIRECTION_ANY_RTL:
21575                         case TEXT_DIRECTION_LTR:
21576                         case TEXT_DIRECTION_RTL:
21577                         case TEXT_DIRECTION_LOCALE:
21578                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
21579                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
21580                             mPrivateFlags2 |=
21581                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21582                             break;
21583                         default:
21584                             // Default resolved direction is "first strong" heuristic
21585                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21586                     }
21587                     break;
21588                 case TEXT_DIRECTION_FIRST_STRONG:
21589                 case TEXT_DIRECTION_ANY_RTL:
21590                 case TEXT_DIRECTION_LTR:
21591                 case TEXT_DIRECTION_RTL:
21592                 case TEXT_DIRECTION_LOCALE:
21593                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
21594                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
21595                     // Resolved direction is the same as text direction
21596                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21597                     break;
21598                 default:
21599                     // Default resolved direction is "first strong" heuristic
21600                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21601             }
21602         } else {
21603             // Default resolved direction is "first strong" heuristic
21604             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21605         }
21606 
21607         // Set to resolved
21608         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21609         return true;
21610     }
21611 
21612     /**
21613      * Check if text direction resolution can be done.
21614      *
21615      * @return true if text direction resolution can be done otherwise return false.
21616      */
canResolveTextDirection()21617     public boolean canResolveTextDirection() {
21618         switch (getRawTextDirection()) {
21619             case TEXT_DIRECTION_INHERIT:
21620                 if (mParent != null) {
21621                     try {
21622                         return mParent.canResolveTextDirection();
21623                     } catch (AbstractMethodError e) {
21624                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21625                                 " does not fully implement ViewParent", e);
21626                     }
21627                 }
21628                 return false;
21629 
21630             default:
21631                 return true;
21632         }
21633     }
21634 
21635     /**
21636      * Reset resolved text direction. Text direction will be resolved during a call to
21637      * {@link #onMeasure(int, int)}.
21638      *
21639      * @hide
21640      */
resetResolvedTextDirection()21641     public void resetResolvedTextDirection() {
21642         // Reset any previous text direction resolution
21643         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21644         // Set to default value
21645         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21646     }
21647 
21648     /**
21649      * @return true if text direction is inherited.
21650      *
21651      * @hide
21652      */
isTextDirectionInherited()21653     public boolean isTextDirectionInherited() {
21654         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21655     }
21656 
21657     /**
21658      * @return true if text direction is resolved.
21659      */
isTextDirectionResolved()21660     public boolean isTextDirectionResolved() {
21661         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21662     }
21663 
21664     /**
21665      * Return the value specifying the text alignment or policy that was set with
21666      * {@link #setTextAlignment(int)}.
21667      *
21668      * @return the defined text alignment. It can be one of:
21669      *
21670      * {@link #TEXT_ALIGNMENT_INHERIT},
21671      * {@link #TEXT_ALIGNMENT_GRAVITY},
21672      * {@link #TEXT_ALIGNMENT_CENTER},
21673      * {@link #TEXT_ALIGNMENT_TEXT_START},
21674      * {@link #TEXT_ALIGNMENT_TEXT_END},
21675      * {@link #TEXT_ALIGNMENT_VIEW_START},
21676      * {@link #TEXT_ALIGNMENT_VIEW_END}
21677      *
21678      * @attr ref android.R.styleable#View_textAlignment
21679      *
21680      * @hide
21681      */
21682     @ViewDebug.ExportedProperty(category = "text", mapping = {
21683             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21684             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21685             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21686             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21687             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21688             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21689             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21690     })
21691     @TextAlignment
getRawTextAlignment()21692     public int getRawTextAlignment() {
21693         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21694     }
21695 
21696     /**
21697      * Set the text alignment.
21698      *
21699      * @param textAlignment The text alignment to set. Should be one of
21700      *
21701      * {@link #TEXT_ALIGNMENT_INHERIT},
21702      * {@link #TEXT_ALIGNMENT_GRAVITY},
21703      * {@link #TEXT_ALIGNMENT_CENTER},
21704      * {@link #TEXT_ALIGNMENT_TEXT_START},
21705      * {@link #TEXT_ALIGNMENT_TEXT_END},
21706      * {@link #TEXT_ALIGNMENT_VIEW_START},
21707      * {@link #TEXT_ALIGNMENT_VIEW_END}
21708      *
21709      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21710      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21711      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21712      *
21713      * @attr ref android.R.styleable#View_textAlignment
21714      */
setTextAlignment(@extAlignment int textAlignment)21715     public void setTextAlignment(@TextAlignment int textAlignment) {
21716         if (textAlignment != getRawTextAlignment()) {
21717             // Reset the current and resolved text alignment
21718             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21719             resetResolvedTextAlignment();
21720             // Set the new text alignment
21721             mPrivateFlags2 |=
21722                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21723             // Do resolution
21724             resolveTextAlignment();
21725             // Notify change
21726             onRtlPropertiesChanged(getLayoutDirection());
21727             // Refresh
21728             requestLayout();
21729             invalidate(true);
21730         }
21731     }
21732 
21733     /**
21734      * Return the resolved text alignment.
21735      *
21736      * @return the resolved text alignment. Returns one of:
21737      *
21738      * {@link #TEXT_ALIGNMENT_GRAVITY},
21739      * {@link #TEXT_ALIGNMENT_CENTER},
21740      * {@link #TEXT_ALIGNMENT_TEXT_START},
21741      * {@link #TEXT_ALIGNMENT_TEXT_END},
21742      * {@link #TEXT_ALIGNMENT_VIEW_START},
21743      * {@link #TEXT_ALIGNMENT_VIEW_END}
21744      *
21745      * @attr ref android.R.styleable#View_textAlignment
21746      */
21747     @ViewDebug.ExportedProperty(category = "text", mapping = {
21748             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21749             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21750             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21751             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21752             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21753             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21754             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21755     })
21756     @TextAlignment
getTextAlignment()21757     public int getTextAlignment() {
21758         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21759                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21760     }
21761 
21762     /**
21763      * Resolve the text alignment.
21764      *
21765      * @return true if resolution has been done, false otherwise.
21766      *
21767      * @hide
21768      */
resolveTextAlignment()21769     public boolean resolveTextAlignment() {
21770         // Reset any previous text alignment resolution
21771         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21772 
21773         if (hasRtlSupport()) {
21774             // Set resolved text alignment flag depending on text alignment flag
21775             final int textAlignment = getRawTextAlignment();
21776             switch (textAlignment) {
21777                 case TEXT_ALIGNMENT_INHERIT:
21778                     // Check if we can resolve the text alignment
21779                     if (!canResolveTextAlignment()) {
21780                         // We cannot do the resolution if there is no parent so use the default
21781                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21782                         // Resolution will need to happen again later
21783                         return false;
21784                     }
21785 
21786                     // Parent has not yet resolved, so we still return the default
21787                     try {
21788                         if (!mParent.isTextAlignmentResolved()) {
21789                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21790                             // Resolution will need to happen again later
21791                             return false;
21792                         }
21793                     } catch (AbstractMethodError e) {
21794                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21795                                 " does not fully implement ViewParent", e);
21796                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21797                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21798                         return true;
21799                     }
21800 
21801                     int parentResolvedTextAlignment;
21802                     try {
21803                         parentResolvedTextAlignment = mParent.getTextAlignment();
21804                     } catch (AbstractMethodError e) {
21805                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21806                                 " does not fully implement ViewParent", e);
21807                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21808                     }
21809                     switch (parentResolvedTextAlignment) {
21810                         case TEXT_ALIGNMENT_GRAVITY:
21811                         case TEXT_ALIGNMENT_TEXT_START:
21812                         case TEXT_ALIGNMENT_TEXT_END:
21813                         case TEXT_ALIGNMENT_CENTER:
21814                         case TEXT_ALIGNMENT_VIEW_START:
21815                         case TEXT_ALIGNMENT_VIEW_END:
21816                             // Resolved text alignment is the same as the parent resolved
21817                             // text alignment
21818                             mPrivateFlags2 |=
21819                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21820                             break;
21821                         default:
21822                             // Use default resolved text alignment
21823                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21824                     }
21825                     break;
21826                 case TEXT_ALIGNMENT_GRAVITY:
21827                 case TEXT_ALIGNMENT_TEXT_START:
21828                 case TEXT_ALIGNMENT_TEXT_END:
21829                 case TEXT_ALIGNMENT_CENTER:
21830                 case TEXT_ALIGNMENT_VIEW_START:
21831                 case TEXT_ALIGNMENT_VIEW_END:
21832                     // Resolved text alignment is the same as text alignment
21833                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21834                     break;
21835                 default:
21836                     // Use default resolved text alignment
21837                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21838             }
21839         } else {
21840             // Use default resolved text alignment
21841             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21842         }
21843 
21844         // Set the resolved
21845         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21846         return true;
21847     }
21848 
21849     /**
21850      * Check if text alignment resolution can be done.
21851      *
21852      * @return true if text alignment resolution can be done otherwise return false.
21853      */
canResolveTextAlignment()21854     public boolean canResolveTextAlignment() {
21855         switch (getRawTextAlignment()) {
21856             case TEXT_DIRECTION_INHERIT:
21857                 if (mParent != null) {
21858                     try {
21859                         return mParent.canResolveTextAlignment();
21860                     } catch (AbstractMethodError e) {
21861                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21862                                 " does not fully implement ViewParent", e);
21863                     }
21864                 }
21865                 return false;
21866 
21867             default:
21868                 return true;
21869         }
21870     }
21871 
21872     /**
21873      * Reset resolved text alignment. Text alignment will be resolved during a call to
21874      * {@link #onMeasure(int, int)}.
21875      *
21876      * @hide
21877      */
resetResolvedTextAlignment()21878     public void resetResolvedTextAlignment() {
21879         // Reset any previous text alignment resolution
21880         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21881         // Set to default
21882         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21883     }
21884 
21885     /**
21886      * @return true if text alignment is inherited.
21887      *
21888      * @hide
21889      */
isTextAlignmentInherited()21890     public boolean isTextAlignmentInherited() {
21891         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21892     }
21893 
21894     /**
21895      * @return true if text alignment is resolved.
21896      */
isTextAlignmentResolved()21897     public boolean isTextAlignmentResolved() {
21898         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21899     }
21900 
21901     /**
21902      * Generate a value suitable for use in {@link #setId(int)}.
21903      * This value will not collide with ID values generated at build time by aapt for R.id.
21904      *
21905      * @return a generated ID value
21906      */
generateViewId()21907     public static int generateViewId() {
21908         for (;;) {
21909             final int result = sNextGeneratedId.get();
21910             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21911             int newValue = result + 1;
21912             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21913             if (sNextGeneratedId.compareAndSet(result, newValue)) {
21914                 return result;
21915             }
21916         }
21917     }
21918 
21919     /**
21920      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21921      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21922      *                           a normal View or a ViewGroup with
21923      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21924      * @hide
21925      */
captureTransitioningViews(List<View> transitioningViews)21926     public void captureTransitioningViews(List<View> transitioningViews) {
21927         if (getVisibility() == View.VISIBLE) {
21928             transitioningViews.add(this);
21929         }
21930     }
21931 
21932     /**
21933      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21934      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21935      * @hide
21936      */
findNamedViews(Map<String, View> namedElements)21937     public void findNamedViews(Map<String, View> namedElements) {
21938         if (getVisibility() == VISIBLE || mGhostView != null) {
21939             String transitionName = getTransitionName();
21940             if (transitionName != null) {
21941                 namedElements.put(transitionName, this);
21942             }
21943         }
21944     }
21945 
21946     /**
21947      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
21948      * The default implementation does not care the location or event types, but some subclasses
21949      * may use it (such as WebViews).
21950      * @param event The MotionEvent from a mouse
21951      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
21952      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
21953      * @see PointerIcon
21954      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)21955     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
21956         final float x = event.getX(pointerIndex);
21957         final float y = event.getY(pointerIndex);
21958         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
21959             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
21960         }
21961         return mPointerIcon;
21962     }
21963 
21964     /**
21965      * Set the pointer icon for the current view.
21966      * Passing {@code null} will restore the pointer icon to its default value.
21967      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
21968      */
setPointerIcon(PointerIcon pointerIcon)21969     public void setPointerIcon(PointerIcon pointerIcon) {
21970         mPointerIcon = pointerIcon;
21971         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
21972             return;
21973         }
21974         try {
21975             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
21976         } catch (RemoteException e) {
21977         }
21978     }
21979 
21980     /**
21981      * Gets the pointer icon for the current view.
21982      */
getPointerIcon()21983     public PointerIcon getPointerIcon() {
21984         return mPointerIcon;
21985     }
21986 
21987     //
21988     // Properties
21989     //
21990     /**
21991      * A Property wrapper around the <code>alpha</code> functionality handled by the
21992      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21993      */
21994     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21995         @Override
21996         public void setValue(View object, float value) {
21997             object.setAlpha(value);
21998         }
21999 
22000         @Override
22001         public Float get(View object) {
22002             return object.getAlpha();
22003         }
22004     };
22005 
22006     /**
22007      * A Property wrapper around the <code>translationX</code> functionality handled by the
22008      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
22009      */
22010     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
22011         @Override
22012         public void setValue(View object, float value) {
22013             object.setTranslationX(value);
22014         }
22015 
22016                 @Override
22017         public Float get(View object) {
22018             return object.getTranslationX();
22019         }
22020     };
22021 
22022     /**
22023      * A Property wrapper around the <code>translationY</code> functionality handled by the
22024      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22025      */
22026     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22027         @Override
22028         public void setValue(View object, float value) {
22029             object.setTranslationY(value);
22030         }
22031 
22032         @Override
22033         public Float get(View object) {
22034             return object.getTranslationY();
22035         }
22036     };
22037 
22038     /**
22039      * A Property wrapper around the <code>translationZ</code> functionality handled by the
22040      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22041      */
22042     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22043         @Override
22044         public void setValue(View object, float value) {
22045             object.setTranslationZ(value);
22046         }
22047 
22048         @Override
22049         public Float get(View object) {
22050             return object.getTranslationZ();
22051         }
22052     };
22053 
22054     /**
22055      * A Property wrapper around the <code>x</code> functionality handled by the
22056      * {@link View#setX(float)} and {@link View#getX()} methods.
22057      */
22058     public static final Property<View, Float> X = new FloatProperty<View>("x") {
22059         @Override
22060         public void setValue(View object, float value) {
22061             object.setX(value);
22062         }
22063 
22064         @Override
22065         public Float get(View object) {
22066             return object.getX();
22067         }
22068     };
22069 
22070     /**
22071      * A Property wrapper around the <code>y</code> functionality handled by the
22072      * {@link View#setY(float)} and {@link View#getY()} methods.
22073      */
22074     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22075         @Override
22076         public void setValue(View object, float value) {
22077             object.setY(value);
22078         }
22079 
22080         @Override
22081         public Float get(View object) {
22082             return object.getY();
22083         }
22084     };
22085 
22086     /**
22087      * A Property wrapper around the <code>z</code> functionality handled by the
22088      * {@link View#setZ(float)} and {@link View#getZ()} methods.
22089      */
22090     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22091         @Override
22092         public void setValue(View object, float value) {
22093             object.setZ(value);
22094         }
22095 
22096         @Override
22097         public Float get(View object) {
22098             return object.getZ();
22099         }
22100     };
22101 
22102     /**
22103      * A Property wrapper around the <code>rotation</code> functionality handled by the
22104      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22105      */
22106     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22107         @Override
22108         public void setValue(View object, float value) {
22109             object.setRotation(value);
22110         }
22111 
22112         @Override
22113         public Float get(View object) {
22114             return object.getRotation();
22115         }
22116     };
22117 
22118     /**
22119      * A Property wrapper around the <code>rotationX</code> functionality handled by the
22120      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22121      */
22122     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22123         @Override
22124         public void setValue(View object, float value) {
22125             object.setRotationX(value);
22126         }
22127 
22128         @Override
22129         public Float get(View object) {
22130             return object.getRotationX();
22131         }
22132     };
22133 
22134     /**
22135      * A Property wrapper around the <code>rotationY</code> functionality handled by the
22136      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22137      */
22138     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22139         @Override
22140         public void setValue(View object, float value) {
22141             object.setRotationY(value);
22142         }
22143 
22144         @Override
22145         public Float get(View object) {
22146             return object.getRotationY();
22147         }
22148     };
22149 
22150     /**
22151      * A Property wrapper around the <code>scaleX</code> functionality handled by the
22152      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22153      */
22154     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22155         @Override
22156         public void setValue(View object, float value) {
22157             object.setScaleX(value);
22158         }
22159 
22160         @Override
22161         public Float get(View object) {
22162             return object.getScaleX();
22163         }
22164     };
22165 
22166     /**
22167      * A Property wrapper around the <code>scaleY</code> functionality handled by the
22168      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22169      */
22170     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22171         @Override
22172         public void setValue(View object, float value) {
22173             object.setScaleY(value);
22174         }
22175 
22176         @Override
22177         public Float get(View object) {
22178             return object.getScaleY();
22179         }
22180     };
22181 
22182     /**
22183      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22184      * Each MeasureSpec represents a requirement for either the width or the height.
22185      * A MeasureSpec is comprised of a size and a mode. There are three possible
22186      * modes:
22187      * <dl>
22188      * <dt>UNSPECIFIED</dt>
22189      * <dd>
22190      * The parent has not imposed any constraint on the child. It can be whatever size
22191      * it wants.
22192      * </dd>
22193      *
22194      * <dt>EXACTLY</dt>
22195      * <dd>
22196      * The parent has determined an exact size for the child. The child is going to be
22197      * given those bounds regardless of how big it wants to be.
22198      * </dd>
22199      *
22200      * <dt>AT_MOST</dt>
22201      * <dd>
22202      * The child can be as large as it wants up to the specified size.
22203      * </dd>
22204      * </dl>
22205      *
22206      * MeasureSpecs are implemented as ints to reduce object allocation. This class
22207      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22208      */
22209     public static class MeasureSpec {
22210         private static final int MODE_SHIFT = 30;
22211         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22212 
22213         /** @hide */
22214         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22215         @Retention(RetentionPolicy.SOURCE)
22216         public @interface MeasureSpecMode {}
22217 
22218         /**
22219          * Measure specification mode: The parent has not imposed any constraint
22220          * on the child. It can be whatever size it wants.
22221          */
22222         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22223 
22224         /**
22225          * Measure specification mode: The parent has determined an exact size
22226          * for the child. The child is going to be given those bounds regardless
22227          * of how big it wants to be.
22228          */
22229         public static final int EXACTLY     = 1 << MODE_SHIFT;
22230 
22231         /**
22232          * Measure specification mode: The child can be as large as it wants up
22233          * to the specified size.
22234          */
22235         public static final int AT_MOST     = 2 << MODE_SHIFT;
22236 
22237         /**
22238          * Creates a measure specification based on the supplied size and mode.
22239          *
22240          * The mode must always be one of the following:
22241          * <ul>
22242          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22243          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22244          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22245          * </ul>
22246          *
22247          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22248          * implementation was such that the order of arguments did not matter
22249          * and overflow in either value could impact the resulting MeasureSpec.
22250          * {@link android.widget.RelativeLayout} was affected by this bug.
22251          * Apps targeting API levels greater than 17 will get the fixed, more strict
22252          * behavior.</p>
22253          *
22254          * @param size the size of the measure specification
22255          * @param mode the mode of the measure specification
22256          * @return the measure specification based on size and mode
22257          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)22258         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22259                                           @MeasureSpecMode int mode) {
22260             if (sUseBrokenMakeMeasureSpec) {
22261                 return size + mode;
22262             } else {
22263                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
22264             }
22265         }
22266 
22267         /**
22268          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22269          * will automatically get a size of 0. Older apps expect this.
22270          *
22271          * @hide internal use only for compatibility with system widgets and older apps
22272          */
makeSafeMeasureSpec(int size, int mode)22273         public static int makeSafeMeasureSpec(int size, int mode) {
22274             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22275                 return 0;
22276             }
22277             return makeMeasureSpec(size, mode);
22278         }
22279 
22280         /**
22281          * Extracts the mode from the supplied measure specification.
22282          *
22283          * @param measureSpec the measure specification to extract the mode from
22284          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22285          *         {@link android.view.View.MeasureSpec#AT_MOST} or
22286          *         {@link android.view.View.MeasureSpec#EXACTLY}
22287          */
22288         @MeasureSpecMode
getMode(int measureSpec)22289         public static int getMode(int measureSpec) {
22290             //noinspection ResourceType
22291             return (measureSpec & MODE_MASK);
22292         }
22293 
22294         /**
22295          * Extracts the size from the supplied measure specification.
22296          *
22297          * @param measureSpec the measure specification to extract the size from
22298          * @return the size in pixels defined in the supplied measure specification
22299          */
getSize(int measureSpec)22300         public static int getSize(int measureSpec) {
22301             return (measureSpec & ~MODE_MASK);
22302         }
22303 
adjust(int measureSpec, int delta)22304         static int adjust(int measureSpec, int delta) {
22305             final int mode = getMode(measureSpec);
22306             int size = getSize(measureSpec);
22307             if (mode == UNSPECIFIED) {
22308                 // No need to adjust size for UNSPECIFIED mode.
22309                 return makeMeasureSpec(size, UNSPECIFIED);
22310             }
22311             size += delta;
22312             if (size < 0) {
22313                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22314                         ") spec: " + toString(measureSpec) + " delta: " + delta);
22315                 size = 0;
22316             }
22317             return makeMeasureSpec(size, mode);
22318         }
22319 
22320         /**
22321          * Returns a String representation of the specified measure
22322          * specification.
22323          *
22324          * @param measureSpec the measure specification to convert to a String
22325          * @return a String with the following format: "MeasureSpec: MODE SIZE"
22326          */
toString(int measureSpec)22327         public static String toString(int measureSpec) {
22328             int mode = getMode(measureSpec);
22329             int size = getSize(measureSpec);
22330 
22331             StringBuilder sb = new StringBuilder("MeasureSpec: ");
22332 
22333             if (mode == UNSPECIFIED)
22334                 sb.append("UNSPECIFIED ");
22335             else if (mode == EXACTLY)
22336                 sb.append("EXACTLY ");
22337             else if (mode == AT_MOST)
22338                 sb.append("AT_MOST ");
22339             else
22340                 sb.append(mode).append(" ");
22341 
22342             sb.append(size);
22343             return sb.toString();
22344         }
22345     }
22346 
22347     private final class CheckForLongPress implements Runnable {
22348         private int mOriginalWindowAttachCount;
22349         private float mX;
22350         private float mY;
22351 
22352         @Override
run()22353         public void run() {
22354             if (isPressed() && (mParent != null)
22355                     && mOriginalWindowAttachCount == mWindowAttachCount) {
22356                 if (performLongClick(mX, mY)) {
22357                     mHasPerformedLongPress = true;
22358                 }
22359             }
22360         }
22361 
setAnchor(float x, float y)22362         public void setAnchor(float x, float y) {
22363             mX = x;
22364             mY = y;
22365         }
22366 
rememberWindowAttachCount()22367         public void rememberWindowAttachCount() {
22368             mOriginalWindowAttachCount = mWindowAttachCount;
22369         }
22370     }
22371 
22372     private final class CheckForTap implements Runnable {
22373         public float x;
22374         public float y;
22375 
22376         @Override
run()22377         public void run() {
22378             mPrivateFlags &= ~PFLAG_PREPRESSED;
22379             setPressed(true, x, y);
22380             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22381         }
22382     }
22383 
22384     private final class PerformClick implements Runnable {
22385         @Override
run()22386         public void run() {
22387             performClick();
22388         }
22389     }
22390 
22391     /**
22392      * This method returns a ViewPropertyAnimator object, which can be used to animate
22393      * specific properties on this View.
22394      *
22395      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22396      */
animate()22397     public ViewPropertyAnimator animate() {
22398         if (mAnimator == null) {
22399             mAnimator = new ViewPropertyAnimator(this);
22400         }
22401         return mAnimator;
22402     }
22403 
22404     /**
22405      * Sets the name of the View to be used to identify Views in Transitions.
22406      * Names should be unique in the View hierarchy.
22407      *
22408      * @param transitionName The name of the View to uniquely identify it for Transitions.
22409      */
setTransitionName(String transitionName)22410     public final void setTransitionName(String transitionName) {
22411         mTransitionName = transitionName;
22412     }
22413 
22414     /**
22415      * Returns the name of the View to be used to identify Views in Transitions.
22416      * Names should be unique in the View hierarchy.
22417      *
22418      * <p>This returns null if the View has not been given a name.</p>
22419      *
22420      * @return The name used of the View to be used to identify Views in Transitions or null
22421      * if no name has been given.
22422      */
22423     @ViewDebug.ExportedProperty
getTransitionName()22424     public String getTransitionName() {
22425         return mTransitionName;
22426     }
22427 
22428     /**
22429      * @hide
22430      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)22431     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22432         // Do nothing.
22433     }
22434 
22435     /**
22436      * Interface definition for a callback to be invoked when a hardware key event is
22437      * dispatched to this view. The callback will be invoked before the key event is
22438      * given to the view. This is only useful for hardware keyboards; a software input
22439      * method has no obligation to trigger this listener.
22440      */
22441     public interface OnKeyListener {
22442         /**
22443          * Called when a hardware key is dispatched to a view. This allows listeners to
22444          * get a chance to respond before the target view.
22445          * <p>Key presses in software keyboards will generally NOT trigger this method,
22446          * although some may elect to do so in some situations. Do not assume a
22447          * software input method has to be key-based; even if it is, it may use key presses
22448          * in a different way than you expect, so there is no way to reliably catch soft
22449          * input key presses.
22450          *
22451          * @param v The view the key has been dispatched to.
22452          * @param keyCode The code for the physical key that was pressed
22453          * @param event The KeyEvent object containing full information about
22454          *        the event.
22455          * @return True if the listener has consumed the event, false otherwise.
22456          */
onKey(View v, int keyCode, KeyEvent event)22457         boolean onKey(View v, int keyCode, KeyEvent event);
22458     }
22459 
22460     /**
22461      * Interface definition for a callback to be invoked when a touch event is
22462      * dispatched to this view. The callback will be invoked before the touch
22463      * event is given to the view.
22464      */
22465     public interface OnTouchListener {
22466         /**
22467          * Called when a touch event is dispatched to a view. This allows listeners to
22468          * get a chance to respond before the target view.
22469          *
22470          * @param v The view the touch event has been dispatched to.
22471          * @param event The MotionEvent object containing full information about
22472          *        the event.
22473          * @return True if the listener has consumed the event, false otherwise.
22474          */
onTouch(View v, MotionEvent event)22475         boolean onTouch(View v, MotionEvent event);
22476     }
22477 
22478     /**
22479      * Interface definition for a callback to be invoked when a hover event is
22480      * dispatched to this view. The callback will be invoked before the hover
22481      * event is given to the view.
22482      */
22483     public interface OnHoverListener {
22484         /**
22485          * Called when a hover event is dispatched to a view. This allows listeners to
22486          * get a chance to respond before the target view.
22487          *
22488          * @param v The view the hover event has been dispatched to.
22489          * @param event The MotionEvent object containing full information about
22490          *        the event.
22491          * @return True if the listener has consumed the event, false otherwise.
22492          */
onHover(View v, MotionEvent event)22493         boolean onHover(View v, MotionEvent event);
22494     }
22495 
22496     /**
22497      * Interface definition for a callback to be invoked when a generic motion event is
22498      * dispatched to this view. The callback will be invoked before the generic motion
22499      * event is given to the view.
22500      */
22501     public interface OnGenericMotionListener {
22502         /**
22503          * Called when a generic motion event is dispatched to a view. This allows listeners to
22504          * get a chance to respond before the target view.
22505          *
22506          * @param v The view the generic motion event has been dispatched to.
22507          * @param event The MotionEvent object containing full information about
22508          *        the event.
22509          * @return True if the listener has consumed the event, false otherwise.
22510          */
onGenericMotion(View v, MotionEvent event)22511         boolean onGenericMotion(View v, MotionEvent event);
22512     }
22513 
22514     /**
22515      * Interface definition for a callback to be invoked when a view has been clicked and held.
22516      */
22517     public interface OnLongClickListener {
22518         /**
22519          * Called when a view has been clicked and held.
22520          *
22521          * @param v The view that was clicked and held.
22522          *
22523          * @return true if the callback consumed the long click, false otherwise.
22524          */
onLongClick(View v)22525         boolean onLongClick(View v);
22526     }
22527 
22528     /**
22529      * Interface definition for a callback to be invoked when a drag is being dispatched
22530      * to this view.  The callback will be invoked before the hosting view's own
22531      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
22532      * onDrag(event) behavior, it should return 'false' from this callback.
22533      *
22534      * <div class="special reference">
22535      * <h3>Developer Guides</h3>
22536      * <p>For a guide to implementing drag and drop features, read the
22537      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22538      * </div>
22539      */
22540     public interface OnDragListener {
22541         /**
22542          * Called when a drag event is dispatched to a view. This allows listeners
22543          * to get a chance to override base View behavior.
22544          *
22545          * @param v The View that received the drag event.
22546          * @param event The {@link android.view.DragEvent} object for the drag event.
22547          * @return {@code true} if the drag event was handled successfully, or {@code false}
22548          * if the drag event was not handled. Note that {@code false} will trigger the View
22549          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22550          */
onDrag(View v, DragEvent event)22551         boolean onDrag(View v, DragEvent event);
22552     }
22553 
22554     /**
22555      * Interface definition for a callback to be invoked when the focus state of
22556      * a view changed.
22557      */
22558     public interface OnFocusChangeListener {
22559         /**
22560          * Called when the focus state of a view has changed.
22561          *
22562          * @param v The view whose state has changed.
22563          * @param hasFocus The new focus state of v.
22564          */
onFocusChange(View v, boolean hasFocus)22565         void onFocusChange(View v, boolean hasFocus);
22566     }
22567 
22568     /**
22569      * Interface definition for a callback to be invoked when a view is clicked.
22570      */
22571     public interface OnClickListener {
22572         /**
22573          * Called when a view has been clicked.
22574          *
22575          * @param v The view that was clicked.
22576          */
onClick(View v)22577         void onClick(View v);
22578     }
22579 
22580     /**
22581      * Interface definition for a callback to be invoked when a view is context clicked.
22582      */
22583     public interface OnContextClickListener {
22584         /**
22585          * Called when a view is context clicked.
22586          *
22587          * @param v The view that has been context clicked.
22588          * @return true if the callback consumed the context click, false otherwise.
22589          */
onContextClick(View v)22590         boolean onContextClick(View v);
22591     }
22592 
22593     /**
22594      * Interface definition for a callback to be invoked when the context menu
22595      * for this view is being built.
22596      */
22597     public interface OnCreateContextMenuListener {
22598         /**
22599          * Called when the context menu for this view is being built. It is not
22600          * safe to hold onto the menu after this method returns.
22601          *
22602          * @param menu The context menu that is being built
22603          * @param v The view for which the context menu is being built
22604          * @param menuInfo Extra information about the item for which the
22605          *            context menu should be shown. This information will vary
22606          *            depending on the class of v.
22607          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)22608         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22609     }
22610 
22611     /**
22612      * Interface definition for a callback to be invoked when the status bar changes
22613      * visibility.  This reports <strong>global</strong> changes to the system UI
22614      * state, not what the application is requesting.
22615      *
22616      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22617      */
22618     public interface OnSystemUiVisibilityChangeListener {
22619         /**
22620          * Called when the status bar changes visibility because of a call to
22621          * {@link View#setSystemUiVisibility(int)}.
22622          *
22623          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22624          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22625          * This tells you the <strong>global</strong> state of these UI visibility
22626          * flags, not what your app is currently applying.
22627          */
onSystemUiVisibilityChange(int visibility)22628         public void onSystemUiVisibilityChange(int visibility);
22629     }
22630 
22631     /**
22632      * Interface definition for a callback to be invoked when this view is attached
22633      * or detached from its window.
22634      */
22635     public interface OnAttachStateChangeListener {
22636         /**
22637          * Called when the view is attached to a window.
22638          * @param v The view that was attached
22639          */
onViewAttachedToWindow(View v)22640         public void onViewAttachedToWindow(View v);
22641         /**
22642          * Called when the view is detached from a window.
22643          * @param v The view that was detached
22644          */
onViewDetachedFromWindow(View v)22645         public void onViewDetachedFromWindow(View v);
22646     }
22647 
22648     /**
22649      * Listener for applying window insets on a view in a custom way.
22650      *
22651      * <p>Apps may choose to implement this interface if they want to apply custom policy
22652      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22653      * is set, its
22654      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22655      * method will be called instead of the View's own
22656      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22657      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22658      * the View's normal behavior as part of its own.</p>
22659      */
22660     public interface OnApplyWindowInsetsListener {
22661         /**
22662          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22663          * on a View, this listener method will be called instead of the view's own
22664          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22665          *
22666          * @param v The view applying window insets
22667          * @param insets The insets to apply
22668          * @return The insets supplied, minus any insets that were consumed
22669          */
onApplyWindowInsets(View v, WindowInsets insets)22670         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22671     }
22672 
22673     private final class UnsetPressedState implements Runnable {
22674         @Override
run()22675         public void run() {
22676             setPressed(false);
22677         }
22678     }
22679 
22680     /**
22681      * Base class for derived classes that want to save and restore their own
22682      * state in {@link android.view.View#onSaveInstanceState()}.
22683      */
22684     public static class BaseSavedState extends AbsSavedState {
22685         String mStartActivityRequestWhoSaved;
22686 
22687         /**
22688          * Constructor used when reading from a parcel. Reads the state of the superclass.
22689          *
22690          * @param source parcel to read from
22691          */
BaseSavedState(Parcel source)22692         public BaseSavedState(Parcel source) {
22693             this(source, null);
22694         }
22695 
22696         /**
22697          * Constructor used when reading from a parcel using a given class loader.
22698          * Reads the state of the superclass.
22699          *
22700          * @param source parcel to read from
22701          * @param loader ClassLoader to use for reading
22702          */
BaseSavedState(Parcel source, ClassLoader loader)22703         public BaseSavedState(Parcel source, ClassLoader loader) {
22704             super(source, loader);
22705             mStartActivityRequestWhoSaved = source.readString();
22706         }
22707 
22708         /**
22709          * Constructor called by derived classes when creating their SavedState objects
22710          *
22711          * @param superState The state of the superclass of this view
22712          */
BaseSavedState(Parcelable superState)22713         public BaseSavedState(Parcelable superState) {
22714             super(superState);
22715         }
22716 
22717         @Override
writeToParcel(Parcel out, int flags)22718         public void writeToParcel(Parcel out, int flags) {
22719             super.writeToParcel(out, flags);
22720             out.writeString(mStartActivityRequestWhoSaved);
22721         }
22722 
22723         public static final Parcelable.Creator<BaseSavedState> CREATOR
22724                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22725             @Override
22726             public BaseSavedState createFromParcel(Parcel in) {
22727                 return new BaseSavedState(in);
22728             }
22729 
22730             @Override
22731             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22732                 return new BaseSavedState(in, loader);
22733             }
22734 
22735             @Override
22736             public BaseSavedState[] newArray(int size) {
22737                 return new BaseSavedState[size];
22738             }
22739         };
22740     }
22741 
22742     /**
22743      * A set of information given to a view when it is attached to its parent
22744      * window.
22745      */
22746     final static class AttachInfo {
22747         interface Callbacks {
playSoundEffect(int effectId)22748             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)22749             boolean performHapticFeedback(int effectId, boolean always);
22750         }
22751 
22752         /**
22753          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22754          * to a Handler. This class contains the target (View) to invalidate and
22755          * the coordinates of the dirty rectangle.
22756          *
22757          * For performance purposes, this class also implements a pool of up to
22758          * POOL_LIMIT objects that get reused. This reduces memory allocations
22759          * whenever possible.
22760          */
22761         static class InvalidateInfo {
22762             private static final int POOL_LIMIT = 10;
22763 
22764             private static final SynchronizedPool<InvalidateInfo> sPool =
22765                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22766 
22767             View target;
22768 
22769             int left;
22770             int top;
22771             int right;
22772             int bottom;
22773 
obtain()22774             public static InvalidateInfo obtain() {
22775                 InvalidateInfo instance = sPool.acquire();
22776                 return (instance != null) ? instance : new InvalidateInfo();
22777             }
22778 
recycle()22779             public void recycle() {
22780                 target = null;
22781                 sPool.release(this);
22782             }
22783         }
22784 
22785         final IWindowSession mSession;
22786 
22787         final IWindow mWindow;
22788 
22789         final IBinder mWindowToken;
22790 
22791         final Display mDisplay;
22792 
22793         final Callbacks mRootCallbacks;
22794 
22795         IWindowId mIWindowId;
22796         WindowId mWindowId;
22797 
22798         /**
22799          * The top view of the hierarchy.
22800          */
22801         View mRootView;
22802 
22803         IBinder mPanelParentWindowToken;
22804 
22805         boolean mHardwareAccelerated;
22806         boolean mHardwareAccelerationRequested;
22807         ThreadedRenderer mHardwareRenderer;
22808         List<RenderNode> mPendingAnimatingRenderNodes;
22809 
22810         /**
22811          * The state of the display to which the window is attached, as reported
22812          * by {@link Display#getState()}.  Note that the display state constants
22813          * declared by {@link Display} do not exactly line up with the screen state
22814          * constants declared by {@link View} (there are more display states than
22815          * screen states).
22816          */
22817         int mDisplayState = Display.STATE_UNKNOWN;
22818 
22819         /**
22820          * Scale factor used by the compatibility mode
22821          */
22822         float mApplicationScale;
22823 
22824         /**
22825          * Indicates whether the application is in compatibility mode
22826          */
22827         boolean mScalingRequired;
22828 
22829         /**
22830          * Left position of this view's window
22831          */
22832         int mWindowLeft;
22833 
22834         /**
22835          * Top position of this view's window
22836          */
22837         int mWindowTop;
22838 
22839         /**
22840          * Indicates whether views need to use 32-bit drawing caches
22841          */
22842         boolean mUse32BitDrawingCache;
22843 
22844         /**
22845          * For windows that are full-screen but using insets to layout inside
22846          * of the screen areas, these are the current insets to appear inside
22847          * the overscan area of the display.
22848          */
22849         final Rect mOverscanInsets = new Rect();
22850 
22851         /**
22852          * For windows that are full-screen but using insets to layout inside
22853          * of the screen decorations, these are the current insets for the
22854          * content of the window.
22855          */
22856         final Rect mContentInsets = new Rect();
22857 
22858         /**
22859          * For windows that are full-screen but using insets to layout inside
22860          * of the screen decorations, these are the current insets for the
22861          * actual visible parts of the window.
22862          */
22863         final Rect mVisibleInsets = new Rect();
22864 
22865         /**
22866          * For windows that are full-screen but using insets to layout inside
22867          * of the screen decorations, these are the current insets for the
22868          * stable system windows.
22869          */
22870         final Rect mStableInsets = new Rect();
22871 
22872         /**
22873          * For windows that include areas that are not covered by real surface these are the outsets
22874          * for real surface.
22875          */
22876         final Rect mOutsets = new Rect();
22877 
22878         /**
22879          * In multi-window we force show the navigation bar. Because we don't want that the surface
22880          * size changes in this mode, we instead have a flag whether the navigation bar size should
22881          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22882          */
22883         boolean mAlwaysConsumeNavBar;
22884 
22885         /**
22886          * The internal insets given by this window.  This value is
22887          * supplied by the client (through
22888          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22889          * be given to the window manager when changed to be used in laying
22890          * out windows behind it.
22891          */
22892         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22893                 = new ViewTreeObserver.InternalInsetsInfo();
22894 
22895         /**
22896          * Set to true when mGivenInternalInsets is non-empty.
22897          */
22898         boolean mHasNonEmptyGivenInternalInsets;
22899 
22900         /**
22901          * All views in the window's hierarchy that serve as scroll containers,
22902          * used to determine if the window can be resized or must be panned
22903          * to adjust for a soft input area.
22904          */
22905         final ArrayList<View> mScrollContainers = new ArrayList<View>();
22906 
22907         final KeyEvent.DispatcherState mKeyDispatchState
22908                 = new KeyEvent.DispatcherState();
22909 
22910         /**
22911          * Indicates whether the view's window currently has the focus.
22912          */
22913         boolean mHasWindowFocus;
22914 
22915         /**
22916          * The current visibility of the window.
22917          */
22918         int mWindowVisibility;
22919 
22920         /**
22921          * Indicates the time at which drawing started to occur.
22922          */
22923         long mDrawingTime;
22924 
22925         /**
22926          * Indicates whether or not ignoring the DIRTY_MASK flags.
22927          */
22928         boolean mIgnoreDirtyState;
22929 
22930         /**
22931          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22932          * to avoid clearing that flag prematurely.
22933          */
22934         boolean mSetIgnoreDirtyState = false;
22935 
22936         /**
22937          * Indicates whether the view's window is currently in touch mode.
22938          */
22939         boolean mInTouchMode;
22940 
22941         /**
22942          * Indicates whether the view has requested unbuffered input dispatching for the current
22943          * event stream.
22944          */
22945         boolean mUnbufferedDispatchRequested;
22946 
22947         /**
22948          * Indicates that ViewAncestor should trigger a global layout change
22949          * the next time it performs a traversal
22950          */
22951         boolean mRecomputeGlobalAttributes;
22952 
22953         /**
22954          * Always report new attributes at next traversal.
22955          */
22956         boolean mForceReportNewAttributes;
22957 
22958         /**
22959          * Set during a traveral if any views want to keep the screen on.
22960          */
22961         boolean mKeepScreenOn;
22962 
22963         /**
22964          * Set during a traveral if the light center needs to be updated.
22965          */
22966         boolean mNeedsUpdateLightCenter;
22967 
22968         /**
22969          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22970          */
22971         int mSystemUiVisibility;
22972 
22973         /**
22974          * Hack to force certain system UI visibility flags to be cleared.
22975          */
22976         int mDisabledSystemUiVisibility;
22977 
22978         /**
22979          * Last global system UI visibility reported by the window manager.
22980          */
22981         int mGlobalSystemUiVisibility = -1;
22982 
22983         /**
22984          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22985          * attached.
22986          */
22987         boolean mHasSystemUiListeners;
22988 
22989         /**
22990          * Set if the window has requested to extend into the overscan region
22991          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22992          */
22993         boolean mOverscanRequested;
22994 
22995         /**
22996          * Set if the visibility of any views has changed.
22997          */
22998         boolean mViewVisibilityChanged;
22999 
23000         /**
23001          * Set to true if a view has been scrolled.
23002          */
23003         boolean mViewScrollChanged;
23004 
23005         /**
23006          * Set to true if high contrast mode enabled
23007          */
23008         boolean mHighContrastText;
23009 
23010         /**
23011          * Set to true if a pointer event is currently being handled.
23012          */
23013         boolean mHandlingPointerEvent;
23014 
23015         /**
23016          * Global to the view hierarchy used as a temporary for dealing with
23017          * x/y points in the transparent region computations.
23018          */
23019         final int[] mTransparentLocation = new int[2];
23020 
23021         /**
23022          * Global to the view hierarchy used as a temporary for dealing with
23023          * x/y points in the ViewGroup.invalidateChild implementation.
23024          */
23025         final int[] mInvalidateChildLocation = new int[2];
23026 
23027         /**
23028          * Global to the view hierarchy used as a temporary for dealing with
23029          * computing absolute on-screen location.
23030          */
23031         final int[] mTmpLocation = new int[2];
23032 
23033         /**
23034          * Global to the view hierarchy used as a temporary for dealing with
23035          * x/y location when view is transformed.
23036          */
23037         final float[] mTmpTransformLocation = new float[2];
23038 
23039         /**
23040          * The view tree observer used to dispatch global events like
23041          * layout, pre-draw, touch mode change, etc.
23042          */
23043         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
23044 
23045         /**
23046          * A Canvas used by the view hierarchy to perform bitmap caching.
23047          */
23048         Canvas mCanvas;
23049 
23050         /**
23051          * The view root impl.
23052          */
23053         final ViewRootImpl mViewRootImpl;
23054 
23055         /**
23056          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23057          * handler can be used to pump events in the UI events queue.
23058          */
23059         final Handler mHandler;
23060 
23061         /**
23062          * Temporary for use in computing invalidate rectangles while
23063          * calling up the hierarchy.
23064          */
23065         final Rect mTmpInvalRect = new Rect();
23066 
23067         /**
23068          * Temporary for use in computing hit areas with transformed views
23069          */
23070         final RectF mTmpTransformRect = new RectF();
23071 
23072         /**
23073          * Temporary for use in computing hit areas with transformed views
23074          */
23075         final RectF mTmpTransformRect1 = new RectF();
23076 
23077         /**
23078          * Temporary list of rectanges.
23079          */
23080         final List<RectF> mTmpRectList = new ArrayList<>();
23081 
23082         /**
23083          * Temporary for use in transforming invalidation rect
23084          */
23085         final Matrix mTmpMatrix = new Matrix();
23086 
23087         /**
23088          * Temporary for use in transforming invalidation rect
23089          */
23090         final Transformation mTmpTransformation = new Transformation();
23091 
23092         /**
23093          * Temporary for use in querying outlines from OutlineProviders
23094          */
23095         final Outline mTmpOutline = new Outline();
23096 
23097         /**
23098          * Temporary list for use in collecting focusable descendents of a view.
23099          */
23100         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23101 
23102         /**
23103          * The id of the window for accessibility purposes.
23104          */
23105         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23106 
23107         /**
23108          * Flags related to accessibility processing.
23109          *
23110          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23111          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23112          */
23113         int mAccessibilityFetchFlags;
23114 
23115         /**
23116          * The drawable for highlighting accessibility focus.
23117          */
23118         Drawable mAccessibilityFocusDrawable;
23119 
23120         /**
23121          * Show where the margins, bounds and layout bounds are for each view.
23122          */
23123         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23124 
23125         /**
23126          * Point used to compute visible regions.
23127          */
23128         final Point mPoint = new Point();
23129 
23130         /**
23131          * Used to track which View originated a requestLayout() call, used when
23132          * requestLayout() is called during layout.
23133          */
23134         View mViewRequestingLayout;
23135 
23136         /**
23137          * Used to track views that need (at least) a partial relayout at their current size
23138          * during the next traversal.
23139          */
23140         List<View> mPartialLayoutViews = new ArrayList<>();
23141 
23142         /**
23143          * Swapped with mPartialLayoutViews during layout to avoid concurrent
23144          * modification. Lazily assigned during ViewRootImpl layout.
23145          */
23146         List<View> mEmptyPartialLayoutViews;
23147 
23148         /**
23149          * Used to track the identity of the current drag operation.
23150          */
23151         IBinder mDragToken;
23152 
23153         /**
23154          * The drag shadow surface for the current drag operation.
23155          */
23156         public Surface mDragSurface;
23157 
23158         /**
23159          * Creates a new set of attachment information with the specified
23160          * events handler and thread.
23161          *
23162          * @param handler the events handler the view must use
23163          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer)23164         AttachInfo(IWindowSession session, IWindow window, Display display,
23165                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23166             mSession = session;
23167             mWindow = window;
23168             mWindowToken = window.asBinder();
23169             mDisplay = display;
23170             mViewRootImpl = viewRootImpl;
23171             mHandler = handler;
23172             mRootCallbacks = effectPlayer;
23173         }
23174     }
23175 
23176     /**
23177      * <p>ScrollabilityCache holds various fields used by a View when scrolling
23178      * is supported. This avoids keeping too many unused fields in most
23179      * instances of View.</p>
23180      */
23181     private static class ScrollabilityCache implements Runnable {
23182 
23183         /**
23184          * Scrollbars are not visible
23185          */
23186         public static final int OFF = 0;
23187 
23188         /**
23189          * Scrollbars are visible
23190          */
23191         public static final int ON = 1;
23192 
23193         /**
23194          * Scrollbars are fading away
23195          */
23196         public static final int FADING = 2;
23197 
23198         public boolean fadeScrollBars;
23199 
23200         public int fadingEdgeLength;
23201         public int scrollBarDefaultDelayBeforeFade;
23202         public int scrollBarFadeDuration;
23203 
23204         public int scrollBarSize;
23205         public ScrollBarDrawable scrollBar;
23206         public float[] interpolatorValues;
23207         public View host;
23208 
23209         public final Paint paint;
23210         public final Matrix matrix;
23211         public Shader shader;
23212 
23213         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23214 
23215         private static final float[] OPAQUE = { 255 };
23216         private static final float[] TRANSPARENT = { 0.0f };
23217 
23218         /**
23219          * When fading should start. This time moves into the future every time
23220          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23221          */
23222         public long fadeStartTime;
23223 
23224 
23225         /**
23226          * The current state of the scrollbars: ON, OFF, or FADING
23227          */
23228         public int state = OFF;
23229 
23230         private int mLastColor;
23231 
23232         public final Rect mScrollBarBounds = new Rect();
23233 
23234         public static final int NOT_DRAGGING = 0;
23235         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23236         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23237         public int mScrollBarDraggingState = NOT_DRAGGING;
23238 
23239         public float mScrollBarDraggingPos = 0;
23240 
ScrollabilityCache(ViewConfiguration configuration, View host)23241         public ScrollabilityCache(ViewConfiguration configuration, View host) {
23242             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23243             scrollBarSize = configuration.getScaledScrollBarSize();
23244             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23245             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23246 
23247             paint = new Paint();
23248             matrix = new Matrix();
23249             // use use a height of 1, and then wack the matrix each time we
23250             // actually use it.
23251             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23252             paint.setShader(shader);
23253             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23254 
23255             this.host = host;
23256         }
23257 
setFadeColor(int color)23258         public void setFadeColor(int color) {
23259             if (color != mLastColor) {
23260                 mLastColor = color;
23261 
23262                 if (color != 0) {
23263                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23264                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23265                     paint.setShader(shader);
23266                     // Restore the default transfer mode (src_over)
23267                     paint.setXfermode(null);
23268                 } else {
23269                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23270                     paint.setShader(shader);
23271                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23272                 }
23273             }
23274         }
23275 
run()23276         public void run() {
23277             long now = AnimationUtils.currentAnimationTimeMillis();
23278             if (now >= fadeStartTime) {
23279 
23280                 // the animation fades the scrollbars out by changing
23281                 // the opacity (alpha) from fully opaque to fully
23282                 // transparent
23283                 int nextFrame = (int) now;
23284                 int framesCount = 0;
23285 
23286                 Interpolator interpolator = scrollBarInterpolator;
23287 
23288                 // Start opaque
23289                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23290 
23291                 // End transparent
23292                 nextFrame += scrollBarFadeDuration;
23293                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23294 
23295                 state = FADING;
23296 
23297                 // Kick off the fade animation
23298                 host.invalidate(true);
23299             }
23300         }
23301     }
23302 
23303     /**
23304      * Resuable callback for sending
23305      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23306      */
23307     private class SendViewScrolledAccessibilityEvent implements Runnable {
23308         public volatile boolean mIsPending;
23309 
run()23310         public void run() {
23311             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23312             mIsPending = false;
23313         }
23314     }
23315 
23316     /**
23317      * <p>
23318      * This class represents a delegate that can be registered in a {@link View}
23319      * to enhance accessibility support via composition rather via inheritance.
23320      * It is specifically targeted to widget developers that extend basic View
23321      * classes i.e. classes in package android.view, that would like their
23322      * applications to be backwards compatible.
23323      * </p>
23324      * <div class="special reference">
23325      * <h3>Developer Guides</h3>
23326      * <p>For more information about making applications accessible, read the
23327      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23328      * developer guide.</p>
23329      * </div>
23330      * <p>
23331      * A scenario in which a developer would like to use an accessibility delegate
23332      * is overriding a method introduced in a later API version then the minimal API
23333      * version supported by the application. For example, the method
23334      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23335      * in API version 4 when the accessibility APIs were first introduced. If a
23336      * developer would like his application to run on API version 4 devices (assuming
23337      * all other APIs used by the application are version 4 or lower) and take advantage
23338      * of this method, instead of overriding the method which would break the application's
23339      * backwards compatibility, he can override the corresponding method in this
23340      * delegate and register the delegate in the target View if the API version of
23341      * the system is high enough i.e. the API version is same or higher to the API
23342      * version that introduced
23343      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23344      * </p>
23345      * <p>
23346      * Here is an example implementation:
23347      * </p>
23348      * <code><pre><p>
23349      * if (Build.VERSION.SDK_INT >= 14) {
23350      *     // If the API version is equal of higher than the version in
23351      *     // which onInitializeAccessibilityNodeInfo was introduced we
23352      *     // register a delegate with a customized implementation.
23353      *     View view = findViewById(R.id.view_id);
23354      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23355      *         public void onInitializeAccessibilityNodeInfo(View host,
23356      *                 AccessibilityNodeInfo info) {
23357      *             // Let the default implementation populate the info.
23358      *             super.onInitializeAccessibilityNodeInfo(host, info);
23359      *             // Set some other information.
23360      *             info.setEnabled(host.isEnabled());
23361      *         }
23362      *     });
23363      * }
23364      * </code></pre></p>
23365      * <p>
23366      * This delegate contains methods that correspond to the accessibility methods
23367      * in View. If a delegate has been specified the implementation in View hands
23368      * off handling to the corresponding method in this delegate. The default
23369      * implementation the delegate methods behaves exactly as the corresponding
23370      * method in View for the case of no accessibility delegate been set. Hence,
23371      * to customize the behavior of a View method, clients can override only the
23372      * corresponding delegate method without altering the behavior of the rest
23373      * accessibility related methods of the host view.
23374      * </p>
23375      * <p>
23376      * <strong>Note:</strong> On platform versions prior to
23377      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23378      * views in the {@code android.widget.*} package are called <i>before</i>
23379      * host methods. This prevents certain properties such as class name from
23380      * being modified by overriding
23381      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23382      * as any changes will be overwritten by the host class.
23383      * <p>
23384      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23385      * methods are called <i>after</i> host methods, which all properties to be
23386      * modified without being overwritten by the host class.
23387      */
23388     public static class AccessibilityDelegate {
23389 
23390         /**
23391          * Sends an accessibility event of the given type. If accessibility is not
23392          * enabled this method has no effect.
23393          * <p>
23394          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23395          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23396          * been set.
23397          * </p>
23398          *
23399          * @param host The View hosting the delegate.
23400          * @param eventType The type of the event to send.
23401          *
23402          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23403          */
sendAccessibilityEvent(View host, int eventType)23404         public void sendAccessibilityEvent(View host, int eventType) {
23405             host.sendAccessibilityEventInternal(eventType);
23406         }
23407 
23408         /**
23409          * Performs the specified accessibility action on the view. For
23410          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23411          * <p>
23412          * The default implementation behaves as
23413          * {@link View#performAccessibilityAction(int, Bundle)
23414          *  View#performAccessibilityAction(int, Bundle)} for the case of
23415          *  no accessibility delegate been set.
23416          * </p>
23417          *
23418          * @param action The action to perform.
23419          * @return Whether the action was performed.
23420          *
23421          * @see View#performAccessibilityAction(int, Bundle)
23422          *      View#performAccessibilityAction(int, Bundle)
23423          */
performAccessibilityAction(View host, int action, Bundle args)23424         public boolean performAccessibilityAction(View host, int action, Bundle args) {
23425             return host.performAccessibilityActionInternal(action, args);
23426         }
23427 
23428         /**
23429          * Sends an accessibility event. This method behaves exactly as
23430          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23431          * empty {@link AccessibilityEvent} and does not perform a check whether
23432          * accessibility is enabled.
23433          * <p>
23434          * The default implementation behaves as
23435          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23436          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23437          * the case of no accessibility delegate been set.
23438          * </p>
23439          *
23440          * @param host The View hosting the delegate.
23441          * @param event The event to send.
23442          *
23443          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23444          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23445          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)23446         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23447             host.sendAccessibilityEventUncheckedInternal(event);
23448         }
23449 
23450         /**
23451          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23452          * to its children for adding their text content to the event.
23453          * <p>
23454          * The default implementation behaves as
23455          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23456          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23457          * the case of no accessibility delegate been set.
23458          * </p>
23459          *
23460          * @param host The View hosting the delegate.
23461          * @param event The event.
23462          * @return True if the event population was completed.
23463          *
23464          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23465          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23466          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)23467         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23468             return host.dispatchPopulateAccessibilityEventInternal(event);
23469         }
23470 
23471         /**
23472          * Gives a chance to the host View to populate the accessibility event with its
23473          * text content.
23474          * <p>
23475          * The default implementation behaves as
23476          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23477          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23478          * the case of no accessibility delegate been set.
23479          * </p>
23480          *
23481          * @param host The View hosting the delegate.
23482          * @param event The accessibility event which to populate.
23483          *
23484          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23485          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23486          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)23487         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23488             host.onPopulateAccessibilityEventInternal(event);
23489         }
23490 
23491         /**
23492          * Initializes an {@link AccessibilityEvent} with information about the
23493          * the host View which is the event source.
23494          * <p>
23495          * The default implementation behaves as
23496          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23497          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23498          * the case of no accessibility delegate been set.
23499          * </p>
23500          *
23501          * @param host The View hosting the delegate.
23502          * @param event The event to initialize.
23503          *
23504          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23505          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
23506          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)23507         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23508             host.onInitializeAccessibilityEventInternal(event);
23509         }
23510 
23511         /**
23512          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23513          * <p>
23514          * The default implementation behaves as
23515          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23516          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23517          * the case of no accessibility delegate been set.
23518          * </p>
23519          *
23520          * @param host The View hosting the delegate.
23521          * @param info The instance to initialize.
23522          *
23523          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23524          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23525          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)23526         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23527             host.onInitializeAccessibilityNodeInfoInternal(info);
23528         }
23529 
23530         /**
23531          * Called when a child of the host View has requested sending an
23532          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23533          * to augment the event.
23534          * <p>
23535          * The default implementation behaves as
23536          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23537          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23538          * the case of no accessibility delegate been set.
23539          * </p>
23540          *
23541          * @param host The View hosting the delegate.
23542          * @param child The child which requests sending the event.
23543          * @param event The event to be sent.
23544          * @return True if the event should be sent
23545          *
23546          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23547          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23548          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)23549         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23550                 AccessibilityEvent event) {
23551             return host.onRequestSendAccessibilityEventInternal(child, event);
23552         }
23553 
23554         /**
23555          * Gets the provider for managing a virtual view hierarchy rooted at this View
23556          * and reported to {@link android.accessibilityservice.AccessibilityService}s
23557          * that explore the window content.
23558          * <p>
23559          * The default implementation behaves as
23560          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23561          * the case of no accessibility delegate been set.
23562          * </p>
23563          *
23564          * @return The provider.
23565          *
23566          * @see AccessibilityNodeProvider
23567          */
getAccessibilityNodeProvider(View host)23568         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23569             return null;
23570         }
23571 
23572         /**
23573          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23574          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23575          * This method is responsible for obtaining an accessibility node info from a
23576          * pool of reusable instances and calling
23577          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23578          * view to initialize the former.
23579          * <p>
23580          * <strong>Note:</strong> The client is responsible for recycling the obtained
23581          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23582          * creation.
23583          * </p>
23584          * <p>
23585          * The default implementation behaves as
23586          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23587          * the case of no accessibility delegate been set.
23588          * </p>
23589          * @return A populated {@link AccessibilityNodeInfo}.
23590          *
23591          * @see AccessibilityNodeInfo
23592          *
23593          * @hide
23594          */
createAccessibilityNodeInfo(View host)23595         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23596             return host.createAccessibilityNodeInfoInternal();
23597         }
23598     }
23599 
23600     private class MatchIdPredicate implements Predicate<View> {
23601         public int mId;
23602 
23603         @Override
apply(View view)23604         public boolean apply(View view) {
23605             return (view.mID == mId);
23606         }
23607     }
23608 
23609     private class MatchLabelForPredicate implements Predicate<View> {
23610         private int mLabeledId;
23611 
23612         @Override
apply(View view)23613         public boolean apply(View view) {
23614             return (view.mLabelForId == mLabeledId);
23615         }
23616     }
23617 
23618     private class SendViewStateChangedAccessibilityEvent implements Runnable {
23619         private int mChangeTypes = 0;
23620         private boolean mPosted;
23621         private boolean mPostedWithDelay;
23622         private long mLastEventTimeMillis;
23623 
23624         @Override
run()23625         public void run() {
23626             mPosted = false;
23627             mPostedWithDelay = false;
23628             mLastEventTimeMillis = SystemClock.uptimeMillis();
23629             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23630                 final AccessibilityEvent event = AccessibilityEvent.obtain();
23631                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23632                 event.setContentChangeTypes(mChangeTypes);
23633                 sendAccessibilityEventUnchecked(event);
23634             }
23635             mChangeTypes = 0;
23636         }
23637 
runOrPost(int changeType)23638         public void runOrPost(int changeType) {
23639             mChangeTypes |= changeType;
23640 
23641             // If this is a live region or the child of a live region, collect
23642             // all events from this frame and send them on the next frame.
23643             if (inLiveRegion()) {
23644                 // If we're already posted with a delay, remove that.
23645                 if (mPostedWithDelay) {
23646                     removeCallbacks(this);
23647                     mPostedWithDelay = false;
23648                 }
23649                 // Only post if we're not already posted.
23650                 if (!mPosted) {
23651                     post(this);
23652                     mPosted = true;
23653                 }
23654                 return;
23655             }
23656 
23657             if (mPosted) {
23658                 return;
23659             }
23660 
23661             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23662             final long minEventIntevalMillis =
23663                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23664             if (timeSinceLastMillis >= minEventIntevalMillis) {
23665                 removeCallbacks(this);
23666                 run();
23667             } else {
23668                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23669                 mPostedWithDelay = true;
23670             }
23671         }
23672     }
23673 
inLiveRegion()23674     private boolean inLiveRegion() {
23675         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23676             return true;
23677         }
23678 
23679         ViewParent parent = getParent();
23680         while (parent instanceof View) {
23681             if (((View) parent).getAccessibilityLiveRegion()
23682                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23683                 return true;
23684             }
23685             parent = parent.getParent();
23686         }
23687 
23688         return false;
23689     }
23690 
23691     /**
23692      * Dump all private flags in readable format, useful for documentation and
23693      * sanity checking.
23694      */
dumpFlags()23695     private static void dumpFlags() {
23696         final HashMap<String, String> found = Maps.newHashMap();
23697         try {
23698             for (Field field : View.class.getDeclaredFields()) {
23699                 final int modifiers = field.getModifiers();
23700                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23701                     if (field.getType().equals(int.class)) {
23702                         final int value = field.getInt(null);
23703                         dumpFlag(found, field.getName(), value);
23704                     } else if (field.getType().equals(int[].class)) {
23705                         final int[] values = (int[]) field.get(null);
23706                         for (int i = 0; i < values.length; i++) {
23707                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23708                         }
23709                     }
23710                 }
23711             }
23712         } catch (IllegalAccessException e) {
23713             throw new RuntimeException(e);
23714         }
23715 
23716         final ArrayList<String> keys = Lists.newArrayList();
23717         keys.addAll(found.keySet());
23718         Collections.sort(keys);
23719         for (String key : keys) {
23720             Log.d(VIEW_LOG_TAG, found.get(key));
23721         }
23722     }
23723 
dumpFlag(HashMap<String, String> found, String name, int value)23724     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23725         // Sort flags by prefix, then by bits, always keeping unique keys
23726         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23727         final int prefix = name.indexOf('_');
23728         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23729         final String output = bits + " " + name;
23730         found.put(key, output);
23731     }
23732 
23733     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)23734     public void encode(@NonNull ViewHierarchyEncoder stream) {
23735         stream.beginObject(this);
23736         encodeProperties(stream);
23737         stream.endObject();
23738     }
23739 
23740     /** {@hide} */
23741     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)23742     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23743         Object resolveId = ViewDebug.resolveId(getContext(), mID);
23744         if (resolveId instanceof String) {
23745             stream.addProperty("id", (String) resolveId);
23746         } else {
23747             stream.addProperty("id", mID);
23748         }
23749 
23750         stream.addProperty("misc:transformation.alpha",
23751                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23752         stream.addProperty("misc:transitionName", getTransitionName());
23753 
23754         // layout
23755         stream.addProperty("layout:left", mLeft);
23756         stream.addProperty("layout:right", mRight);
23757         stream.addProperty("layout:top", mTop);
23758         stream.addProperty("layout:bottom", mBottom);
23759         stream.addProperty("layout:width", getWidth());
23760         stream.addProperty("layout:height", getHeight());
23761         stream.addProperty("layout:layoutDirection", getLayoutDirection());
23762         stream.addProperty("layout:layoutRtl", isLayoutRtl());
23763         stream.addProperty("layout:hasTransientState", hasTransientState());
23764         stream.addProperty("layout:baseline", getBaseline());
23765 
23766         // layout params
23767         ViewGroup.LayoutParams layoutParams = getLayoutParams();
23768         if (layoutParams != null) {
23769             stream.addPropertyKey("layoutParams");
23770             layoutParams.encode(stream);
23771         }
23772 
23773         // scrolling
23774         stream.addProperty("scrolling:scrollX", mScrollX);
23775         stream.addProperty("scrolling:scrollY", mScrollY);
23776 
23777         // padding
23778         stream.addProperty("padding:paddingLeft", mPaddingLeft);
23779         stream.addProperty("padding:paddingRight", mPaddingRight);
23780         stream.addProperty("padding:paddingTop", mPaddingTop);
23781         stream.addProperty("padding:paddingBottom", mPaddingBottom);
23782         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23783         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23784         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23785         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23786         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23787 
23788         // measurement
23789         stream.addProperty("measurement:minHeight", mMinHeight);
23790         stream.addProperty("measurement:minWidth", mMinWidth);
23791         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23792         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23793 
23794         // drawing
23795         stream.addProperty("drawing:elevation", getElevation());
23796         stream.addProperty("drawing:translationX", getTranslationX());
23797         stream.addProperty("drawing:translationY", getTranslationY());
23798         stream.addProperty("drawing:translationZ", getTranslationZ());
23799         stream.addProperty("drawing:rotation", getRotation());
23800         stream.addProperty("drawing:rotationX", getRotationX());
23801         stream.addProperty("drawing:rotationY", getRotationY());
23802         stream.addProperty("drawing:scaleX", getScaleX());
23803         stream.addProperty("drawing:scaleY", getScaleY());
23804         stream.addProperty("drawing:pivotX", getPivotX());
23805         stream.addProperty("drawing:pivotY", getPivotY());
23806         stream.addProperty("drawing:opaque", isOpaque());
23807         stream.addProperty("drawing:alpha", getAlpha());
23808         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23809         stream.addProperty("drawing:shadow", hasShadow());
23810         stream.addProperty("drawing:solidColor", getSolidColor());
23811         stream.addProperty("drawing:layerType", mLayerType);
23812         stream.addProperty("drawing:willNotDraw", willNotDraw());
23813         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23814         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23815         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23816         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23817 
23818         // focus
23819         stream.addProperty("focus:hasFocus", hasFocus());
23820         stream.addProperty("focus:isFocused", isFocused());
23821         stream.addProperty("focus:isFocusable", isFocusable());
23822         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23823 
23824         stream.addProperty("misc:clickable", isClickable());
23825         stream.addProperty("misc:pressed", isPressed());
23826         stream.addProperty("misc:selected", isSelected());
23827         stream.addProperty("misc:touchMode", isInTouchMode());
23828         stream.addProperty("misc:hovered", isHovered());
23829         stream.addProperty("misc:activated", isActivated());
23830 
23831         stream.addProperty("misc:visibility", getVisibility());
23832         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23833         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23834 
23835         stream.addProperty("misc:enabled", isEnabled());
23836         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23837         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23838 
23839         // theme attributes
23840         Resources.Theme theme = getContext().getTheme();
23841         if (theme != null) {
23842             stream.addPropertyKey("theme");
23843             theme.encode(stream);
23844         }
23845 
23846         // view attribute information
23847         int n = mAttributes != null ? mAttributes.length : 0;
23848         stream.addProperty("meta:__attrCount__", n/2);
23849         for (int i = 0; i < n; i += 2) {
23850             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23851         }
23852 
23853         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23854 
23855         // text
23856         stream.addProperty("text:textDirection", getTextDirection());
23857         stream.addProperty("text:textAlignment", getTextAlignment());
23858 
23859         // accessibility
23860         CharSequence contentDescription = getContentDescription();
23861         stream.addProperty("accessibility:contentDescription",
23862                 contentDescription == null ? "" : contentDescription.toString());
23863         stream.addProperty("accessibility:labelFor", getLabelFor());
23864         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23865     }
23866 
23867     /**
23868      * Determine if this view is rendered on a round wearable device and is the main view
23869      * on the screen.
23870      */
shouldDrawRoundScrollbar()23871     private boolean shouldDrawRoundScrollbar() {
23872         if (!mResources.getConfiguration().isScreenRound()) {
23873             return false;
23874         }
23875 
23876         final View rootView = getRootView();
23877         final WindowInsets insets = getRootWindowInsets();
23878 
23879         int height = getHeight();
23880         int width = getWidth();
23881         int displayHeight = rootView.getHeight();
23882         int displayWidth = rootView.getWidth();
23883 
23884         if (height != displayHeight || width != displayWidth) {
23885             return false;
23886         }
23887 
23888         getLocationOnScreen(mAttachInfo.mTmpLocation);
23889         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
23890                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
23891     }
23892 }
23893