1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import android.animation.AnimatorInflater;
20 import android.animation.StateListAnimator;
21 import android.annotation.CallSuper;
22 import android.annotation.ColorInt;
23 import android.annotation.DrawableRes;
24 import android.annotation.FloatRange;
25 import android.annotation.IdRes;
26 import android.annotation.IntDef;
27 import android.annotation.IntRange;
28 import android.annotation.LayoutRes;
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.annotation.Size;
32 import android.annotation.UiThread;
33 import android.content.ClipData;
34 import android.content.Context;
35 import android.content.ContextWrapper;
36 import android.content.Intent;
37 import android.content.res.ColorStateList;
38 import android.content.res.Configuration;
39 import android.content.res.Resources;
40 import android.content.res.TypedArray;
41 import android.graphics.Bitmap;
42 import android.graphics.Canvas;
43 import android.graphics.Insets;
44 import android.graphics.Interpolator;
45 import android.graphics.LinearGradient;
46 import android.graphics.Matrix;
47 import android.graphics.Outline;
48 import android.graphics.Paint;
49 import android.graphics.PixelFormat;
50 import android.graphics.Point;
51 import android.graphics.PorterDuff;
52 import android.graphics.PorterDuffXfermode;
53 import android.graphics.Rect;
54 import android.graphics.RectF;
55 import android.graphics.Region;
56 import android.graphics.Shader;
57 import android.graphics.drawable.ColorDrawable;
58 import android.graphics.drawable.Drawable;
59 import android.hardware.display.DisplayManagerGlobal;
60 import android.os.Build.VERSION_CODES;
61 import android.os.Bundle;
62 import android.os.Handler;
63 import android.os.IBinder;
64 import android.os.Parcel;
65 import android.os.Parcelable;
66 import android.os.RemoteException;
67 import android.os.SystemClock;
68 import android.os.SystemProperties;
69 import android.os.Trace;
70 import android.text.TextUtils;
71 import android.util.AttributeSet;
72 import android.util.FloatProperty;
73 import android.util.LayoutDirection;
74 import android.util.Log;
75 import android.util.LongSparseLongArray;
76 import android.util.Pools.SynchronizedPool;
77 import android.util.Property;
78 import android.util.SparseArray;
79 import android.util.StateSet;
80 import android.util.SuperNotCalledException;
81 import android.util.TypedValue;
82 import android.view.ContextMenu.ContextMenuInfo;
83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
85 import android.view.AccessibilityIterators.TextSegmentIterator;
86 import android.view.AccessibilityIterators.WordTextSegmentIterator;
87 import android.view.accessibility.AccessibilityEvent;
88 import android.view.accessibility.AccessibilityEventSource;
89 import android.view.accessibility.AccessibilityManager;
90 import android.view.accessibility.AccessibilityNodeInfo;
91 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
92 import android.view.accessibility.AccessibilityNodeProvider;
93 import android.view.animation.Animation;
94 import android.view.animation.AnimationUtils;
95 import android.view.animation.Transformation;
96 import android.view.inputmethod.EditorInfo;
97 import android.view.inputmethod.InputConnection;
98 import android.view.inputmethod.InputMethodManager;
99 import android.widget.Checkable;
100 import android.widget.FrameLayout;
101 import android.widget.ScrollBarDrawable;
102 import static android.os.Build.VERSION_CODES.*;
103 import static java.lang.Math.max;
104 
105 import com.android.internal.R;
106 import com.android.internal.util.Predicate;
107 import com.android.internal.view.menu.MenuBuilder;
108 import com.android.internal.widget.ScrollBarUtils;
109 import com.google.android.collect.Lists;
110 import com.google.android.collect.Maps;
111 
112 import java.lang.NullPointerException;
113 import java.lang.annotation.Retention;
114 import java.lang.annotation.RetentionPolicy;
115 import java.lang.ref.WeakReference;
116 import java.lang.reflect.Field;
117 import java.lang.reflect.InvocationTargetException;
118 import java.lang.reflect.Method;
119 import java.lang.reflect.Modifier;
120 import java.util.ArrayList;
121 import java.util.Arrays;
122 import java.util.Collections;
123 import java.util.HashMap;
124 import java.util.List;
125 import java.util.Locale;
126 import java.util.Map;
127 import java.util.concurrent.CopyOnWriteArrayList;
128 import java.util.concurrent.atomic.AtomicInteger;
129 
130 /**
131  * <p>
132  * This class represents the basic building block for user interface components. A View
133  * occupies a rectangular area on the screen and is responsible for drawing and
134  * event handling. View is the base class for <em>widgets</em>, which are
135  * used to create interactive UI components (buttons, text fields, etc.). The
136  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
137  * are invisible containers that hold other Views (or other ViewGroups) and define
138  * their layout properties.
139  * </p>
140  *
141  * <div class="special reference">
142  * <h3>Developer Guides</h3>
143  * <p>For information about using this class to develop your application's user interface,
144  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
145  * </div>
146  *
147  * <a name="Using"></a>
148  * <h3>Using Views</h3>
149  * <p>
150  * All of the views in a window are arranged in a single tree. You can add views
151  * either from code or by specifying a tree of views in one or more XML layout
152  * files. There are many specialized subclasses of views that act as controls or
153  * are capable of displaying text, images, or other content.
154  * </p>
155  * <p>
156  * Once you have created a tree of views, there are typically a few types of
157  * common operations you may wish to perform:
158  * <ul>
159  * <li><strong>Set properties:</strong> for example setting the text of a
160  * {@link android.widget.TextView}. The available properties and the methods
161  * that set them will vary among the different subclasses of views. Note that
162  * properties that are known at build time can be set in the XML layout
163  * files.</li>
164  * <li><strong>Set focus:</strong> The framework will handle moving focus in
165  * response to user input. To force focus to a specific view, call
166  * {@link #requestFocus}.</li>
167  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
168  * that will be notified when something interesting happens to the view. For
169  * example, all views will let you set a listener to be notified when the view
170  * gains or loses focus. You can register such a listener using
171  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
172  * Other view subclasses offer more specialized listeners. For example, a Button
173  * exposes a listener to notify clients when the button is clicked.</li>
174  * <li><strong>Set visibility:</strong> You can hide or show views using
175  * {@link #setVisibility(int)}.</li>
176  * </ul>
177  * </p>
178  * <p><em>
179  * Note: The Android framework is responsible for measuring, laying out and
180  * drawing views. You should not call methods that perform these actions on
181  * views yourself unless you are actually implementing a
182  * {@link android.view.ViewGroup}.
183  * </em></p>
184  *
185  * <a name="Lifecycle"></a>
186  * <h3>Implementing a Custom View</h3>
187  *
188  * <p>
189  * To implement a custom view, you will usually begin by providing overrides for
190  * some of the standard methods that the framework calls on all views. You do
191  * not need to override all of these methods. In fact, you can start by just
192  * overriding {@link #onDraw(android.graphics.Canvas)}.
193  * <table border="2" width="85%" align="center" cellpadding="5">
194  *     <thead>
195  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
196  *     </thead>
197  *
198  *     <tbody>
199  *     <tr>
200  *         <td rowspan="2">Creation</td>
201  *         <td>Constructors</td>
202  *         <td>There is a form of the constructor that are called when the view
203  *         is created from code and a form that is called when the view is
204  *         inflated from a layout file. The second form should parse and apply
205  *         any attributes defined in the layout file.
206  *         </td>
207  *     </tr>
208  *     <tr>
209  *         <td><code>{@link #onFinishInflate()}</code></td>
210  *         <td>Called after a view and all of its children has been inflated
211  *         from XML.</td>
212  *     </tr>
213  *
214  *     <tr>
215  *         <td rowspan="3">Layout</td>
216  *         <td><code>{@link #onMeasure(int, int)}</code></td>
217  *         <td>Called to determine the size requirements for this view and all
218  *         of its children.
219  *         </td>
220  *     </tr>
221  *     <tr>
222  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
223  *         <td>Called when this view should assign a size and position to all
224  *         of its children.
225  *         </td>
226  *     </tr>
227  *     <tr>
228  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
229  *         <td>Called when the size of this view has changed.
230  *         </td>
231  *     </tr>
232  *
233  *     <tr>
234  *         <td>Drawing</td>
235  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
236  *         <td>Called when the view should render its content.
237  *         </td>
238  *     </tr>
239  *
240  *     <tr>
241  *         <td rowspan="4">Event processing</td>
242  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
243  *         <td>Called when a new hardware key event occurs.
244  *         </td>
245  *     </tr>
246  *     <tr>
247  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
248  *         <td>Called when a hardware key up event occurs.
249  *         </td>
250  *     </tr>
251  *     <tr>
252  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
253  *         <td>Called when a trackball motion event occurs.
254  *         </td>
255  *     </tr>
256  *     <tr>
257  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
258  *         <td>Called when a touch screen motion event occurs.
259  *         </td>
260  *     </tr>
261  *
262  *     <tr>
263  *         <td rowspan="2">Focus</td>
264  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
265  *         <td>Called when the view gains or loses focus.
266  *         </td>
267  *     </tr>
268  *
269  *     <tr>
270  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
271  *         <td>Called when the window containing the view gains or loses focus.
272  *         </td>
273  *     </tr>
274  *
275  *     <tr>
276  *         <td rowspan="3">Attaching</td>
277  *         <td><code>{@link #onAttachedToWindow()}</code></td>
278  *         <td>Called when the view is attached to a window.
279  *         </td>
280  *     </tr>
281  *
282  *     <tr>
283  *         <td><code>{@link #onDetachedFromWindow}</code></td>
284  *         <td>Called when the view is detached from its window.
285  *         </td>
286  *     </tr>
287  *
288  *     <tr>
289  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
290  *         <td>Called when the visibility of the window containing the view
291  *         has changed.
292  *         </td>
293  *     </tr>
294  *     </tbody>
295  *
296  * </table>
297  * </p>
298  *
299  * <a name="IDs"></a>
300  * <h3>IDs</h3>
301  * Views may have an integer id associated with them. These ids are typically
302  * assigned in the layout XML files, and are used to find specific views within
303  * the view tree. A common pattern is to:
304  * <ul>
305  * <li>Define a Button in the layout file and assign it a unique ID.
306  * <pre>
307  * &lt;Button
308  *     android:id="@+id/my_button"
309  *     android:layout_width="wrap_content"
310  *     android:layout_height="wrap_content"
311  *     android:text="@string/my_button_text"/&gt;
312  * </pre></li>
313  * <li>From the onCreate method of an Activity, find the Button
314  * <pre class="prettyprint">
315  *      Button myButton = (Button) findViewById(R.id.my_button);
316  * </pre></li>
317  * </ul>
318  * <p>
319  * View IDs need not be unique throughout the tree, but it is good practice to
320  * ensure that they are at least unique within the part of the tree you are
321  * searching.
322  * </p>
323  *
324  * <a name="Position"></a>
325  * <h3>Position</h3>
326  * <p>
327  * The geometry of a view is that of a rectangle. A view has a location,
328  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
329  * two dimensions, expressed as a width and a height. The unit for location
330  * and dimensions is the pixel.
331  * </p>
332  *
333  * <p>
334  * It is possible to retrieve the location of a view by invoking the methods
335  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
336  * coordinate of the rectangle representing the view. The latter returns the
337  * top, or Y, coordinate of the rectangle representing the view. These methods
338  * both return the location of the view relative to its parent. For instance,
339  * when getLeft() returns 20, that means the view is located 20 pixels to the
340  * right of the left edge of its direct parent.
341  * </p>
342  *
343  * <p>
344  * In addition, several convenience methods are offered to avoid unnecessary
345  * computations, namely {@link #getRight()} and {@link #getBottom()}.
346  * These methods return the coordinates of the right and bottom edges of the
347  * rectangle representing the view. For instance, calling {@link #getRight()}
348  * is similar to the following computation: <code>getLeft() + getWidth()</code>
349  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
350  * </p>
351  *
352  * <a name="SizePaddingMargins"></a>
353  * <h3>Size, padding and margins</h3>
354  * <p>
355  * The size of a view is expressed with a width and a height. A view actually
356  * possess two pairs of width and height values.
357  * </p>
358  *
359  * <p>
360  * The first pair is known as <em>measured width</em> and
361  * <em>measured height</em>. These dimensions define how big a view wants to be
362  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
363  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
364  * and {@link #getMeasuredHeight()}.
365  * </p>
366  *
367  * <p>
368  * The second pair is simply known as <em>width</em> and <em>height</em>, or
369  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
370  * dimensions define the actual size of the view on screen, at drawing time and
371  * after layout. These values may, but do not have to, be different from the
372  * measured width and height. The width and height can be obtained by calling
373  * {@link #getWidth()} and {@link #getHeight()}.
374  * </p>
375  *
376  * <p>
377  * To measure its dimensions, a view takes into account its padding. The padding
378  * is expressed in pixels for the left, top, right and bottom parts of the view.
379  * Padding can be used to offset the content of the view by a specific amount of
380  * pixels. For instance, a left padding of 2 will push the view's content by
381  * 2 pixels to the right of the left edge. Padding can be set using the
382  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
383  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
384  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
385  * {@link #getPaddingEnd()}.
386  * </p>
387  *
388  * <p>
389  * Even though a view can define a padding, it does not provide any support for
390  * margins. However, view groups provide such a support. Refer to
391  * {@link android.view.ViewGroup} and
392  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
393  * </p>
394  *
395  * <a name="Layout"></a>
396  * <h3>Layout</h3>
397  * <p>
398  * Layout is a two pass process: a measure pass and a layout pass. The measuring
399  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
400  * of the view tree. Each view pushes dimension specifications down the tree
401  * during the recursion. At the end of the measure pass, every view has stored
402  * its measurements. The second pass happens in
403  * {@link #layout(int,int,int,int)} and is also top-down. During
404  * this pass each parent is responsible for positioning all of its children
405  * using the sizes computed in the measure pass.
406  * </p>
407  *
408  * <p>
409  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
410  * {@link #getMeasuredHeight()} values must be set, along with those for all of
411  * that view's descendants. A view's measured width and measured height values
412  * must respect the constraints imposed by the view's parents. This guarantees
413  * that at the end of the measure pass, all parents accept all of their
414  * children's measurements. A parent view may call measure() more than once on
415  * its children. For example, the parent may measure each child once with
416  * unspecified dimensions to find out how big they want to be, then call
417  * measure() on them again with actual numbers if the sum of all the children's
418  * unconstrained sizes is too big or too small.
419  * </p>
420  *
421  * <p>
422  * The measure pass uses two classes to communicate dimensions. The
423  * {@link MeasureSpec} class is used by views to tell their parents how they
424  * want to be measured and positioned. The base LayoutParams class just
425  * describes how big the view wants to be for both width and height. For each
426  * dimension, it can specify one of:
427  * <ul>
428  * <li> an exact number
429  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
430  * (minus padding)
431  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
432  * enclose its content (plus padding).
433  * </ul>
434  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
435  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
436  * an X and Y value.
437  * </p>
438  *
439  * <p>
440  * MeasureSpecs are used to push requirements down the tree from parent to
441  * child. A MeasureSpec can be in one of three modes:
442  * <ul>
443  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
444  * of a child view. For example, a LinearLayout may call measure() on its child
445  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
446  * tall the child view wants to be given a width of 240 pixels.
447  * <li>EXACTLY: This is used by the parent to impose an exact size on the
448  * child. The child must use this size, and guarantee that all of its
449  * descendants will fit within this size.
450  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
451  * child. The child must guarantee that it and all of its descendants will fit
452  * within this size.
453  * </ul>
454  * </p>
455  *
456  * <p>
457  * To initiate a layout, call {@link #requestLayout}. This method is typically
458  * called by a view on itself when it believes that is can no longer fit within
459  * its current bounds.
460  * </p>
461  *
462  * <a name="Drawing"></a>
463  * <h3>Drawing</h3>
464  * <p>
465  * Drawing is handled by walking the tree and recording the drawing commands of
466  * any View that needs to update. After this, the drawing commands of the
467  * entire tree are issued to screen, clipped to the newly damaged area.
468  * </p>
469  *
470  * <p>
471  * The tree is largely recorded and drawn in order, with parents drawn before
472  * (i.e., behind) their children, with siblings drawn in the order they appear
473  * in the tree. If you set a background drawable for a View, then the View will
474  * draw it before calling back to its <code>onDraw()</code> method. The child
475  * drawing order can be overridden with
476  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
477  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
478  * </p>
479  *
480  * <p>
481  * To force a view to draw, call {@link #invalidate()}.
482  * </p>
483  *
484  * <a name="EventHandlingThreading"></a>
485  * <h3>Event Handling and Threading</h3>
486  * <p>
487  * The basic cycle of a view is as follows:
488  * <ol>
489  * <li>An event comes in and is dispatched to the appropriate view. The view
490  * handles the event and notifies any listeners.</li>
491  * <li>If in the course of processing the event, the view's bounds may need
492  * to be changed, the view will call {@link #requestLayout()}.</li>
493  * <li>Similarly, if in the course of processing the event the view's appearance
494  * may need to be changed, the view will call {@link #invalidate()}.</li>
495  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
496  * the framework will take care of measuring, laying out, and drawing the tree
497  * as appropriate.</li>
498  * </ol>
499  * </p>
500  *
501  * <p><em>Note: The entire view tree is single threaded. You must always be on
502  * the UI thread when calling any method on any view.</em>
503  * If you are doing work on other threads and want to update the state of a view
504  * from that thread, you should use a {@link Handler}.
505  * </p>
506  *
507  * <a name="FocusHandling"></a>
508  * <h3>Focus Handling</h3>
509  * <p>
510  * The framework will handle routine focus movement in response to user input.
511  * This includes changing the focus as views are removed or hidden, or as new
512  * views become available. Views indicate their willingness to take focus
513  * through the {@link #isFocusable} method. To change whether a view can take
514  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
515  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
516  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
517  * </p>
518  * <p>
519  * Focus movement is based on an algorithm which finds the nearest neighbor in a
520  * given direction. In rare cases, the default algorithm may not match the
521  * intended behavior of the developer. In these situations, you can provide
522  * explicit overrides by using these XML attributes in the layout file:
523  * <pre>
524  * nextFocusDown
525  * nextFocusLeft
526  * nextFocusRight
527  * nextFocusUp
528  * </pre>
529  * </p>
530  *
531  *
532  * <p>
533  * To get a particular view to take focus, call {@link #requestFocus()}.
534  * </p>
535  *
536  * <a name="TouchMode"></a>
537  * <h3>Touch Mode</h3>
538  * <p>
539  * When a user is navigating a user interface via directional keys such as a D-pad, it is
540  * necessary to give focus to actionable items such as buttons so the user can see
541  * what will take input.  If the device has touch capabilities, however, and the user
542  * begins interacting with the interface by touching it, it is no longer necessary to
543  * always highlight, or give focus to, a particular view.  This motivates a mode
544  * for interaction named 'touch mode'.
545  * </p>
546  * <p>
547  * For a touch capable device, once the user touches the screen, the device
548  * will enter touch mode.  From this point onward, only views for which
549  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
550  * Other views that are touchable, like buttons, will not take focus when touched; they will
551  * only fire the on click listeners.
552  * </p>
553  * <p>
554  * Any time a user hits a directional key, such as a D-pad direction, the view device will
555  * exit touch mode, and find a view to take focus, so that the user may resume interacting
556  * with the user interface without touching the screen again.
557  * </p>
558  * <p>
559  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
560  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
561  * </p>
562  *
563  * <a name="Scrolling"></a>
564  * <h3>Scrolling</h3>
565  * <p>
566  * The framework provides basic support for views that wish to internally
567  * scroll their content. This includes keeping track of the X and Y scroll
568  * offset as well as mechanisms for drawing scrollbars. See
569  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
570  * {@link #awakenScrollBars()} for more details.
571  * </p>
572  *
573  * <a name="Tags"></a>
574  * <h3>Tags</h3>
575  * <p>
576  * Unlike IDs, tags are not used to identify views. Tags are essentially an
577  * extra piece of information that can be associated with a view. They are most
578  * often used as a convenience to store data related to views in the views
579  * themselves rather than by putting them in a separate structure.
580  * </p>
581  * <p>
582  * Tags may be specified with character sequence values in layout XML as either
583  * a single tag using the {@link android.R.styleable#View_tag android:tag}
584  * attribute or multiple tags using the {@code <tag>} child element:
585  * <pre>
586  *     &ltView ...
587  *           android:tag="@string/mytag_value" /&gt;
588  *     &ltView ...&gt;
589  *         &lttag android:id="@+id/mytag"
590  *              android:value="@string/mytag_value" /&gt;
591  *     &lt/View>
592  * </pre>
593  * </p>
594  * <p>
595  * Tags may also be specified with arbitrary objects from code using
596  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
597  * </p>
598  *
599  * <a name="Themes"></a>
600  * <h3>Themes</h3>
601  * <p>
602  * By default, Views are created using the theme of the Context object supplied
603  * to their constructor; however, a different theme may be specified by using
604  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
605  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
606  * code.
607  * </p>
608  * <p>
609  * When the {@link android.R.styleable#View_theme android:theme} attribute is
610  * used in XML, the specified theme is applied on top of the inflation
611  * context's theme (see {@link LayoutInflater}) and used for the view itself as
612  * well as any child elements.
613  * </p>
614  * <p>
615  * In the following example, both views will be created using the Material dark
616  * color scheme; however, because an overlay theme is used which only defines a
617  * subset of attributes, the value of
618  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
619  * the inflation context's theme (e.g. the Activity theme) will be preserved.
620  * <pre>
621  *     &ltLinearLayout
622  *             ...
623  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
624  *         &ltView ...&gt;
625  *     &lt/LinearLayout&gt;
626  * </pre>
627  * </p>
628  *
629  * <a name="Properties"></a>
630  * <h3>Properties</h3>
631  * <p>
632  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
633  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
634  * available both in the {@link Property} form as well as in similarly-named setter/getter
635  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
636  * be used to set persistent state associated with these rendering-related properties on the view.
637  * The properties and methods can also be used in conjunction with
638  * {@link android.animation.Animator Animator}-based animations, described more in the
639  * <a href="#Animation">Animation</a> section.
640  * </p>
641  *
642  * <a name="Animation"></a>
643  * <h3>Animation</h3>
644  * <p>
645  * Starting with Android 3.0, the preferred way of animating views is to use the
646  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
647  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
648  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
649  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
650  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
651  * makes animating these View properties particularly easy and efficient.
652  * </p>
653  * <p>
654  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
655  * You can attach an {@link Animation} object to a view using
656  * {@link #setAnimation(Animation)} or
657  * {@link #startAnimation(Animation)}. The animation can alter the scale,
658  * rotation, translation and alpha of a view over time. If the animation is
659  * attached to a view that has children, the animation will affect the entire
660  * subtree rooted by that node. When an animation is started, the framework will
661  * take care of redrawing the appropriate views until the animation completes.
662  * </p>
663  *
664  * <a name="Security"></a>
665  * <h3>Security</h3>
666  * <p>
667  * Sometimes it is essential that an application be able to verify that an action
668  * is being performed with the full knowledge and consent of the user, such as
669  * granting a permission request, making a purchase or clicking on an advertisement.
670  * Unfortunately, a malicious application could try to spoof the user into
671  * performing these actions, unaware, by concealing the intended purpose of the view.
672  * As a remedy, the framework offers a touch filtering mechanism that can be used to
673  * improve the security of views that provide access to sensitive functionality.
674  * </p><p>
675  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
676  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
677  * will discard touches that are received whenever the view's window is obscured by
678  * another visible window.  As a result, the view will not receive touches whenever a
679  * toast, dialog or other window appears above the view's window.
680  * </p><p>
681  * For more fine-grained control over security, consider overriding the
682  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
683  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
684  * </p>
685  *
686  * @attr ref android.R.styleable#View_alpha
687  * @attr ref android.R.styleable#View_background
688  * @attr ref android.R.styleable#View_clickable
689  * @attr ref android.R.styleable#View_contentDescription
690  * @attr ref android.R.styleable#View_drawingCacheQuality
691  * @attr ref android.R.styleable#View_duplicateParentState
692  * @attr ref android.R.styleable#View_id
693  * @attr ref android.R.styleable#View_requiresFadingEdge
694  * @attr ref android.R.styleable#View_fadeScrollbars
695  * @attr ref android.R.styleable#View_fadingEdgeLength
696  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
697  * @attr ref android.R.styleable#View_fitsSystemWindows
698  * @attr ref android.R.styleable#View_isScrollContainer
699  * @attr ref android.R.styleable#View_focusable
700  * @attr ref android.R.styleable#View_focusableInTouchMode
701  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
702  * @attr ref android.R.styleable#View_keepScreenOn
703  * @attr ref android.R.styleable#View_layerType
704  * @attr ref android.R.styleable#View_layoutDirection
705  * @attr ref android.R.styleable#View_longClickable
706  * @attr ref android.R.styleable#View_minHeight
707  * @attr ref android.R.styleable#View_minWidth
708  * @attr ref android.R.styleable#View_nextFocusDown
709  * @attr ref android.R.styleable#View_nextFocusLeft
710  * @attr ref android.R.styleable#View_nextFocusRight
711  * @attr ref android.R.styleable#View_nextFocusUp
712  * @attr ref android.R.styleable#View_onClick
713  * @attr ref android.R.styleable#View_padding
714  * @attr ref android.R.styleable#View_paddingBottom
715  * @attr ref android.R.styleable#View_paddingLeft
716  * @attr ref android.R.styleable#View_paddingRight
717  * @attr ref android.R.styleable#View_paddingTop
718  * @attr ref android.R.styleable#View_paddingStart
719  * @attr ref android.R.styleable#View_paddingEnd
720  * @attr ref android.R.styleable#View_saveEnabled
721  * @attr ref android.R.styleable#View_rotation
722  * @attr ref android.R.styleable#View_rotationX
723  * @attr ref android.R.styleable#View_rotationY
724  * @attr ref android.R.styleable#View_scaleX
725  * @attr ref android.R.styleable#View_scaleY
726  * @attr ref android.R.styleable#View_scrollX
727  * @attr ref android.R.styleable#View_scrollY
728  * @attr ref android.R.styleable#View_scrollbarSize
729  * @attr ref android.R.styleable#View_scrollbarStyle
730  * @attr ref android.R.styleable#View_scrollbars
731  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
732  * @attr ref android.R.styleable#View_scrollbarFadeDuration
733  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
734  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
735  * @attr ref android.R.styleable#View_scrollbarThumbVertical
736  * @attr ref android.R.styleable#View_scrollbarTrackVertical
737  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
738  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
739  * @attr ref android.R.styleable#View_stateListAnimator
740  * @attr ref android.R.styleable#View_transitionName
741  * @attr ref android.R.styleable#View_soundEffectsEnabled
742  * @attr ref android.R.styleable#View_tag
743  * @attr ref android.R.styleable#View_textAlignment
744  * @attr ref android.R.styleable#View_textDirection
745  * @attr ref android.R.styleable#View_transformPivotX
746  * @attr ref android.R.styleable#View_transformPivotY
747  * @attr ref android.R.styleable#View_translationX
748  * @attr ref android.R.styleable#View_translationY
749  * @attr ref android.R.styleable#View_translationZ
750  * @attr ref android.R.styleable#View_visibility
751  * @attr ref android.R.styleable#View_theme
752  *
753  * @see android.view.ViewGroup
754  */
755 @UiThread
756 public class View implements Drawable.Callback, KeyEvent.Callback,
757         AccessibilityEventSource {
758     private static final boolean DBG = false;
759 
760     /**
761      * The logging tag used by this class with android.util.Log.
762      */
763     protected static final String VIEW_LOG_TAG = "View";
764 
765     /**
766      * When set to true, apps will draw debugging information about their layouts.
767      *
768      * @hide
769      */
770     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
771 
772     /**
773      * When set to true, this view will save its attribute data.
774      *
775      * @hide
776      */
777     public static boolean mDebugViewAttributes = false;
778 
779     /**
780      * Used to mark a View that has no ID.
781      */
782     public static final int NO_ID = -1;
783 
784     /**
785      * Signals that compatibility booleans have been initialized according to
786      * target SDK versions.
787      */
788     private static boolean sCompatibilityDone = false;
789 
790     /**
791      * Use the old (broken) way of building MeasureSpecs.
792      */
793     private static boolean sUseBrokenMakeMeasureSpec = false;
794 
795     /**
796      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
797      */
798     static boolean sUseZeroUnspecifiedMeasureSpec = false;
799 
800     /**
801      * Ignore any optimizations using the measure cache.
802      */
803     private static boolean sIgnoreMeasureCache = false;
804 
805     /**
806      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
807      */
808     private static boolean sAlwaysRemeasureExactly = false;
809 
810     /**
811      * Relax constraints around whether setLayoutParams() must be called after
812      * modifying the layout params.
813      */
814     private static boolean sLayoutParamsAlwaysChanged = false;
815 
816     /**
817      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
818      * without throwing
819      */
820     static boolean sTextureViewIgnoresDrawableSetters = false;
821 
822     /**
823      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
824      * calling setFlags.
825      */
826     private static final int NOT_FOCUSABLE = 0x00000000;
827 
828     /**
829      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
830      * setFlags.
831      */
832     private static final int FOCUSABLE = 0x00000001;
833 
834     /**
835      * Mask for use with setFlags indicating bits used for focus.
836      */
837     private static final int FOCUSABLE_MASK = 0x00000001;
838 
839     /**
840      * This view will adjust its padding to fit sytem windows (e.g. status bar)
841      */
842     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
843 
844     /** @hide */
845     @IntDef({VISIBLE, INVISIBLE, GONE})
846     @Retention(RetentionPolicy.SOURCE)
847     public @interface Visibility {}
848 
849     /**
850      * This view is visible.
851      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
852      * android:visibility}.
853      */
854     public static final int VISIBLE = 0x00000000;
855 
856     /**
857      * This view is invisible, but it still takes up space for layout purposes.
858      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
859      * android:visibility}.
860      */
861     public static final int INVISIBLE = 0x00000004;
862 
863     /**
864      * This view is invisible, and it doesn't take any space for layout
865      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
866      * android:visibility}.
867      */
868     public static final int GONE = 0x00000008;
869 
870     /**
871      * Mask for use with setFlags indicating bits used for visibility.
872      * {@hide}
873      */
874     static final int VISIBILITY_MASK = 0x0000000C;
875 
876     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
877 
878     /**
879      * This view is enabled. Interpretation varies by subclass.
880      * Use with ENABLED_MASK when calling setFlags.
881      * {@hide}
882      */
883     static final int ENABLED = 0x00000000;
884 
885     /**
886      * This view is disabled. Interpretation varies by subclass.
887      * Use with ENABLED_MASK when calling setFlags.
888      * {@hide}
889      */
890     static final int DISABLED = 0x00000020;
891 
892    /**
893     * Mask for use with setFlags indicating bits used for indicating whether
894     * this view is enabled
895     * {@hide}
896     */
897     static final int ENABLED_MASK = 0x00000020;
898 
899     /**
900      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
901      * called and further optimizations will be performed. It is okay to have
902      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
903      * {@hide}
904      */
905     static final int WILL_NOT_DRAW = 0x00000080;
906 
907     /**
908      * Mask for use with setFlags indicating bits used for indicating whether
909      * this view is will draw
910      * {@hide}
911      */
912     static final int DRAW_MASK = 0x00000080;
913 
914     /**
915      * <p>This view doesn't show scrollbars.</p>
916      * {@hide}
917      */
918     static final int SCROLLBARS_NONE = 0x00000000;
919 
920     /**
921      * <p>This view shows horizontal scrollbars.</p>
922      * {@hide}
923      */
924     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
925 
926     /**
927      * <p>This view shows vertical scrollbars.</p>
928      * {@hide}
929      */
930     static final int SCROLLBARS_VERTICAL = 0x00000200;
931 
932     /**
933      * <p>Mask for use with setFlags indicating bits used for indicating which
934      * scrollbars are enabled.</p>
935      * {@hide}
936      */
937     static final int SCROLLBARS_MASK = 0x00000300;
938 
939     /**
940      * Indicates that the view should filter touches when its window is obscured.
941      * Refer to the class comments for more information about this security feature.
942      * {@hide}
943      */
944     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
945 
946     /**
947      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
948      * that they are optional and should be skipped if the window has
949      * requested system UI flags that ignore those insets for layout.
950      */
951     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
952 
953     /**
954      * <p>This view doesn't show fading edges.</p>
955      * {@hide}
956      */
957     static final int FADING_EDGE_NONE = 0x00000000;
958 
959     /**
960      * <p>This view shows horizontal fading edges.</p>
961      * {@hide}
962      */
963     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
964 
965     /**
966      * <p>This view shows vertical fading edges.</p>
967      * {@hide}
968      */
969     static final int FADING_EDGE_VERTICAL = 0x00002000;
970 
971     /**
972      * <p>Mask for use with setFlags indicating bits used for indicating which
973      * fading edges are enabled.</p>
974      * {@hide}
975      */
976     static final int FADING_EDGE_MASK = 0x00003000;
977 
978     /**
979      * <p>Indicates this view can be clicked. When clickable, a View reacts
980      * to clicks by notifying the OnClickListener.<p>
981      * {@hide}
982      */
983     static final int CLICKABLE = 0x00004000;
984 
985     /**
986      * <p>Indicates this view is caching its drawing into a bitmap.</p>
987      * {@hide}
988      */
989     static final int DRAWING_CACHE_ENABLED = 0x00008000;
990 
991     /**
992      * <p>Indicates that no icicle should be saved for this view.<p>
993      * {@hide}
994      */
995     static final int SAVE_DISABLED = 0x000010000;
996 
997     /**
998      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
999      * property.</p>
1000      * {@hide}
1001      */
1002     static final int SAVE_DISABLED_MASK = 0x000010000;
1003 
1004     /**
1005      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1006      * {@hide}
1007      */
1008     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1009 
1010     /**
1011      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1012      * {@hide}
1013      */
1014     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1015 
1016     /** @hide */
1017     @Retention(RetentionPolicy.SOURCE)
1018     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1019     public @interface DrawingCacheQuality {}
1020 
1021     /**
1022      * <p>Enables low quality mode for the drawing cache.</p>
1023      */
1024     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1025 
1026     /**
1027      * <p>Enables high quality mode for the drawing cache.</p>
1028      */
1029     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1030 
1031     /**
1032      * <p>Enables automatic quality mode for the drawing cache.</p>
1033      */
1034     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1035 
1036     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1037             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1038     };
1039 
1040     /**
1041      * <p>Mask for use with setFlags indicating bits used for the cache
1042      * quality property.</p>
1043      * {@hide}
1044      */
1045     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1046 
1047     /**
1048      * <p>
1049      * Indicates this view can be long clicked. When long clickable, a View
1050      * reacts to long clicks by notifying the OnLongClickListener or showing a
1051      * context menu.
1052      * </p>
1053      * {@hide}
1054      */
1055     static final int LONG_CLICKABLE = 0x00200000;
1056 
1057     /**
1058      * <p>Indicates that this view gets its drawable states from its direct parent
1059      * and ignores its original internal states.</p>
1060      *
1061      * @hide
1062      */
1063     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1064 
1065     /**
1066      * <p>
1067      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1068      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1069      * OnContextClickListener.
1070      * </p>
1071      * {@hide}
1072      */
1073     static final int CONTEXT_CLICKABLE = 0x00800000;
1074 
1075 
1076     /** @hide */
1077     @IntDef({
1078         SCROLLBARS_INSIDE_OVERLAY,
1079         SCROLLBARS_INSIDE_INSET,
1080         SCROLLBARS_OUTSIDE_OVERLAY,
1081         SCROLLBARS_OUTSIDE_INSET
1082     })
1083     @Retention(RetentionPolicy.SOURCE)
1084     public @interface ScrollBarStyle {}
1085 
1086     /**
1087      * The scrollbar style to display the scrollbars inside the content area,
1088      * without increasing the padding. The scrollbars will be overlaid with
1089      * translucency on the view's content.
1090      */
1091     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1092 
1093     /**
1094      * The scrollbar style to display the scrollbars inside the padded area,
1095      * increasing the padding of the view. The scrollbars will not overlap the
1096      * content area of the view.
1097      */
1098     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1099 
1100     /**
1101      * The scrollbar style to display the scrollbars at the edge of the view,
1102      * without increasing the padding. The scrollbars will be overlaid with
1103      * translucency.
1104      */
1105     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1106 
1107     /**
1108      * The scrollbar style to display the scrollbars at the edge of the view,
1109      * increasing the padding of the view. The scrollbars will only overlap the
1110      * background, if any.
1111      */
1112     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1113 
1114     /**
1115      * Mask to check if the scrollbar style is overlay or inset.
1116      * {@hide}
1117      */
1118     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1119 
1120     /**
1121      * Mask to check if the scrollbar style is inside or outside.
1122      * {@hide}
1123      */
1124     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1125 
1126     /**
1127      * Mask for scrollbar style.
1128      * {@hide}
1129      */
1130     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1131 
1132     /**
1133      * View flag indicating that the screen should remain on while the
1134      * window containing this view is visible to the user.  This effectively
1135      * takes care of automatically setting the WindowManager's
1136      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1137      */
1138     public static final int KEEP_SCREEN_ON = 0x04000000;
1139 
1140     /**
1141      * View flag indicating whether this view should have sound effects enabled
1142      * for events such as clicking and touching.
1143      */
1144     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1145 
1146     /**
1147      * View flag indicating whether this view should have haptic feedback
1148      * enabled for events such as long presses.
1149      */
1150     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1151 
1152     /**
1153      * <p>Indicates that the view hierarchy should stop saving state when
1154      * it reaches this view.  If state saving is initiated immediately at
1155      * the view, it will be allowed.
1156      * {@hide}
1157      */
1158     static final int PARENT_SAVE_DISABLED = 0x20000000;
1159 
1160     /**
1161      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1162      * {@hide}
1163      */
1164     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1165 
1166     /** @hide */
1167     @IntDef(flag = true,
1168             value = {
1169                 FOCUSABLES_ALL,
1170                 FOCUSABLES_TOUCH_MODE
1171             })
1172     @Retention(RetentionPolicy.SOURCE)
1173     public @interface FocusableMode {}
1174 
1175     /**
1176      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1177      * should add all focusable Views regardless if they are focusable in touch mode.
1178      */
1179     public static final int FOCUSABLES_ALL = 0x00000000;
1180 
1181     /**
1182      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1183      * should add only Views focusable in touch mode.
1184      */
1185     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1186 
1187     /** @hide */
1188     @IntDef({
1189             FOCUS_BACKWARD,
1190             FOCUS_FORWARD,
1191             FOCUS_LEFT,
1192             FOCUS_UP,
1193             FOCUS_RIGHT,
1194             FOCUS_DOWN
1195     })
1196     @Retention(RetentionPolicy.SOURCE)
1197     public @interface FocusDirection {}
1198 
1199     /** @hide */
1200     @IntDef({
1201             FOCUS_LEFT,
1202             FOCUS_UP,
1203             FOCUS_RIGHT,
1204             FOCUS_DOWN
1205     })
1206     @Retention(RetentionPolicy.SOURCE)
1207     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1208 
1209     /**
1210      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1211      * item.
1212      */
1213     public static final int FOCUS_BACKWARD = 0x00000001;
1214 
1215     /**
1216      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1217      * item.
1218      */
1219     public static final int FOCUS_FORWARD = 0x00000002;
1220 
1221     /**
1222      * Use with {@link #focusSearch(int)}. Move focus to the left.
1223      */
1224     public static final int FOCUS_LEFT = 0x00000011;
1225 
1226     /**
1227      * Use with {@link #focusSearch(int)}. Move focus up.
1228      */
1229     public static final int FOCUS_UP = 0x00000021;
1230 
1231     /**
1232      * Use with {@link #focusSearch(int)}. Move focus to the right.
1233      */
1234     public static final int FOCUS_RIGHT = 0x00000042;
1235 
1236     /**
1237      * Use with {@link #focusSearch(int)}. Move focus down.
1238      */
1239     public static final int FOCUS_DOWN = 0x00000082;
1240 
1241     /**
1242      * Bits of {@link #getMeasuredWidthAndState()} and
1243      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1244      */
1245     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1246 
1247     /**
1248      * Bits of {@link #getMeasuredWidthAndState()} and
1249      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1250      */
1251     public static final int MEASURED_STATE_MASK = 0xff000000;
1252 
1253     /**
1254      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1255      * for functions that combine both width and height into a single int,
1256      * such as {@link #getMeasuredState()} and the childState argument of
1257      * {@link #resolveSizeAndState(int, int, int)}.
1258      */
1259     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1260 
1261     /**
1262      * Bit of {@link #getMeasuredWidthAndState()} and
1263      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1264      * is smaller that the space the view would like to have.
1265      */
1266     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1267 
1268     /**
1269      * Base View state sets
1270      */
1271     // Singles
1272     /**
1273      * Indicates the view has no states set. States are used with
1274      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1275      * view depending on its state.
1276      *
1277      * @see android.graphics.drawable.Drawable
1278      * @see #getDrawableState()
1279      */
1280     protected static final int[] EMPTY_STATE_SET;
1281     /**
1282      * Indicates the view is enabled. States are used with
1283      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1284      * view depending on its state.
1285      *
1286      * @see android.graphics.drawable.Drawable
1287      * @see #getDrawableState()
1288      */
1289     protected static final int[] ENABLED_STATE_SET;
1290     /**
1291      * Indicates the view is focused. States are used with
1292      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1293      * view depending on its state.
1294      *
1295      * @see android.graphics.drawable.Drawable
1296      * @see #getDrawableState()
1297      */
1298     protected static final int[] FOCUSED_STATE_SET;
1299     /**
1300      * Indicates the view is selected. States are used with
1301      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1302      * view depending on its state.
1303      *
1304      * @see android.graphics.drawable.Drawable
1305      * @see #getDrawableState()
1306      */
1307     protected static final int[] SELECTED_STATE_SET;
1308     /**
1309      * Indicates the view is pressed. States are used with
1310      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1311      * view depending on its state.
1312      *
1313      * @see android.graphics.drawable.Drawable
1314      * @see #getDrawableState()
1315      */
1316     protected static final int[] PRESSED_STATE_SET;
1317     /**
1318      * Indicates the view's window has focus. States are used with
1319      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1320      * view depending on its state.
1321      *
1322      * @see android.graphics.drawable.Drawable
1323      * @see #getDrawableState()
1324      */
1325     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1326     // Doubles
1327     /**
1328      * Indicates the view is enabled and has the focus.
1329      *
1330      * @see #ENABLED_STATE_SET
1331      * @see #FOCUSED_STATE_SET
1332      */
1333     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1334     /**
1335      * Indicates the view is enabled and selected.
1336      *
1337      * @see #ENABLED_STATE_SET
1338      * @see #SELECTED_STATE_SET
1339      */
1340     protected static final int[] ENABLED_SELECTED_STATE_SET;
1341     /**
1342      * Indicates the view is enabled and that its window has focus.
1343      *
1344      * @see #ENABLED_STATE_SET
1345      * @see #WINDOW_FOCUSED_STATE_SET
1346      */
1347     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1348     /**
1349      * Indicates the view is focused and selected.
1350      *
1351      * @see #FOCUSED_STATE_SET
1352      * @see #SELECTED_STATE_SET
1353      */
1354     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1355     /**
1356      * Indicates the view has the focus and that its window has the focus.
1357      *
1358      * @see #FOCUSED_STATE_SET
1359      * @see #WINDOW_FOCUSED_STATE_SET
1360      */
1361     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1362     /**
1363      * Indicates the view is selected and that its window has the focus.
1364      *
1365      * @see #SELECTED_STATE_SET
1366      * @see #WINDOW_FOCUSED_STATE_SET
1367      */
1368     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1369     // Triples
1370     /**
1371      * Indicates the view is enabled, focused and selected.
1372      *
1373      * @see #ENABLED_STATE_SET
1374      * @see #FOCUSED_STATE_SET
1375      * @see #SELECTED_STATE_SET
1376      */
1377     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1378     /**
1379      * Indicates the view is enabled, focused and its window has the focus.
1380      *
1381      * @see #ENABLED_STATE_SET
1382      * @see #FOCUSED_STATE_SET
1383      * @see #WINDOW_FOCUSED_STATE_SET
1384      */
1385     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1386     /**
1387      * Indicates the view is enabled, selected and its window has the focus.
1388      *
1389      * @see #ENABLED_STATE_SET
1390      * @see #SELECTED_STATE_SET
1391      * @see #WINDOW_FOCUSED_STATE_SET
1392      */
1393     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1394     /**
1395      * Indicates the view is focused, selected and its window has the focus.
1396      *
1397      * @see #FOCUSED_STATE_SET
1398      * @see #SELECTED_STATE_SET
1399      * @see #WINDOW_FOCUSED_STATE_SET
1400      */
1401     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1402     /**
1403      * Indicates the view is enabled, focused, selected and its window
1404      * has the focus.
1405      *
1406      * @see #ENABLED_STATE_SET
1407      * @see #FOCUSED_STATE_SET
1408      * @see #SELECTED_STATE_SET
1409      * @see #WINDOW_FOCUSED_STATE_SET
1410      */
1411     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1412     /**
1413      * Indicates the view is pressed and its window has the focus.
1414      *
1415      * @see #PRESSED_STATE_SET
1416      * @see #WINDOW_FOCUSED_STATE_SET
1417      */
1418     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1419     /**
1420      * Indicates the view is pressed and selected.
1421      *
1422      * @see #PRESSED_STATE_SET
1423      * @see #SELECTED_STATE_SET
1424      */
1425     protected static final int[] PRESSED_SELECTED_STATE_SET;
1426     /**
1427      * Indicates the view is pressed, selected and its window has the focus.
1428      *
1429      * @see #PRESSED_STATE_SET
1430      * @see #SELECTED_STATE_SET
1431      * @see #WINDOW_FOCUSED_STATE_SET
1432      */
1433     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1434     /**
1435      * Indicates the view is pressed and focused.
1436      *
1437      * @see #PRESSED_STATE_SET
1438      * @see #FOCUSED_STATE_SET
1439      */
1440     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1441     /**
1442      * Indicates the view is pressed, focused and its window has the focus.
1443      *
1444      * @see #PRESSED_STATE_SET
1445      * @see #FOCUSED_STATE_SET
1446      * @see #WINDOW_FOCUSED_STATE_SET
1447      */
1448     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1449     /**
1450      * Indicates the view is pressed, focused and selected.
1451      *
1452      * @see #PRESSED_STATE_SET
1453      * @see #SELECTED_STATE_SET
1454      * @see #FOCUSED_STATE_SET
1455      */
1456     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1457     /**
1458      * Indicates the view is pressed, focused, selected and its window has the focus.
1459      *
1460      * @see #PRESSED_STATE_SET
1461      * @see #FOCUSED_STATE_SET
1462      * @see #SELECTED_STATE_SET
1463      * @see #WINDOW_FOCUSED_STATE_SET
1464      */
1465     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1466     /**
1467      * Indicates the view is pressed and enabled.
1468      *
1469      * @see #PRESSED_STATE_SET
1470      * @see #ENABLED_STATE_SET
1471      */
1472     protected static final int[] PRESSED_ENABLED_STATE_SET;
1473     /**
1474      * Indicates the view is pressed, enabled and its window has the focus.
1475      *
1476      * @see #PRESSED_STATE_SET
1477      * @see #ENABLED_STATE_SET
1478      * @see #WINDOW_FOCUSED_STATE_SET
1479      */
1480     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1481     /**
1482      * Indicates the view is pressed, enabled and selected.
1483      *
1484      * @see #PRESSED_STATE_SET
1485      * @see #ENABLED_STATE_SET
1486      * @see #SELECTED_STATE_SET
1487      */
1488     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1489     /**
1490      * Indicates the view is pressed, enabled, selected and its window has the
1491      * focus.
1492      *
1493      * @see #PRESSED_STATE_SET
1494      * @see #ENABLED_STATE_SET
1495      * @see #SELECTED_STATE_SET
1496      * @see #WINDOW_FOCUSED_STATE_SET
1497      */
1498     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1499     /**
1500      * Indicates the view is pressed, enabled and focused.
1501      *
1502      * @see #PRESSED_STATE_SET
1503      * @see #ENABLED_STATE_SET
1504      * @see #FOCUSED_STATE_SET
1505      */
1506     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1507     /**
1508      * Indicates the view is pressed, enabled, focused and its window has the
1509      * focus.
1510      *
1511      * @see #PRESSED_STATE_SET
1512      * @see #ENABLED_STATE_SET
1513      * @see #FOCUSED_STATE_SET
1514      * @see #WINDOW_FOCUSED_STATE_SET
1515      */
1516     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1517     /**
1518      * Indicates the view is pressed, enabled, focused and selected.
1519      *
1520      * @see #PRESSED_STATE_SET
1521      * @see #ENABLED_STATE_SET
1522      * @see #SELECTED_STATE_SET
1523      * @see #FOCUSED_STATE_SET
1524      */
1525     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1526     /**
1527      * Indicates the view is pressed, enabled, focused, selected and its window
1528      * has the focus.
1529      *
1530      * @see #PRESSED_STATE_SET
1531      * @see #ENABLED_STATE_SET
1532      * @see #SELECTED_STATE_SET
1533      * @see #FOCUSED_STATE_SET
1534      * @see #WINDOW_FOCUSED_STATE_SET
1535      */
1536     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1537 
1538     static {
1539         EMPTY_STATE_SET = StateSet.get(0);
1540 
1541         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1542 
1543         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1544         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1545                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1546 
1547         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1548         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1549                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1550         FOCUSED_SELECTED_STATE_SET = StateSet.get(
1551                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1552         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1553                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1554                         | StateSet.VIEW_STATE_FOCUSED);
1555 
1556         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1557         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1558                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1559         ENABLED_SELECTED_STATE_SET = StateSet.get(
1560                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1561         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1562                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1563                         | StateSet.VIEW_STATE_ENABLED);
1564         ENABLED_FOCUSED_STATE_SET = StateSet.get(
1565                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1566         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1567                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1568                         | StateSet.VIEW_STATE_ENABLED);
1569         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1570                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1571                         | StateSet.VIEW_STATE_ENABLED);
1572         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1573                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1574                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1575 
1576         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1577         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1578                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1579         PRESSED_SELECTED_STATE_SET = StateSet.get(
1580                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1581         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1582                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1583                         | StateSet.VIEW_STATE_PRESSED);
1584         PRESSED_FOCUSED_STATE_SET = StateSet.get(
1585                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1586         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1587                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1588                         | StateSet.VIEW_STATE_PRESSED);
1589         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1590                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1591                         | StateSet.VIEW_STATE_PRESSED);
1592         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1593                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1594                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1595         PRESSED_ENABLED_STATE_SET = StateSet.get(
1596                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1597         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1598                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1599                         | StateSet.VIEW_STATE_PRESSED);
1600         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1601                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1602                         | StateSet.VIEW_STATE_PRESSED);
1603         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1604                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1605                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1606         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1607                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1608                         | StateSet.VIEW_STATE_PRESSED);
1609         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1610                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1611                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1612         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1613                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1614                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1615         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1616                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1617                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1618                         | StateSet.VIEW_STATE_PRESSED);
1619     }
1620 
1621     /**
1622      * Accessibility event types that are dispatched for text population.
1623      */
1624     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1625             AccessibilityEvent.TYPE_VIEW_CLICKED
1626             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1627             | AccessibilityEvent.TYPE_VIEW_SELECTED
1628             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1629             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1630             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1631             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1632             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1633             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1634             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1635             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1636 
1637     /**
1638      * Temporary Rect currently for use in setBackground().  This will probably
1639      * be extended in the future to hold our own class with more than just
1640      * a Rect. :)
1641      */
1642     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1643 
1644     /**
1645      * Map used to store views' tags.
1646      */
1647     private SparseArray<Object> mKeyedTags;
1648 
1649     /**
1650      * The next available accessibility id.
1651      */
1652     private static int sNextAccessibilityViewId;
1653 
1654     /**
1655      * The animation currently associated with this view.
1656      * @hide
1657      */
1658     protected Animation mCurrentAnimation = null;
1659 
1660     /**
1661      * Width as measured during measure pass.
1662      * {@hide}
1663      */
1664     @ViewDebug.ExportedProperty(category = "measurement")
1665     int mMeasuredWidth;
1666 
1667     /**
1668      * Height as measured during measure pass.
1669      * {@hide}
1670      */
1671     @ViewDebug.ExportedProperty(category = "measurement")
1672     int mMeasuredHeight;
1673 
1674     /**
1675      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1676      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1677      * its display list. This flag, used only when hw accelerated, allows us to clear the
1678      * flag while retaining this information until it's needed (at getDisplayList() time and
1679      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1680      *
1681      * {@hide}
1682      */
1683     boolean mRecreateDisplayList = false;
1684 
1685     /**
1686      * The view's identifier.
1687      * {@hide}
1688      *
1689      * @see #setId(int)
1690      * @see #getId()
1691      */
1692     @IdRes
1693     @ViewDebug.ExportedProperty(resolveId = true)
1694     int mID = NO_ID;
1695 
1696     /**
1697      * The stable ID of this view for accessibility purposes.
1698      */
1699     int mAccessibilityViewId = NO_ID;
1700 
1701     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1702 
1703     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1704 
1705     /**
1706      * The view's tag.
1707      * {@hide}
1708      *
1709      * @see #setTag(Object)
1710      * @see #getTag()
1711      */
1712     protected Object mTag = null;
1713 
1714     // for mPrivateFlags:
1715     /** {@hide} */
1716     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1717     /** {@hide} */
1718     static final int PFLAG_FOCUSED                     = 0x00000002;
1719     /** {@hide} */
1720     static final int PFLAG_SELECTED                    = 0x00000004;
1721     /** {@hide} */
1722     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1723     /** {@hide} */
1724     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1725     /** {@hide} */
1726     static final int PFLAG_DRAWN                       = 0x00000020;
1727     /**
1728      * When this flag is set, this view is running an animation on behalf of its
1729      * children and should therefore not cancel invalidate requests, even if they
1730      * lie outside of this view's bounds.
1731      *
1732      * {@hide}
1733      */
1734     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1735     /** {@hide} */
1736     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1737     /** {@hide} */
1738     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1739     /** {@hide} */
1740     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1741     /** {@hide} */
1742     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1743     /** {@hide} */
1744     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1745     /** {@hide} */
1746     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1747 
1748     private static final int PFLAG_PRESSED             = 0x00004000;
1749 
1750     /** {@hide} */
1751     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1752     /**
1753      * Flag used to indicate that this view should be drawn once more (and only once
1754      * more) after its animation has completed.
1755      * {@hide}
1756      */
1757     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1758 
1759     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1760 
1761     /**
1762      * Indicates that the View returned true when onSetAlpha() was called and that
1763      * the alpha must be restored.
1764      * {@hide}
1765      */
1766     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1767 
1768     /**
1769      * Set by {@link #setScrollContainer(boolean)}.
1770      */
1771     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1772 
1773     /**
1774      * Set by {@link #setScrollContainer(boolean)}.
1775      */
1776     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1777 
1778     /**
1779      * View flag indicating whether this view was invalidated (fully or partially.)
1780      *
1781      * @hide
1782      */
1783     static final int PFLAG_DIRTY                       = 0x00200000;
1784 
1785     /**
1786      * View flag indicating whether this view was invalidated by an opaque
1787      * invalidate request.
1788      *
1789      * @hide
1790      */
1791     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1792 
1793     /**
1794      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1795      *
1796      * @hide
1797      */
1798     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1799 
1800     /**
1801      * Indicates whether the background is opaque.
1802      *
1803      * @hide
1804      */
1805     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1806 
1807     /**
1808      * Indicates whether the scrollbars are opaque.
1809      *
1810      * @hide
1811      */
1812     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1813 
1814     /**
1815      * Indicates whether the view is opaque.
1816      *
1817      * @hide
1818      */
1819     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1820 
1821     /**
1822      * Indicates a prepressed state;
1823      * the short time between ACTION_DOWN and recognizing
1824      * a 'real' press. Prepressed is used to recognize quick taps
1825      * even when they are shorter than ViewConfiguration.getTapTimeout().
1826      *
1827      * @hide
1828      */
1829     private static final int PFLAG_PREPRESSED          = 0x02000000;
1830 
1831     /**
1832      * Indicates whether the view is temporarily detached.
1833      *
1834      * @hide
1835      */
1836     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1837 
1838     /**
1839      * Indicates that we should awaken scroll bars once attached
1840      *
1841      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1842      * during window attachment and it is no longer needed. Feel free to repurpose it.
1843      *
1844      * @hide
1845      */
1846     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1847 
1848     /**
1849      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1850      * @hide
1851      */
1852     private static final int PFLAG_HOVERED             = 0x10000000;
1853 
1854     /**
1855      * no longer needed, should be reused
1856      */
1857     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1858 
1859     /** {@hide} */
1860     static final int PFLAG_ACTIVATED                   = 0x40000000;
1861 
1862     /**
1863      * Indicates that this view was specifically invalidated, not just dirtied because some
1864      * child view was invalidated. The flag is used to determine when we need to recreate
1865      * a view's display list (as opposed to just returning a reference to its existing
1866      * display list).
1867      *
1868      * @hide
1869      */
1870     static final int PFLAG_INVALIDATED                 = 0x80000000;
1871 
1872     /**
1873      * Masks for mPrivateFlags2, as generated by dumpFlags():
1874      *
1875      * |-------|-------|-------|-------|
1876      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1877      *                                1  PFLAG2_DRAG_HOVERED
1878      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1879      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1880      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1881      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1882      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1883      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1884      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1885      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1886      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1887      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1888      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1889      *                         111       PFLAG2_TEXT_DIRECTION_MASK
1890      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1891      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1892      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1893      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1894      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1895      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1896      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1897      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1898      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1899      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1900      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1901      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1902      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1903      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1904      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1905      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1906      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1907      *     1                             PFLAG2_VIEW_QUICK_REJECTED
1908      *    1                              PFLAG2_PADDING_RESOLVED
1909      *   1                               PFLAG2_DRAWABLE_RESOLVED
1910      *  1                                PFLAG2_HAS_TRANSIENT_STATE
1911      * |-------|-------|-------|-------|
1912      */
1913 
1914     /**
1915      * Indicates that this view has reported that it can accept the current drag's content.
1916      * Cleared when the drag operation concludes.
1917      * @hide
1918      */
1919     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1920 
1921     /**
1922      * Indicates that this view is currently directly under the drag location in a
1923      * drag-and-drop operation involving content that it can accept.  Cleared when
1924      * the drag exits the view, or when the drag operation concludes.
1925      * @hide
1926      */
1927     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1928 
1929     /** @hide */
1930     @IntDef({
1931         LAYOUT_DIRECTION_LTR,
1932         LAYOUT_DIRECTION_RTL,
1933         LAYOUT_DIRECTION_INHERIT,
1934         LAYOUT_DIRECTION_LOCALE
1935     })
1936     @Retention(RetentionPolicy.SOURCE)
1937     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1938     public @interface LayoutDir {}
1939 
1940     /** @hide */
1941     @IntDef({
1942         LAYOUT_DIRECTION_LTR,
1943         LAYOUT_DIRECTION_RTL
1944     })
1945     @Retention(RetentionPolicy.SOURCE)
1946     public @interface ResolvedLayoutDir {}
1947 
1948     /**
1949      * A flag to indicate that the layout direction of this view has not been defined yet.
1950      * @hide
1951      */
1952     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1953 
1954     /**
1955      * Horizontal layout direction of this view is from Left to Right.
1956      * Use with {@link #setLayoutDirection}.
1957      */
1958     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1959 
1960     /**
1961      * Horizontal layout direction of this view is from Right to Left.
1962      * Use with {@link #setLayoutDirection}.
1963      */
1964     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1965 
1966     /**
1967      * Horizontal layout direction of this view is inherited from its parent.
1968      * Use with {@link #setLayoutDirection}.
1969      */
1970     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1971 
1972     /**
1973      * Horizontal layout direction of this view is from deduced from the default language
1974      * script for the locale. Use with {@link #setLayoutDirection}.
1975      */
1976     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1977 
1978     /**
1979      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1980      * @hide
1981      */
1982     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1983 
1984     /**
1985      * Mask for use with private flags indicating bits used for horizontal layout direction.
1986      * @hide
1987      */
1988     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1989 
1990     /**
1991      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1992      * right-to-left direction.
1993      * @hide
1994      */
1995     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1996 
1997     /**
1998      * Indicates whether the view horizontal layout direction has been resolved.
1999      * @hide
2000      */
2001     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2002 
2003     /**
2004      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2005      * @hide
2006      */
2007     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2008             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2009 
2010     /*
2011      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2012      * flag value.
2013      * @hide
2014      */
2015     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2016             LAYOUT_DIRECTION_LTR,
2017             LAYOUT_DIRECTION_RTL,
2018             LAYOUT_DIRECTION_INHERIT,
2019             LAYOUT_DIRECTION_LOCALE
2020     };
2021 
2022     /**
2023      * Default horizontal layout direction.
2024      */
2025     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2026 
2027     /**
2028      * Default horizontal layout direction.
2029      * @hide
2030      */
2031     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2032 
2033     /**
2034      * Text direction is inherited through {@link ViewGroup}
2035      */
2036     public static final int TEXT_DIRECTION_INHERIT = 0;
2037 
2038     /**
2039      * Text direction is using "first strong algorithm". The first strong directional character
2040      * determines the paragraph direction. If there is no strong directional character, the
2041      * paragraph direction is the view's resolved layout direction.
2042      */
2043     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2044 
2045     /**
2046      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2047      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2048      * If there are neither, the paragraph direction is the view's resolved layout direction.
2049      */
2050     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2051 
2052     /**
2053      * Text direction is forced to LTR.
2054      */
2055     public static final int TEXT_DIRECTION_LTR = 3;
2056 
2057     /**
2058      * Text direction is forced to RTL.
2059      */
2060     public static final int TEXT_DIRECTION_RTL = 4;
2061 
2062     /**
2063      * Text direction is coming from the system Locale.
2064      */
2065     public static final int TEXT_DIRECTION_LOCALE = 5;
2066 
2067     /**
2068      * Text direction is using "first strong algorithm". The first strong directional character
2069      * determines the paragraph direction. If there is no strong directional character, the
2070      * paragraph direction is LTR.
2071      */
2072     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2073 
2074     /**
2075      * Text direction is using "first strong algorithm". The first strong directional character
2076      * determines the paragraph direction. If there is no strong directional character, the
2077      * paragraph direction is RTL.
2078      */
2079     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2080 
2081     /**
2082      * Default text direction is inherited
2083      */
2084     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2085 
2086     /**
2087      * Default resolved text direction
2088      * @hide
2089      */
2090     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2091 
2092     /**
2093      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2094      * @hide
2095      */
2096     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2097 
2098     /**
2099      * Mask for use with private flags indicating bits used for text direction.
2100      * @hide
2101      */
2102     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2103             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2104 
2105     /**
2106      * Array of text direction flags for mapping attribute "textDirection" to correct
2107      * flag value.
2108      * @hide
2109      */
2110     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2111             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2112             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2113             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2114             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2115             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2116             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2117             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2118             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2119     };
2120 
2121     /**
2122      * Indicates whether the view text direction has been resolved.
2123      * @hide
2124      */
2125     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2126             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2127 
2128     /**
2129      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2130      * @hide
2131      */
2132     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2133 
2134     /**
2135      * Mask for use with private flags indicating bits used for resolved text direction.
2136      * @hide
2137      */
2138     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2139             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2140 
2141     /**
2142      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2143      * @hide
2144      */
2145     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2146             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2147 
2148     /** @hide */
2149     @IntDef({
2150         TEXT_ALIGNMENT_INHERIT,
2151         TEXT_ALIGNMENT_GRAVITY,
2152         TEXT_ALIGNMENT_CENTER,
2153         TEXT_ALIGNMENT_TEXT_START,
2154         TEXT_ALIGNMENT_TEXT_END,
2155         TEXT_ALIGNMENT_VIEW_START,
2156         TEXT_ALIGNMENT_VIEW_END
2157     })
2158     @Retention(RetentionPolicy.SOURCE)
2159     public @interface TextAlignment {}
2160 
2161     /**
2162      * Default text alignment. The text alignment of this View is inherited from its parent.
2163      * Use with {@link #setTextAlignment(int)}
2164      */
2165     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2166 
2167     /**
2168      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2169      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2170      *
2171      * Use with {@link #setTextAlignment(int)}
2172      */
2173     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2174 
2175     /**
2176      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2177      *
2178      * Use with {@link #setTextAlignment(int)}
2179      */
2180     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2181 
2182     /**
2183      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2184      *
2185      * Use with {@link #setTextAlignment(int)}
2186      */
2187     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2188 
2189     /**
2190      * Center the paragraph, e.g. ALIGN_CENTER.
2191      *
2192      * Use with {@link #setTextAlignment(int)}
2193      */
2194     public static final int TEXT_ALIGNMENT_CENTER = 4;
2195 
2196     /**
2197      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2198      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2199      *
2200      * Use with {@link #setTextAlignment(int)}
2201      */
2202     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2203 
2204     /**
2205      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2206      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2207      *
2208      * Use with {@link #setTextAlignment(int)}
2209      */
2210     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2211 
2212     /**
2213      * Default text alignment is inherited
2214      */
2215     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2216 
2217     /**
2218      * Default resolved text alignment
2219      * @hide
2220      */
2221     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2222 
2223     /**
2224       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2225       * @hide
2226       */
2227     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2228 
2229     /**
2230       * Mask for use with private flags indicating bits used for text alignment.
2231       * @hide
2232       */
2233     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2234 
2235     /**
2236      * Array of text direction flags for mapping attribute "textAlignment" to correct
2237      * flag value.
2238      * @hide
2239      */
2240     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2241             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2242             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2243             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2244             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2245             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2246             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2247             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2248     };
2249 
2250     /**
2251      * Indicates whether the view text alignment has been resolved.
2252      * @hide
2253      */
2254     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2255 
2256     /**
2257      * Bit shift to get the resolved text alignment.
2258      * @hide
2259      */
2260     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2261 
2262     /**
2263      * Mask for use with private flags indicating bits used for text alignment.
2264      * @hide
2265      */
2266     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2267             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2268 
2269     /**
2270      * Indicates whether if the view text alignment has been resolved to gravity
2271      */
2272     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2273             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2274 
2275     // Accessiblity constants for mPrivateFlags2
2276 
2277     /**
2278      * Shift for the bits in {@link #mPrivateFlags2} related to the
2279      * "importantForAccessibility" attribute.
2280      */
2281     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2282 
2283     /**
2284      * Automatically determine whether a view is important for accessibility.
2285      */
2286     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2287 
2288     /**
2289      * The view is important for accessibility.
2290      */
2291     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2292 
2293     /**
2294      * The view is not important for accessibility.
2295      */
2296     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2297 
2298     /**
2299      * The view is not important for accessibility, nor are any of its
2300      * descendant views.
2301      */
2302     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2303 
2304     /**
2305      * The default whether the view is important for accessibility.
2306      */
2307     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2308 
2309     /**
2310      * Mask for obtainig the bits which specify how to determine
2311      * whether a view is important for accessibility.
2312      */
2313     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2314         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2315         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2316         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2317 
2318     /**
2319      * Shift for the bits in {@link #mPrivateFlags2} related to the
2320      * "accessibilityLiveRegion" attribute.
2321      */
2322     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2323 
2324     /**
2325      * Live region mode specifying that accessibility services should not
2326      * automatically announce changes to this view. This is the default live
2327      * region mode for most views.
2328      * <p>
2329      * Use with {@link #setAccessibilityLiveRegion(int)}.
2330      */
2331     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2332 
2333     /**
2334      * Live region mode specifying that accessibility services should announce
2335      * changes to this view.
2336      * <p>
2337      * Use with {@link #setAccessibilityLiveRegion(int)}.
2338      */
2339     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2340 
2341     /**
2342      * Live region mode specifying that accessibility services should interrupt
2343      * ongoing speech to immediately announce changes to this view.
2344      * <p>
2345      * Use with {@link #setAccessibilityLiveRegion(int)}.
2346      */
2347     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2348 
2349     /**
2350      * The default whether the view is important for accessibility.
2351      */
2352     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2353 
2354     /**
2355      * Mask for obtaining the bits which specify a view's accessibility live
2356      * region mode.
2357      */
2358     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2359             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2360             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2361 
2362     /**
2363      * Flag indicating whether a view has accessibility focus.
2364      */
2365     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2366 
2367     /**
2368      * Flag whether the accessibility state of the subtree rooted at this view changed.
2369      */
2370     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2371 
2372     /**
2373      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2374      * is used to check whether later changes to the view's transform should invalidate the
2375      * view to force the quickReject test to run again.
2376      */
2377     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2378 
2379     /**
2380      * Flag indicating that start/end padding has been resolved into left/right padding
2381      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2382      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2383      * during measurement. In some special cases this is required such as when an adapter-based
2384      * view measures prospective children without attaching them to a window.
2385      */
2386     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2387 
2388     /**
2389      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2390      */
2391     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2392 
2393     /**
2394      * Indicates that the view is tracking some sort of transient state
2395      * that the app should not need to be aware of, but that the framework
2396      * should take special care to preserve.
2397      */
2398     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2399 
2400     /**
2401      * Group of bits indicating that RTL properties resolution is done.
2402      */
2403     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2404             PFLAG2_TEXT_DIRECTION_RESOLVED |
2405             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2406             PFLAG2_PADDING_RESOLVED |
2407             PFLAG2_DRAWABLE_RESOLVED;
2408 
2409     // There are a couple of flags left in mPrivateFlags2
2410 
2411     /* End of masks for mPrivateFlags2 */
2412 
2413     /**
2414      * Masks for mPrivateFlags3, as generated by dumpFlags():
2415      *
2416      * |-------|-------|-------|-------|
2417      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2418      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2419      *                               1   PFLAG3_IS_LAID_OUT
2420      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2421      *                             1     PFLAG3_CALLED_SUPER
2422      *                            1      PFLAG3_APPLYING_INSETS
2423      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2424      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2425      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2426      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2427      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2428      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2429      *                     1             PFLAG3_SCROLL_INDICATOR_START
2430      *                    1              PFLAG3_SCROLL_INDICATOR_END
2431      *                   1               PFLAG3_ASSIST_BLOCKED
2432      *                  1                PFLAG3_POINTER_ICON_NULL
2433      *                 1                 PFLAG3_POINTER_ICON_VALUE_START
2434      *           11111111                PFLAG3_POINTER_ICON_MASK
2435      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2436      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2437      *        1                          PFLAG3_TEMPORARY_DETACH
2438      * |-------|-------|-------|-------|
2439      */
2440 
2441     /**
2442      * Flag indicating that view has a transform animation set on it. This is used to track whether
2443      * an animation is cleared between successive frames, in order to tell the associated
2444      * DisplayList to clear its animation matrix.
2445      */
2446     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2447 
2448     /**
2449      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2450      * animation is cleared between successive frames, in order to tell the associated
2451      * DisplayList to restore its alpha value.
2452      */
2453     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2454 
2455     /**
2456      * Flag indicating that the view has been through at least one layout since it
2457      * was last attached to a window.
2458      */
2459     static final int PFLAG3_IS_LAID_OUT = 0x4;
2460 
2461     /**
2462      * Flag indicating that a call to measure() was skipped and should be done
2463      * instead when layout() is invoked.
2464      */
2465     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2466 
2467     /**
2468      * Flag indicating that an overridden method correctly called down to
2469      * the superclass implementation as required by the API spec.
2470      */
2471     static final int PFLAG3_CALLED_SUPER = 0x10;
2472 
2473     /**
2474      * Flag indicating that we're in the process of applying window insets.
2475      */
2476     static final int PFLAG3_APPLYING_INSETS = 0x20;
2477 
2478     /**
2479      * Flag indicating that we're in the process of fitting system windows using the old method.
2480      */
2481     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2482 
2483     /**
2484      * Flag indicating that nested scrolling is enabled for this view.
2485      * The view will optionally cooperate with views up its parent chain to allow for
2486      * integrated nested scrolling along the same axis.
2487      */
2488     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2489 
2490     /**
2491      * Flag indicating that the bottom scroll indicator should be displayed
2492      * when this view can scroll up.
2493      */
2494     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2495 
2496     /**
2497      * Flag indicating that the bottom scroll indicator should be displayed
2498      * when this view can scroll down.
2499      */
2500     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2501 
2502     /**
2503      * Flag indicating that the left scroll indicator should be displayed
2504      * when this view can scroll left.
2505      */
2506     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2507 
2508     /**
2509      * Flag indicating that the right scroll indicator should be displayed
2510      * when this view can scroll right.
2511      */
2512     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2513 
2514     /**
2515      * Flag indicating that the start scroll indicator should be displayed
2516      * when this view can scroll in the start direction.
2517      */
2518     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2519 
2520     /**
2521      * Flag indicating that the end scroll indicator should be displayed
2522      * when this view can scroll in the end direction.
2523      */
2524     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2525 
2526     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2527 
2528     static final int SCROLL_INDICATORS_NONE = 0x0000;
2529 
2530     /**
2531      * Mask for use with setFlags indicating bits used for indicating which
2532      * scroll indicators are enabled.
2533      */
2534     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2535             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2536             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2537             | PFLAG3_SCROLL_INDICATOR_END;
2538 
2539     /**
2540      * Left-shift required to translate between public scroll indicator flags
2541      * and internal PFLAGS3 flags. When used as a right-shift, translates
2542      * PFLAGS3 flags to public flags.
2543      */
2544     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2545 
2546     /** @hide */
2547     @Retention(RetentionPolicy.SOURCE)
2548     @IntDef(flag = true,
2549             value = {
2550                     SCROLL_INDICATOR_TOP,
2551                     SCROLL_INDICATOR_BOTTOM,
2552                     SCROLL_INDICATOR_LEFT,
2553                     SCROLL_INDICATOR_RIGHT,
2554                     SCROLL_INDICATOR_START,
2555                     SCROLL_INDICATOR_END,
2556             })
2557     public @interface ScrollIndicators {}
2558 
2559     /**
2560      * Scroll indicator direction for the top edge of the view.
2561      *
2562      * @see #setScrollIndicators(int)
2563      * @see #setScrollIndicators(int, int)
2564      * @see #getScrollIndicators()
2565      */
2566     public static final int SCROLL_INDICATOR_TOP =
2567             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2568 
2569     /**
2570      * Scroll indicator direction for the bottom edge of the view.
2571      *
2572      * @see #setScrollIndicators(int)
2573      * @see #setScrollIndicators(int, int)
2574      * @see #getScrollIndicators()
2575      */
2576     public static final int SCROLL_INDICATOR_BOTTOM =
2577             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2578 
2579     /**
2580      * Scroll indicator direction for the left edge of the view.
2581      *
2582      * @see #setScrollIndicators(int)
2583      * @see #setScrollIndicators(int, int)
2584      * @see #getScrollIndicators()
2585      */
2586     public static final int SCROLL_INDICATOR_LEFT =
2587             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2588 
2589     /**
2590      * Scroll indicator direction for the right edge of the view.
2591      *
2592      * @see #setScrollIndicators(int)
2593      * @see #setScrollIndicators(int, int)
2594      * @see #getScrollIndicators()
2595      */
2596     public static final int SCROLL_INDICATOR_RIGHT =
2597             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2598 
2599     /**
2600      * Scroll indicator direction for the starting edge of the view.
2601      * <p>
2602      * Resolved according to the view's layout direction, see
2603      * {@link #getLayoutDirection()} for more information.
2604      *
2605      * @see #setScrollIndicators(int)
2606      * @see #setScrollIndicators(int, int)
2607      * @see #getScrollIndicators()
2608      */
2609     public static final int SCROLL_INDICATOR_START =
2610             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2611 
2612     /**
2613      * Scroll indicator direction for the ending edge of the view.
2614      * <p>
2615      * Resolved according to the view's layout direction, see
2616      * {@link #getLayoutDirection()} for more information.
2617      *
2618      * @see #setScrollIndicators(int)
2619      * @see #setScrollIndicators(int, int)
2620      * @see #getScrollIndicators()
2621      */
2622     public static final int SCROLL_INDICATOR_END =
2623             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2624 
2625     /**
2626      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2627      * into this view.<p>
2628      */
2629     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2630 
2631     /**
2632      * The mask for use with private flags indicating bits used for pointer icon shapes.
2633      */
2634     static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2635 
2636     /**
2637      * Left-shift used for pointer icon shape values in private flags.
2638      */
2639     static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2640 
2641     /**
2642      * Value indicating no specific pointer icons.
2643      */
2644     private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2645 
2646     /**
2647      * Value indicating {@link PointerIcon.TYPE_NULL}.
2648      */
2649     private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2650 
2651     /**
2652      * The base value for other pointer icon shapes.
2653      */
2654     private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2655 
2656     /**
2657      * Whether this view has rendered elements that overlap (see {@link
2658      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2659      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2660      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2661      * determined by whatever {@link #hasOverlappingRendering()} returns.
2662      */
2663     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2664 
2665     /**
2666      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2667      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2668      */
2669     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2670 
2671     /**
2672      * Flag indicating that the view is temporarily detached from the parent view.
2673      *
2674      * @see #onStartTemporaryDetach()
2675      * @see #onFinishTemporaryDetach()
2676      */
2677     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2678 
2679     /* End of masks for mPrivateFlags3 */
2680 
2681     /**
2682      * Always allow a user to over-scroll this view, provided it is a
2683      * view that can scroll.
2684      *
2685      * @see #getOverScrollMode()
2686      * @see #setOverScrollMode(int)
2687      */
2688     public static final int OVER_SCROLL_ALWAYS = 0;
2689 
2690     /**
2691      * Allow a user to over-scroll this view only if the content is large
2692      * enough to meaningfully scroll, provided it is a view that can scroll.
2693      *
2694      * @see #getOverScrollMode()
2695      * @see #setOverScrollMode(int)
2696      */
2697     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2698 
2699     /**
2700      * Never allow a user to over-scroll this view.
2701      *
2702      * @see #getOverScrollMode()
2703      * @see #setOverScrollMode(int)
2704      */
2705     public static final int OVER_SCROLL_NEVER = 2;
2706 
2707     /**
2708      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2709      * requested the system UI (status bar) to be visible (the default).
2710      *
2711      * @see #setSystemUiVisibility(int)
2712      */
2713     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2714 
2715     /**
2716      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2717      * system UI to enter an unobtrusive "low profile" mode.
2718      *
2719      * <p>This is for use in games, book readers, video players, or any other
2720      * "immersive" application where the usual system chrome is deemed too distracting.
2721      *
2722      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2723      *
2724      * @see #setSystemUiVisibility(int)
2725      */
2726     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2727 
2728     /**
2729      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2730      * system navigation be temporarily hidden.
2731      *
2732      * <p>This is an even less obtrusive state than that called for by
2733      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2734      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2735      * those to disappear. This is useful (in conjunction with the
2736      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2737      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2738      * window flags) for displaying content using every last pixel on the display.
2739      *
2740      * <p>There is a limitation: because navigation controls are so important, the least user
2741      * interaction will cause them to reappear immediately.  When this happens, both
2742      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2743      * so that both elements reappear at the same time.
2744      *
2745      * @see #setSystemUiVisibility(int)
2746      */
2747     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2748 
2749     /**
2750      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2751      * into the normal fullscreen mode so that its content can take over the screen
2752      * while still allowing the user to interact with the application.
2753      *
2754      * <p>This has the same visual effect as
2755      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2756      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2757      * meaning that non-critical screen decorations (such as the status bar) will be
2758      * hidden while the user is in the View's window, focusing the experience on
2759      * that content.  Unlike the window flag, if you are using ActionBar in
2760      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2761      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2762      * hide the action bar.
2763      *
2764      * <p>This approach to going fullscreen is best used over the window flag when
2765      * it is a transient state -- that is, the application does this at certain
2766      * points in its user interaction where it wants to allow the user to focus
2767      * on content, but not as a continuous state.  For situations where the application
2768      * would like to simply stay full screen the entire time (such as a game that
2769      * wants to take over the screen), the
2770      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2771      * is usually a better approach.  The state set here will be removed by the system
2772      * in various situations (such as the user moving to another application) like
2773      * the other system UI states.
2774      *
2775      * <p>When using this flag, the application should provide some easy facility
2776      * for the user to go out of it.  A common example would be in an e-book
2777      * reader, where tapping on the screen brings back whatever screen and UI
2778      * decorations that had been hidden while the user was immersed in reading
2779      * the book.
2780      *
2781      * @see #setSystemUiVisibility(int)
2782      */
2783     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2784 
2785     /**
2786      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2787      * flags, we would like a stable view of the content insets given to
2788      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2789      * will always represent the worst case that the application can expect
2790      * as a continuous state.  In the stock Android UI this is the space for
2791      * the system bar, nav bar, and status bar, but not more transient elements
2792      * such as an input method.
2793      *
2794      * The stable layout your UI sees is based on the system UI modes you can
2795      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2796      * then you will get a stable layout for changes of the
2797      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2798      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2799      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2800      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2801      * with a stable layout.  (Note that you should avoid using
2802      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2803      *
2804      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2805      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2806      * then a hidden status bar will be considered a "stable" state for purposes
2807      * here.  This allows your UI to continually hide the status bar, while still
2808      * using the system UI flags to hide the action bar while still retaining
2809      * a stable layout.  Note that changing the window fullscreen flag will never
2810      * provide a stable layout for a clean transition.
2811      *
2812      * <p>If you are using ActionBar in
2813      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2814      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2815      * insets it adds to those given to the application.
2816      */
2817     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2818 
2819     /**
2820      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2821      * to be laid out as if it has requested
2822      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2823      * allows it to avoid artifacts when switching in and out of that mode, at
2824      * the expense that some of its user interface may be covered by screen
2825      * decorations when they are shown.  You can perform layout of your inner
2826      * UI elements to account for the navigation system UI through the
2827      * {@link #fitSystemWindows(Rect)} method.
2828      */
2829     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2830 
2831     /**
2832      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2833      * to be laid out as if it has requested
2834      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2835      * allows it to avoid artifacts when switching in and out of that mode, at
2836      * the expense that some of its user interface may be covered by screen
2837      * decorations when they are shown.  You can perform layout of your inner
2838      * UI elements to account for non-fullscreen system UI through the
2839      * {@link #fitSystemWindows(Rect)} method.
2840      */
2841     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2842 
2843     /**
2844      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2845      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2846      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2847      * user interaction.
2848      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2849      * has an effect when used in combination with that flag.</p>
2850      */
2851     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2852 
2853     /**
2854      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2855      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2856      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2857      * experience while also hiding the system bars.  If this flag is not set,
2858      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2859      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2860      * if the user swipes from the top of the screen.
2861      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2862      * system gestures, such as swiping from the top of the screen.  These transient system bars
2863      * will overlay app’s content, may have some degree of transparency, and will automatically
2864      * hide after a short timeout.
2865      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2866      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2867      * with one or both of those flags.</p>
2868      */
2869     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2870 
2871     /**
2872      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2873      * is compatible with light status bar backgrounds.
2874      *
2875      * <p>For this to take effect, the window must request
2876      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2877      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2878      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2879      *         FLAG_TRANSLUCENT_STATUS}.
2880      *
2881      * @see android.R.attr#windowLightStatusBar
2882      */
2883     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2884 
2885     /**
2886      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2887      */
2888     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2889 
2890     /**
2891      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2892      */
2893     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2894 
2895     /**
2896      * @hide
2897      *
2898      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2899      * out of the public fields to keep the undefined bits out of the developer's way.
2900      *
2901      * Flag to make the status bar not expandable.  Unless you also
2902      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2903      */
2904     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2905 
2906     /**
2907      * @hide
2908      *
2909      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2910      * out of the public fields to keep the undefined bits out of the developer's way.
2911      *
2912      * Flag to hide notification icons and scrolling ticker text.
2913      */
2914     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2915 
2916     /**
2917      * @hide
2918      *
2919      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2920      * out of the public fields to keep the undefined bits out of the developer's way.
2921      *
2922      * Flag to disable incoming notification alerts.  This will not block
2923      * icons, but it will block sound, vibrating and other visual or aural notifications.
2924      */
2925     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2926 
2927     /**
2928      * @hide
2929      *
2930      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2931      * out of the public fields to keep the undefined bits out of the developer's way.
2932      *
2933      * Flag to hide only the scrolling ticker.  Note that
2934      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2935      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2936      */
2937     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2938 
2939     /**
2940      * @hide
2941      *
2942      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2943      * out of the public fields to keep the undefined bits out of the developer's way.
2944      *
2945      * Flag to hide the center system info area.
2946      */
2947     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
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 home button.  Don't use this
2956      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2957      */
2958     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2959 
2960     /**
2961      * @hide
2962      *
2963      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2964      * out of the public fields to keep the undefined bits out of the developer's way.
2965      *
2966      * Flag to hide only the back button. Don't use this
2967      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2968      */
2969     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
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 clock.  You might use this if your activity has
2978      * its own clock making the status bar's clock redundant.
2979      */
2980     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
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 recent apps 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_RECENT = 0x01000000;
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 disable the global search gesture. Don't use this
3000      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3001      */
3002     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
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 specify that the status bar is displayed in transient mode.
3011      */
3012     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3013 
3014     /**
3015      * @hide
3016      *
3017      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3018      * out of the public fields to keep the undefined bits out of the developer's way.
3019      *
3020      * Flag to specify that the navigation bar is displayed in transient mode.
3021      */
3022     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3023 
3024     /**
3025      * @hide
3026      *
3027      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3028      * out of the public fields to keep the undefined bits out of the developer's way.
3029      *
3030      * Flag to specify that the hidden status bar would like to be shown.
3031      */
3032     public static final int STATUS_BAR_UNHIDE = 0x10000000;
3033 
3034     /**
3035      * @hide
3036      *
3037      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3038      * out of the public fields to keep the undefined bits out of the developer's way.
3039      *
3040      * Flag to specify that the hidden navigation bar would like to be shown.
3041      */
3042     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3043 
3044     /**
3045      * @hide
3046      *
3047      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3048      * out of the public fields to keep the undefined bits out of the developer's way.
3049      *
3050      * Flag to specify that the status bar is displayed in translucent mode.
3051      */
3052     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3053 
3054     /**
3055      * @hide
3056      *
3057      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3058      * out of the public fields to keep the undefined bits out of the developer's way.
3059      *
3060      * Flag to specify that the navigation bar is displayed in translucent mode.
3061      */
3062     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3063 
3064     /**
3065      * @hide
3066      *
3067      * Whether Recents is visible or not.
3068      */
3069     public static final int RECENT_APPS_VISIBLE = 0x00004000;
3070 
3071     /**
3072      * @hide
3073      *
3074      * Whether the TV's picture-in-picture is visible or not.
3075      */
3076     public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
3077 
3078     /**
3079      * @hide
3080      *
3081      * Makes navigation bar transparent (but not the status bar).
3082      */
3083     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3084 
3085     /**
3086      * @hide
3087      *
3088      * Makes status bar transparent (but not the navigation bar).
3089      */
3090     public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3091 
3092     /**
3093      * @hide
3094      *
3095      * Makes both status bar and navigation bar transparent.
3096      */
3097     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3098             | STATUS_BAR_TRANSPARENT;
3099 
3100     /**
3101      * @hide
3102      */
3103     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3104 
3105     /**
3106      * These are the system UI flags that can be cleared by events outside
3107      * of an application.  Currently this is just the ability to tap on the
3108      * screen while hiding the navigation bar to have it return.
3109      * @hide
3110      */
3111     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3112             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3113             | SYSTEM_UI_FLAG_FULLSCREEN;
3114 
3115     /**
3116      * Flags that can impact the layout in relation to system UI.
3117      */
3118     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3119             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3120             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3121 
3122     /** @hide */
3123     @IntDef(flag = true,
3124             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3125     @Retention(RetentionPolicy.SOURCE)
3126     public @interface FindViewFlags {}
3127 
3128     /**
3129      * Find views that render the specified text.
3130      *
3131      * @see #findViewsWithText(ArrayList, CharSequence, int)
3132      */
3133     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3134 
3135     /**
3136      * Find find views that contain the specified content description.
3137      *
3138      * @see #findViewsWithText(ArrayList, CharSequence, int)
3139      */
3140     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3141 
3142     /**
3143      * Find views that contain {@link AccessibilityNodeProvider}. Such
3144      * a View is a root of virtual view hierarchy and may contain the searched
3145      * text. If this flag is set Views with providers are automatically
3146      * added and it is a responsibility of the client to call the APIs of
3147      * the provider to determine whether the virtual tree rooted at this View
3148      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3149      * representing the virtual views with this text.
3150      *
3151      * @see #findViewsWithText(ArrayList, CharSequence, int)
3152      *
3153      * @hide
3154      */
3155     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3156 
3157     /**
3158      * The undefined cursor position.
3159      *
3160      * @hide
3161      */
3162     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3163 
3164     /**
3165      * Indicates that the screen has changed state and is now off.
3166      *
3167      * @see #onScreenStateChanged(int)
3168      */
3169     public static final int SCREEN_STATE_OFF = 0x0;
3170 
3171     /**
3172      * Indicates that the screen has changed state and is now on.
3173      *
3174      * @see #onScreenStateChanged(int)
3175      */
3176     public static final int SCREEN_STATE_ON = 0x1;
3177 
3178     /**
3179      * Indicates no axis of view scrolling.
3180      */
3181     public static final int SCROLL_AXIS_NONE = 0;
3182 
3183     /**
3184      * Indicates scrolling along the horizontal axis.
3185      */
3186     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3187 
3188     /**
3189      * Indicates scrolling along the vertical axis.
3190      */
3191     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3192 
3193     /**
3194      * Controls the over-scroll mode for this view.
3195      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3196      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3197      * and {@link #OVER_SCROLL_NEVER}.
3198      */
3199     private int mOverScrollMode;
3200 
3201     /**
3202      * The parent this view is attached to.
3203      * {@hide}
3204      *
3205      * @see #getParent()
3206      */
3207     protected ViewParent mParent;
3208 
3209     /**
3210      * {@hide}
3211      */
3212     AttachInfo mAttachInfo;
3213 
3214     /**
3215      * {@hide}
3216      */
3217     @ViewDebug.ExportedProperty(flagMapping = {
3218         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3219                 name = "FORCE_LAYOUT"),
3220         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3221                 name = "LAYOUT_REQUIRED"),
3222         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3223             name = "DRAWING_CACHE_INVALID", outputIf = false),
3224         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3225         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3226         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3227         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3228     }, formatToHexString = true)
3229     int mPrivateFlags;
3230     int mPrivateFlags2;
3231     int mPrivateFlags3;
3232 
3233     /**
3234      * This view's request for the visibility of the status bar.
3235      * @hide
3236      */
3237     @ViewDebug.ExportedProperty(flagMapping = {
3238         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3239                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3240                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3241         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3242                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3243                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3244         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3245                                 equals = SYSTEM_UI_FLAG_VISIBLE,
3246                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3247     }, formatToHexString = true)
3248     int mSystemUiVisibility;
3249 
3250     /**
3251      * Reference count for transient state.
3252      * @see #setHasTransientState(boolean)
3253      */
3254     int mTransientStateCount = 0;
3255 
3256     /**
3257      * Count of how many windows this view has been attached to.
3258      */
3259     int mWindowAttachCount;
3260 
3261     /**
3262      * The layout parameters associated with this view and used by the parent
3263      * {@link android.view.ViewGroup} to determine how this view should be
3264      * laid out.
3265      * {@hide}
3266      */
3267     protected ViewGroup.LayoutParams mLayoutParams;
3268 
3269     /**
3270      * The view flags hold various views states.
3271      * {@hide}
3272      */
3273     @ViewDebug.ExportedProperty(formatToHexString = true)
3274     int mViewFlags;
3275 
3276     static class TransformationInfo {
3277         /**
3278          * The transform matrix for the View. This transform is calculated internally
3279          * based on the translation, rotation, and scale properties.
3280          *
3281          * Do *not* use this variable directly; instead call getMatrix(), which will
3282          * load the value from the View's RenderNode.
3283          */
3284         private final Matrix mMatrix = new Matrix();
3285 
3286         /**
3287          * The inverse transform matrix for the View. This transform is calculated
3288          * internally based on the translation, rotation, and scale properties.
3289          *
3290          * Do *not* use this variable directly; instead call getInverseMatrix(),
3291          * which will load the value from the View's RenderNode.
3292          */
3293         private Matrix mInverseMatrix;
3294 
3295         /**
3296          * The opacity of the View. This is a value from 0 to 1, where 0 means
3297          * completely transparent and 1 means completely opaque.
3298          */
3299         @ViewDebug.ExportedProperty
3300         float mAlpha = 1f;
3301 
3302         /**
3303          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3304          * property only used by transitions, which is composited with the other alpha
3305          * values to calculate the final visual alpha value.
3306          */
3307         float mTransitionAlpha = 1f;
3308     }
3309 
3310     TransformationInfo mTransformationInfo;
3311 
3312     /**
3313      * Current clip bounds. to which all drawing of this view are constrained.
3314      */
3315     Rect mClipBounds = null;
3316 
3317     private boolean mLastIsOpaque;
3318 
3319     /**
3320      * The distance in pixels from the left edge of this view's parent
3321      * to the left edge of this view.
3322      * {@hide}
3323      */
3324     @ViewDebug.ExportedProperty(category = "layout")
3325     protected int mLeft;
3326     /**
3327      * The distance in pixels from the left edge of this view's parent
3328      * to the right edge of this view.
3329      * {@hide}
3330      */
3331     @ViewDebug.ExportedProperty(category = "layout")
3332     protected int mRight;
3333     /**
3334      * The distance in pixels from the top edge of this view's parent
3335      * to the top edge of this view.
3336      * {@hide}
3337      */
3338     @ViewDebug.ExportedProperty(category = "layout")
3339     protected int mTop;
3340     /**
3341      * The distance in pixels from the top edge of this view's parent
3342      * to the bottom edge of this view.
3343      * {@hide}
3344      */
3345     @ViewDebug.ExportedProperty(category = "layout")
3346     protected int mBottom;
3347 
3348     /**
3349      * The offset, in pixels, by which the content of this view is scrolled
3350      * horizontally.
3351      * {@hide}
3352      */
3353     @ViewDebug.ExportedProperty(category = "scrolling")
3354     protected int mScrollX;
3355     /**
3356      * The offset, in pixels, by which the content of this view is scrolled
3357      * vertically.
3358      * {@hide}
3359      */
3360     @ViewDebug.ExportedProperty(category = "scrolling")
3361     protected int mScrollY;
3362 
3363     /**
3364      * The left padding in pixels, that is the distance in pixels between the
3365      * left edge of this view and the left edge of its content.
3366      * {@hide}
3367      */
3368     @ViewDebug.ExportedProperty(category = "padding")
3369     protected int mPaddingLeft = 0;
3370     /**
3371      * The right padding in pixels, that is the distance in pixels between the
3372      * right edge of this view and the right edge of its content.
3373      * {@hide}
3374      */
3375     @ViewDebug.ExportedProperty(category = "padding")
3376     protected int mPaddingRight = 0;
3377     /**
3378      * The top padding in pixels, that is the distance in pixels between the
3379      * top edge of this view and the top edge of its content.
3380      * {@hide}
3381      */
3382     @ViewDebug.ExportedProperty(category = "padding")
3383     protected int mPaddingTop;
3384     /**
3385      * The bottom padding in pixels, that is the distance in pixels between the
3386      * bottom edge of this view and the bottom edge of its content.
3387      * {@hide}
3388      */
3389     @ViewDebug.ExportedProperty(category = "padding")
3390     protected int mPaddingBottom;
3391 
3392     /**
3393      * The layout insets in pixels, that is the distance in pixels between the
3394      * visible edges of this view its bounds.
3395      */
3396     private Insets mLayoutInsets;
3397 
3398     /**
3399      * Briefly describes the view and is primarily used for accessibility support.
3400      */
3401     private CharSequence mContentDescription;
3402 
3403     /**
3404      * Specifies the id of a view for which this view serves as a label for
3405      * accessibility purposes.
3406      */
3407     private int mLabelForId = View.NO_ID;
3408 
3409     /**
3410      * Predicate for matching labeled view id with its label for
3411      * accessibility purposes.
3412      */
3413     private MatchLabelForPredicate mMatchLabelForPredicate;
3414 
3415     /**
3416      * Specifies a view before which this one is visited in accessibility traversal.
3417      */
3418     private int mAccessibilityTraversalBeforeId = NO_ID;
3419 
3420     /**
3421      * Specifies a view after which this one is visited in accessibility traversal.
3422      */
3423     private int mAccessibilityTraversalAfterId = NO_ID;
3424 
3425     /**
3426      * Predicate for matching a view by its id.
3427      */
3428     private MatchIdPredicate mMatchIdPredicate;
3429 
3430     /**
3431      * Cache the paddingRight set by the user to append to the scrollbar's size.
3432      *
3433      * @hide
3434      */
3435     @ViewDebug.ExportedProperty(category = "padding")
3436     protected int mUserPaddingRight;
3437 
3438     /**
3439      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3440      *
3441      * @hide
3442      */
3443     @ViewDebug.ExportedProperty(category = "padding")
3444     protected int mUserPaddingBottom;
3445 
3446     /**
3447      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3448      *
3449      * @hide
3450      */
3451     @ViewDebug.ExportedProperty(category = "padding")
3452     protected int mUserPaddingLeft;
3453 
3454     /**
3455      * Cache the paddingStart set by the user to append to the scrollbar's size.
3456      *
3457      */
3458     @ViewDebug.ExportedProperty(category = "padding")
3459     int mUserPaddingStart;
3460 
3461     /**
3462      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3463      *
3464      */
3465     @ViewDebug.ExportedProperty(category = "padding")
3466     int mUserPaddingEnd;
3467 
3468     /**
3469      * Cache initial left padding.
3470      *
3471      * @hide
3472      */
3473     int mUserPaddingLeftInitial;
3474 
3475     /**
3476      * Cache initial right padding.
3477      *
3478      * @hide
3479      */
3480     int mUserPaddingRightInitial;
3481 
3482     /**
3483      * Default undefined padding
3484      */
3485     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3486 
3487     /**
3488      * Cache if a left padding has been defined
3489      */
3490     private boolean mLeftPaddingDefined = false;
3491 
3492     /**
3493      * Cache if a right padding has been defined
3494      */
3495     private boolean mRightPaddingDefined = false;
3496 
3497     /**
3498      * @hide
3499      */
3500     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3501     /**
3502      * @hide
3503      */
3504     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3505 
3506     private LongSparseLongArray mMeasureCache;
3507 
3508     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3509     private Drawable mBackground;
3510     private TintInfo mBackgroundTint;
3511 
3512     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3513     private ForegroundInfo mForegroundInfo;
3514 
3515     private Drawable mScrollIndicatorDrawable;
3516 
3517     /**
3518      * RenderNode used for backgrounds.
3519      * <p>
3520      * When non-null and valid, this is expected to contain an up-to-date copy
3521      * of the background drawable. It is cleared on temporary detach, and reset
3522      * on cleanup.
3523      */
3524     private RenderNode mBackgroundRenderNode;
3525 
3526     private int mBackgroundResource;
3527     private boolean mBackgroundSizeChanged;
3528 
3529     private String mTransitionName;
3530 
3531     static class TintInfo {
3532         ColorStateList mTintList;
3533         PorterDuff.Mode mTintMode;
3534         boolean mHasTintMode;
3535         boolean mHasTintList;
3536     }
3537 
3538     private static class ForegroundInfo {
3539         private Drawable mDrawable;
3540         private TintInfo mTintInfo;
3541         private int mGravity = Gravity.FILL;
3542         private boolean mInsidePadding = true;
3543         private boolean mBoundsChanged = true;
3544         private final Rect mSelfBounds = new Rect();
3545         private final Rect mOverlayBounds = new Rect();
3546     }
3547 
3548     static class ListenerInfo {
3549         /**
3550          * Listener used to dispatch focus change events.
3551          * This field should be made private, so it is hidden from the SDK.
3552          * {@hide}
3553          */
3554         protected OnFocusChangeListener mOnFocusChangeListener;
3555 
3556         /**
3557          * Listeners for layout change events.
3558          */
3559         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3560 
3561         protected OnScrollChangeListener mOnScrollChangeListener;
3562 
3563         /**
3564          * Listeners for attach events.
3565          */
3566         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3567 
3568         /**
3569          * Listener used to dispatch click events.
3570          * This field should be made private, so it is hidden from the SDK.
3571          * {@hide}
3572          */
3573         public OnClickListener mOnClickListener;
3574 
3575         /**
3576          * Listener used to dispatch long click events.
3577          * This field should be made private, so it is hidden from the SDK.
3578          * {@hide}
3579          */
3580         protected OnLongClickListener mOnLongClickListener;
3581 
3582         /**
3583          * Listener used to dispatch context click events. This field should be made private, so it
3584          * is hidden from the SDK.
3585          * {@hide}
3586          */
3587         protected OnContextClickListener mOnContextClickListener;
3588 
3589         /**
3590          * Listener used to build the context menu.
3591          * This field should be made private, so it is hidden from the SDK.
3592          * {@hide}
3593          */
3594         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3595 
3596         private OnKeyListener mOnKeyListener;
3597 
3598         private OnTouchListener mOnTouchListener;
3599 
3600         private OnHoverListener mOnHoverListener;
3601 
3602         private OnGenericMotionListener mOnGenericMotionListener;
3603 
3604         private OnDragListener mOnDragListener;
3605 
3606         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3607 
3608         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3609     }
3610 
3611     ListenerInfo mListenerInfo;
3612 
3613     // Temporary values used to hold (x,y) coordinates when delegating from the
3614     // two-arg performLongClick() method to the legacy no-arg version.
3615     private float mLongClickX = Float.NaN;
3616     private float mLongClickY = Float.NaN;
3617 
3618     /**
3619      * The application environment this view lives in.
3620      * This field should be made private, so it is hidden from the SDK.
3621      * {@hide}
3622      */
3623     @ViewDebug.ExportedProperty(deepExport = true)
3624     protected Context mContext;
3625 
3626     private final Resources mResources;
3627 
3628     private ScrollabilityCache mScrollCache;
3629 
3630     private int[] mDrawableState = null;
3631 
3632     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3633 
3634     /**
3635      * Animator that automatically runs based on state changes.
3636      */
3637     private StateListAnimator mStateListAnimator;
3638 
3639     /**
3640      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3641      * the user may specify which view to go to next.
3642      */
3643     private int mNextFocusLeftId = View.NO_ID;
3644 
3645     /**
3646      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3647      * the user may specify which view to go to next.
3648      */
3649     private int mNextFocusRightId = View.NO_ID;
3650 
3651     /**
3652      * When this view has focus and the next focus is {@link #FOCUS_UP},
3653      * the user may specify which view to go to next.
3654      */
3655     private int mNextFocusUpId = View.NO_ID;
3656 
3657     /**
3658      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3659      * the user may specify which view to go to next.
3660      */
3661     private int mNextFocusDownId = View.NO_ID;
3662 
3663     /**
3664      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3665      * the user may specify which view to go to next.
3666      */
3667     int mNextFocusForwardId = View.NO_ID;
3668 
3669     private CheckForLongPress mPendingCheckForLongPress;
3670     private CheckForTap mPendingCheckForTap = null;
3671     private PerformClick mPerformClick;
3672     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3673 
3674     private UnsetPressedState mUnsetPressedState;
3675 
3676     /**
3677      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3678      * up event while a long press is invoked as soon as the long press duration is reached, so
3679      * a long press could be performed before the tap is checked, in which case the tap's action
3680      * should not be invoked.
3681      */
3682     private boolean mHasPerformedLongPress;
3683 
3684     /**
3685      * Whether a context click button is currently pressed down. This is true when the stylus is
3686      * touching the screen and the primary button has been pressed, or if a mouse's right button is
3687      * pressed. This is false once the button is released or if the stylus has been lifted.
3688      */
3689     private boolean mInContextButtonPress;
3690 
3691     /**
3692      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3693      * true after a stylus button press has occured, when the next up event should not be recognized
3694      * as a tap.
3695      */
3696     private boolean mIgnoreNextUpEvent;
3697 
3698     /**
3699      * The minimum height of the view. We'll try our best to have the height
3700      * of this view to at least this amount.
3701      */
3702     @ViewDebug.ExportedProperty(category = "measurement")
3703     private int mMinHeight;
3704 
3705     /**
3706      * The minimum width of the view. We'll try our best to have the width
3707      * of this view to at least this amount.
3708      */
3709     @ViewDebug.ExportedProperty(category = "measurement")
3710     private int mMinWidth;
3711 
3712     /**
3713      * The delegate to handle touch events that are physically in this view
3714      * but should be handled by another view.
3715      */
3716     private TouchDelegate mTouchDelegate = null;
3717 
3718     /**
3719      * Solid color to use as a background when creating the drawing cache. Enables
3720      * the cache to use 16 bit bitmaps instead of 32 bit.
3721      */
3722     private int mDrawingCacheBackgroundColor = 0;
3723 
3724     /**
3725      * Special tree observer used when mAttachInfo is null.
3726      */
3727     private ViewTreeObserver mFloatingTreeObserver;
3728 
3729     /**
3730      * Cache the touch slop from the context that created the view.
3731      */
3732     private int mTouchSlop;
3733 
3734     /**
3735      * Object that handles automatic animation of view properties.
3736      */
3737     private ViewPropertyAnimator mAnimator = null;
3738 
3739     /**
3740      * List of registered FrameMetricsObservers.
3741      */
3742     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3743 
3744     /**
3745      * Flag indicating that a drag can cross window boundaries.  When
3746      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3747      * with this flag set, all visible applications will be able to participate
3748      * in the drag operation and receive the dragged content.
3749      *
3750      * If this is the only flag set, then the drag recipient will only have access to text data
3751      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3752      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
3753      */
3754     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3755 
3756     /**
3757      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3758      * request read access to the content URI(s) contained in the {@link ClipData} object.
3759      * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3760      */
3761     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3762 
3763     /**
3764      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3765      * request write access to the content URI(s) contained in the {@link ClipData} object.
3766      * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3767      */
3768     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3769 
3770     /**
3771      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3772      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3773      * reboots until explicitly revoked with
3774      * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3775      * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3776      */
3777     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3778             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3779 
3780     /**
3781      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3782      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3783      * match against the original granted URI.
3784      * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3785      */
3786     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3787             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3788 
3789     /**
3790      * Flag indicating that the drag shadow will be opaque.  When
3791      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3792      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3793      */
3794     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3795 
3796     /**
3797      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3798      */
3799     private float mVerticalScrollFactor;
3800 
3801     /**
3802      * Position of the vertical scroll bar.
3803      */
3804     private int mVerticalScrollbarPosition;
3805 
3806     /**
3807      * Position the scroll bar at the default position as determined by the system.
3808      */
3809     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3810 
3811     /**
3812      * Position the scroll bar along the left edge.
3813      */
3814     public static final int SCROLLBAR_POSITION_LEFT = 1;
3815 
3816     /**
3817      * Position the scroll bar along the right edge.
3818      */
3819     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3820 
3821     /**
3822      * Indicates that the view does not have a layer.
3823      *
3824      * @see #getLayerType()
3825      * @see #setLayerType(int, android.graphics.Paint)
3826      * @see #LAYER_TYPE_SOFTWARE
3827      * @see #LAYER_TYPE_HARDWARE
3828      */
3829     public static final int LAYER_TYPE_NONE = 0;
3830 
3831     /**
3832      * <p>Indicates that the view has a software layer. A software layer is backed
3833      * by a bitmap and causes the view to be rendered using Android's software
3834      * rendering pipeline, even if hardware acceleration is enabled.</p>
3835      *
3836      * <p>Software layers have various usages:</p>
3837      * <p>When the application is not using hardware acceleration, a software layer
3838      * is useful to apply a specific color filter and/or blending mode and/or
3839      * translucency to a view and all its children.</p>
3840      * <p>When the application is using hardware acceleration, a software layer
3841      * is useful to render drawing primitives not supported by the hardware
3842      * accelerated pipeline. It can also be used to cache a complex view tree
3843      * into a texture and reduce the complexity of drawing operations. For instance,
3844      * when animating a complex view tree with a translation, a software layer can
3845      * be used to render the view tree only once.</p>
3846      * <p>Software layers should be avoided when the affected view tree updates
3847      * often. Every update will require to re-render the software layer, which can
3848      * potentially be slow (particularly when hardware acceleration is turned on
3849      * since the layer will have to be uploaded into a hardware texture after every
3850      * update.)</p>
3851      *
3852      * @see #getLayerType()
3853      * @see #setLayerType(int, android.graphics.Paint)
3854      * @see #LAYER_TYPE_NONE
3855      * @see #LAYER_TYPE_HARDWARE
3856      */
3857     public static final int LAYER_TYPE_SOFTWARE = 1;
3858 
3859     /**
3860      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3861      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3862      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3863      * rendering pipeline, but only if hardware acceleration is turned on for the
3864      * view hierarchy. When hardware acceleration is turned off, hardware layers
3865      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3866      *
3867      * <p>A hardware layer is useful to apply a specific color filter and/or
3868      * blending mode and/or translucency to a view and all its children.</p>
3869      * <p>A hardware layer can be used to cache a complex view tree into a
3870      * texture and reduce the complexity of drawing operations. For instance,
3871      * when animating a complex view tree with a translation, a hardware layer can
3872      * be used to render the view tree only once.</p>
3873      * <p>A hardware layer can also be used to increase the rendering quality when
3874      * rotation transformations are applied on a view. It can also be used to
3875      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3876      *
3877      * @see #getLayerType()
3878      * @see #setLayerType(int, android.graphics.Paint)
3879      * @see #LAYER_TYPE_NONE
3880      * @see #LAYER_TYPE_SOFTWARE
3881      */
3882     public static final int LAYER_TYPE_HARDWARE = 2;
3883 
3884     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3885             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3886             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3887             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3888     })
3889     int mLayerType = LAYER_TYPE_NONE;
3890     Paint mLayerPaint;
3891 
3892     /**
3893      * Set to true when drawing cache is enabled and cannot be created.
3894      *
3895      * @hide
3896      */
3897     public boolean mCachingFailed;
3898     private Bitmap mDrawingCache;
3899     private Bitmap mUnscaledDrawingCache;
3900 
3901     /**
3902      * RenderNode holding View properties, potentially holding a DisplayList of View content.
3903      * <p>
3904      * When non-null and valid, this is expected to contain an up-to-date copy
3905      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3906      * cleanup.
3907      */
3908     final RenderNode mRenderNode;
3909 
3910     /**
3911      * Set to true when the view is sending hover accessibility events because it
3912      * is the innermost hovered view.
3913      */
3914     private boolean mSendingHoverAccessibilityEvents;
3915 
3916     /**
3917      * Delegate for injecting accessibility functionality.
3918      */
3919     AccessibilityDelegate mAccessibilityDelegate;
3920 
3921     /**
3922      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3923      * and add/remove objects to/from the overlay directly through the Overlay methods.
3924      */
3925     ViewOverlay mOverlay;
3926 
3927     /**
3928      * The currently active parent view for receiving delegated nested scrolling events.
3929      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3930      * by {@link #stopNestedScroll()} at the same point where we clear
3931      * requestDisallowInterceptTouchEvent.
3932      */
3933     private ViewParent mNestedScrollingParent;
3934 
3935     /**
3936      * Consistency verifier for debugging purposes.
3937      * @hide
3938      */
3939     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3940             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3941                     new InputEventConsistencyVerifier(this, 0) : null;
3942 
3943     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3944 
3945     private int[] mTempNestedScrollConsumed;
3946 
3947     /**
3948      * An overlay is going to draw this View instead of being drawn as part of this
3949      * View's parent. mGhostView is the View in the Overlay that must be invalidated
3950      * when this view is invalidated.
3951      */
3952     GhostView mGhostView;
3953 
3954     /**
3955      * Holds pairs of adjacent attribute data: attribute name followed by its value.
3956      * @hide
3957      */
3958     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3959     public String[] mAttributes;
3960 
3961     /**
3962      * Maps a Resource id to its name.
3963      */
3964     private static SparseArray<String> mAttributeMap;
3965 
3966     /**
3967      * Queue of pending runnables. Used to postpone calls to post() until this
3968      * view is attached and has a handler.
3969      */
3970     private HandlerActionQueue mRunQueue;
3971 
3972     /**
3973      * The pointer icon when the mouse hovers on this view. The default is null.
3974      */
3975     private PointerIcon mPointerIcon;
3976 
3977     /**
3978      * @hide
3979      */
3980     String mStartActivityRequestWho;
3981 
3982     /**
3983      * Simple constructor to use when creating a view from code.
3984      *
3985      * @param context The Context the view is running in, through which it can
3986      *        access the current theme, resources, etc.
3987      */
View(Context context)3988     public View(Context context) {
3989         mContext = context;
3990         mResources = context != null ? context.getResources() : null;
3991         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3992         // Set some flags defaults
3993         mPrivateFlags2 =
3994                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3995                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3996                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3997                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3998                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3999                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4000         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4001         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4002         mUserPaddingStart = UNDEFINED_PADDING;
4003         mUserPaddingEnd = UNDEFINED_PADDING;
4004         mRenderNode = RenderNode.create(getClass().getName(), this);
4005 
4006         if (!sCompatibilityDone && context != null) {
4007             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4008 
4009             // Older apps may need this compatibility hack for measurement.
4010             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4011 
4012             // Older apps expect onMeasure() to always be called on a layout pass, regardless
4013             // of whether a layout was requested on that View.
4014             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4015 
4016             Canvas.sCompatibilityRestore = targetSdkVersion < M;
4017 
4018             // In M and newer, our widgets can pass a "hint" value in the size
4019             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4020             // know what the expected parent size is going to be, so e.g. list items can size
4021             // themselves at 1/3 the size of their container. It breaks older apps though,
4022             // specifically apps that use some popular open source libraries.
4023             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4024 
4025             // Old versions of the platform would give different results from
4026             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4027             // modes, so we always need to run an additional EXACTLY pass.
4028             sAlwaysRemeasureExactly = targetSdkVersion <= M;
4029 
4030             // Prior to N, layout params could change without requiring a
4031             // subsequent call to setLayoutParams() and they would usually
4032             // work. Partial layout breaks this assumption.
4033             sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4034 
4035             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4036             // On N+, we throw, but that breaks compatibility with apps that use these methods.
4037             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4038 
4039             sCompatibilityDone = true;
4040         }
4041     }
4042 
4043     /**
4044      * Constructor that is called when inflating a view from XML. This is called
4045      * when a view is being constructed from an XML file, supplying attributes
4046      * that were specified in the XML file. This version uses a default style of
4047      * 0, so the only attribute values applied are those in the Context's Theme
4048      * and the given AttributeSet.
4049      *
4050      * <p>
4051      * The method onFinishInflate() will be called after all children have been
4052      * added.
4053      *
4054      * @param context The Context the view is running in, through which it can
4055      *        access the current theme, resources, etc.
4056      * @param attrs The attributes of the XML tag that is inflating the view.
4057      * @see #View(Context, AttributeSet, int)
4058      */
4059     public View(Context context, @Nullable AttributeSet attrs) {
4060         this(context, attrs, 0);
4061     }
4062 
4063     /**
4064      * Perform inflation from XML and apply a class-specific base style from a
4065      * theme attribute. This constructor of View allows subclasses to use their
4066      * own base style when they are inflating. For example, a Button class's
4067      * constructor would call this version of the super class constructor and
4068      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4069      * allows the theme's button style to modify all of the base view attributes
4070      * (in particular its background) as well as the Button class's attributes.
4071      *
4072      * @param context The Context the view is running in, through which it can
4073      *        access the current theme, resources, etc.
4074      * @param attrs The attributes of the XML tag that is inflating the view.
4075      * @param defStyleAttr An attribute in the current theme that contains a
4076      *        reference to a style resource that supplies default values for
4077      *        the view. Can be 0 to not look for defaults.
4078      * @see #View(Context, AttributeSet)
4079      */
4080     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4081         this(context, attrs, defStyleAttr, 0);
4082     }
4083 
4084     /**
4085      * Perform inflation from XML and apply a class-specific base style from a
4086      * theme attribute or style resource. This constructor of View allows
4087      * subclasses to use their own base style when they are inflating.
4088      * <p>
4089      * When determining the final value of a particular attribute, there are
4090      * four inputs that come into play:
4091      * <ol>
4092      * <li>Any attribute values in the given AttributeSet.
4093      * <li>The style resource specified in the AttributeSet (named "style").
4094      * <li>The default style specified by <var>defStyleAttr</var>.
4095      * <li>The default style specified by <var>defStyleRes</var>.
4096      * <li>The base values in this theme.
4097      * </ol>
4098      * <p>
4099      * Each of these inputs is considered in-order, with the first listed taking
4100      * precedence over the following ones. In other words, if in the
4101      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4102      * , then the button's text will <em>always</em> be black, regardless of
4103      * what is specified in any of the styles.
4104      *
4105      * @param context The Context the view is running in, through which it can
4106      *        access the current theme, resources, etc.
4107      * @param attrs The attributes of the XML tag that is inflating the view.
4108      * @param defStyleAttr An attribute in the current theme that contains a
4109      *        reference to a style resource that supplies default values for
4110      *        the view. Can be 0 to not look for defaults.
4111      * @param defStyleRes A resource identifier of a style resource that
4112      *        supplies default values for the view, used only if
4113      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4114      *        to not look for defaults.
4115      * @see #View(Context, AttributeSet, int)
4116      */
4117     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4118         this(context);
4119 
4120         final TypedArray a = context.obtainStyledAttributes(
4121                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4122 
4123         if (mDebugViewAttributes) {
4124             saveAttributeData(attrs, a);
4125         }
4126 
4127         Drawable background = null;
4128 
4129         int leftPadding = -1;
4130         int topPadding = -1;
4131         int rightPadding = -1;
4132         int bottomPadding = -1;
4133         int startPadding = UNDEFINED_PADDING;
4134         int endPadding = UNDEFINED_PADDING;
4135 
4136         int padding = -1;
4137 
4138         int viewFlagValues = 0;
4139         int viewFlagMasks = 0;
4140 
4141         boolean setScrollContainer = false;
4142 
4143         int x = 0;
4144         int y = 0;
4145 
4146         float tx = 0;
4147         float ty = 0;
4148         float tz = 0;
4149         float elevation = 0;
4150         float rotation = 0;
4151         float rotationX = 0;
4152         float rotationY = 0;
4153         float sx = 1f;
4154         float sy = 1f;
4155         boolean transformSet = false;
4156 
4157         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4158         int overScrollMode = mOverScrollMode;
4159         boolean initializeScrollbars = false;
4160         boolean initializeScrollIndicators = false;
4161 
4162         boolean startPaddingDefined = false;
4163         boolean endPaddingDefined = false;
4164         boolean leftPaddingDefined = false;
4165         boolean rightPaddingDefined = false;
4166 
4167         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4168 
4169         final int N = a.getIndexCount();
4170         for (int i = 0; i < N; i++) {
4171             int attr = a.getIndex(i);
4172             switch (attr) {
4173                 case com.android.internal.R.styleable.View_background:
4174                     background = a.getDrawable(attr);
4175                     break;
4176                 case com.android.internal.R.styleable.View_padding:
4177                     padding = a.getDimensionPixelSize(attr, -1);
4178                     mUserPaddingLeftInitial = padding;
4179                     mUserPaddingRightInitial = padding;
4180                     leftPaddingDefined = true;
4181                     rightPaddingDefined = true;
4182                     break;
4183                  case com.android.internal.R.styleable.View_paddingLeft:
4184                     leftPadding = a.getDimensionPixelSize(attr, -1);
4185                     mUserPaddingLeftInitial = leftPadding;
4186                     leftPaddingDefined = true;
4187                     break;
4188                 case com.android.internal.R.styleable.View_paddingTop:
4189                     topPadding = a.getDimensionPixelSize(attr, -1);
4190                     break;
4191                 case com.android.internal.R.styleable.View_paddingRight:
4192                     rightPadding = a.getDimensionPixelSize(attr, -1);
4193                     mUserPaddingRightInitial = rightPadding;
4194                     rightPaddingDefined = true;
4195                     break;
4196                 case com.android.internal.R.styleable.View_paddingBottom:
4197                     bottomPadding = a.getDimensionPixelSize(attr, -1);
4198                     break;
4199                 case com.android.internal.R.styleable.View_paddingStart:
4200                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4201                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4202                     break;
4203                 case com.android.internal.R.styleable.View_paddingEnd:
4204                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4205                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4206                     break;
4207                 case com.android.internal.R.styleable.View_scrollX:
4208                     x = a.getDimensionPixelOffset(attr, 0);
4209                     break;
4210                 case com.android.internal.R.styleable.View_scrollY:
4211                     y = a.getDimensionPixelOffset(attr, 0);
4212                     break;
4213                 case com.android.internal.R.styleable.View_alpha:
4214                     setAlpha(a.getFloat(attr, 1f));
4215                     break;
4216                 case com.android.internal.R.styleable.View_transformPivotX:
4217                     setPivotX(a.getDimensionPixelOffset(attr, 0));
4218                     break;
4219                 case com.android.internal.R.styleable.View_transformPivotY:
4220                     setPivotY(a.getDimensionPixelOffset(attr, 0));
4221                     break;
4222                 case com.android.internal.R.styleable.View_translationX:
4223                     tx = a.getDimensionPixelOffset(attr, 0);
4224                     transformSet = true;
4225                     break;
4226                 case com.android.internal.R.styleable.View_translationY:
4227                     ty = a.getDimensionPixelOffset(attr, 0);
4228                     transformSet = true;
4229                     break;
4230                 case com.android.internal.R.styleable.View_translationZ:
4231                     tz = a.getDimensionPixelOffset(attr, 0);
4232                     transformSet = true;
4233                     break;
4234                 case com.android.internal.R.styleable.View_elevation:
4235                     elevation = a.getDimensionPixelOffset(attr, 0);
4236                     transformSet = true;
4237                     break;
4238                 case com.android.internal.R.styleable.View_rotation:
4239                     rotation = a.getFloat(attr, 0);
4240                     transformSet = true;
4241                     break;
4242                 case com.android.internal.R.styleable.View_rotationX:
4243                     rotationX = a.getFloat(attr, 0);
4244                     transformSet = true;
4245                     break;
4246                 case com.android.internal.R.styleable.View_rotationY:
4247                     rotationY = a.getFloat(attr, 0);
4248                     transformSet = true;
4249                     break;
4250                 case com.android.internal.R.styleable.View_scaleX:
4251                     sx = a.getFloat(attr, 1f);
4252                     transformSet = true;
4253                     break;
4254                 case com.android.internal.R.styleable.View_scaleY:
4255                     sy = a.getFloat(attr, 1f);
4256                     transformSet = true;
4257                     break;
4258                 case com.android.internal.R.styleable.View_id:
4259                     mID = a.getResourceId(attr, NO_ID);
4260                     break;
4261                 case com.android.internal.R.styleable.View_tag:
4262                     mTag = a.getText(attr);
4263                     break;
4264                 case com.android.internal.R.styleable.View_fitsSystemWindows:
4265                     if (a.getBoolean(attr, false)) {
4266                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
4267                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4268                     }
4269                     break;
4270                 case com.android.internal.R.styleable.View_focusable:
4271                     if (a.getBoolean(attr, false)) {
4272                         viewFlagValues |= FOCUSABLE;
4273                         viewFlagMasks |= FOCUSABLE_MASK;
4274                     }
4275                     break;
4276                 case com.android.internal.R.styleable.View_focusableInTouchMode:
4277                     if (a.getBoolean(attr, false)) {
4278                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4279                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4280                     }
4281                     break;
4282                 case com.android.internal.R.styleable.View_clickable:
4283                     if (a.getBoolean(attr, false)) {
4284                         viewFlagValues |= CLICKABLE;
4285                         viewFlagMasks |= CLICKABLE;
4286                     }
4287                     break;
4288                 case com.android.internal.R.styleable.View_longClickable:
4289                     if (a.getBoolean(attr, false)) {
4290                         viewFlagValues |= LONG_CLICKABLE;
4291                         viewFlagMasks |= LONG_CLICKABLE;
4292                     }
4293                     break;
4294                 case com.android.internal.R.styleable.View_contextClickable:
4295                     if (a.getBoolean(attr, false)) {
4296                         viewFlagValues |= CONTEXT_CLICKABLE;
4297                         viewFlagMasks |= CONTEXT_CLICKABLE;
4298                     }
4299                     break;
4300                 case com.android.internal.R.styleable.View_saveEnabled:
4301                     if (!a.getBoolean(attr, true)) {
4302                         viewFlagValues |= SAVE_DISABLED;
4303                         viewFlagMasks |= SAVE_DISABLED_MASK;
4304                     }
4305                     break;
4306                 case com.android.internal.R.styleable.View_duplicateParentState:
4307                     if (a.getBoolean(attr, false)) {
4308                         viewFlagValues |= DUPLICATE_PARENT_STATE;
4309                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
4310                     }
4311                     break;
4312                 case com.android.internal.R.styleable.View_visibility:
4313                     final int visibility = a.getInt(attr, 0);
4314                     if (visibility != 0) {
4315                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
4316                         viewFlagMasks |= VISIBILITY_MASK;
4317                     }
4318                     break;
4319                 case com.android.internal.R.styleable.View_layoutDirection:
4320                     // Clear any layout direction flags (included resolved bits) already set
4321                     mPrivateFlags2 &=
4322                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4323                     // Set the layout direction flags depending on the value of the attribute
4324                     final int layoutDirection = a.getInt(attr, -1);
4325                     final int value = (layoutDirection != -1) ?
4326                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4327                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4328                     break;
4329                 case com.android.internal.R.styleable.View_drawingCacheQuality:
4330                     final int cacheQuality = a.getInt(attr, 0);
4331                     if (cacheQuality != 0) {
4332                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4333                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4334                     }
4335                     break;
4336                 case com.android.internal.R.styleable.View_contentDescription:
4337                     setContentDescription(a.getString(attr));
4338                     break;
4339                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4340                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4341                     break;
4342                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4343                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4344                     break;
4345                 case com.android.internal.R.styleable.View_labelFor:
4346                     setLabelFor(a.getResourceId(attr, NO_ID));
4347                     break;
4348                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4349                     if (!a.getBoolean(attr, true)) {
4350                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4351                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4352                     }
4353                     break;
4354                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4355                     if (!a.getBoolean(attr, true)) {
4356                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4357                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4358                     }
4359                     break;
4360                 case R.styleable.View_scrollbars:
4361                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4362                     if (scrollbars != SCROLLBARS_NONE) {
4363                         viewFlagValues |= scrollbars;
4364                         viewFlagMasks |= SCROLLBARS_MASK;
4365                         initializeScrollbars = true;
4366                     }
4367                     break;
4368                 //noinspection deprecation
4369                 case R.styleable.View_fadingEdge:
4370                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4371                         // Ignore the attribute starting with ICS
4372                         break;
4373                     }
4374                     // With builds < ICS, fall through and apply fading edges
4375                 case R.styleable.View_requiresFadingEdge:
4376                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4377                     if (fadingEdge != FADING_EDGE_NONE) {
4378                         viewFlagValues |= fadingEdge;
4379                         viewFlagMasks |= FADING_EDGE_MASK;
4380                         initializeFadingEdgeInternal(a);
4381                     }
4382                     break;
4383                 case R.styleable.View_scrollbarStyle:
4384                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4385                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4386                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4387                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4388                     }
4389                     break;
4390                 case R.styleable.View_isScrollContainer:
4391                     setScrollContainer = true;
4392                     if (a.getBoolean(attr, false)) {
4393                         setScrollContainer(true);
4394                     }
4395                     break;
4396                 case com.android.internal.R.styleable.View_keepScreenOn:
4397                     if (a.getBoolean(attr, false)) {
4398                         viewFlagValues |= KEEP_SCREEN_ON;
4399                         viewFlagMasks |= KEEP_SCREEN_ON;
4400                     }
4401                     break;
4402                 case R.styleable.View_filterTouchesWhenObscured:
4403                     if (a.getBoolean(attr, false)) {
4404                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4405                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4406                     }
4407                     break;
4408                 case R.styleable.View_nextFocusLeft:
4409                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4410                     break;
4411                 case R.styleable.View_nextFocusRight:
4412                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4413                     break;
4414                 case R.styleable.View_nextFocusUp:
4415                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4416                     break;
4417                 case R.styleable.View_nextFocusDown:
4418                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4419                     break;
4420                 case R.styleable.View_nextFocusForward:
4421                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4422                     break;
4423                 case R.styleable.View_minWidth:
4424                     mMinWidth = a.getDimensionPixelSize(attr, 0);
4425                     break;
4426                 case R.styleable.View_minHeight:
4427                     mMinHeight = a.getDimensionPixelSize(attr, 0);
4428                     break;
4429                 case R.styleable.View_onClick:
4430                     if (context.isRestricted()) {
4431                         throw new IllegalStateException("The android:onClick attribute cannot "
4432                                 + "be used within a restricted context");
4433                     }
4434 
4435                     final String handlerName = a.getString(attr);
4436                     if (handlerName != null) {
4437                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4438                     }
4439                     break;
4440                 case R.styleable.View_overScrollMode:
4441                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4442                     break;
4443                 case R.styleable.View_verticalScrollbarPosition:
4444                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4445                     break;
4446                 case R.styleable.View_layerType:
4447                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4448                     break;
4449                 case R.styleable.View_textDirection:
4450                     // Clear any text direction flag already set
4451                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4452                     // Set the text direction flags depending on the value of the attribute
4453                     final int textDirection = a.getInt(attr, -1);
4454                     if (textDirection != -1) {
4455                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4456                     }
4457                     break;
4458                 case R.styleable.View_textAlignment:
4459                     // Clear any text alignment flag already set
4460                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4461                     // Set the text alignment flag depending on the value of the attribute
4462                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4463                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4464                     break;
4465                 case R.styleable.View_importantForAccessibility:
4466                     setImportantForAccessibility(a.getInt(attr,
4467                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4468                     break;
4469                 case R.styleable.View_accessibilityLiveRegion:
4470                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4471                     break;
4472                 case R.styleable.View_transitionName:
4473                     setTransitionName(a.getString(attr));
4474                     break;
4475                 case R.styleable.View_nestedScrollingEnabled:
4476                     setNestedScrollingEnabled(a.getBoolean(attr, false));
4477                     break;
4478                 case R.styleable.View_stateListAnimator:
4479                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4480                             a.getResourceId(attr, 0)));
4481                     break;
4482                 case R.styleable.View_backgroundTint:
4483                     // This will get applied later during setBackground().
4484                     if (mBackgroundTint == null) {
4485                         mBackgroundTint = new TintInfo();
4486                     }
4487                     mBackgroundTint.mTintList = a.getColorStateList(
4488                             R.styleable.View_backgroundTint);
4489                     mBackgroundTint.mHasTintList = true;
4490                     break;
4491                 case R.styleable.View_backgroundTintMode:
4492                     // This will get applied later during setBackground().
4493                     if (mBackgroundTint == null) {
4494                         mBackgroundTint = new TintInfo();
4495                     }
4496                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4497                             R.styleable.View_backgroundTintMode, -1), null);
4498                     mBackgroundTint.mHasTintMode = true;
4499                     break;
4500                 case R.styleable.View_outlineProvider:
4501                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4502                             PROVIDER_BACKGROUND));
4503                     break;
4504                 case R.styleable.View_foreground:
4505                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4506                         setForeground(a.getDrawable(attr));
4507                     }
4508                     break;
4509                 case R.styleable.View_foregroundGravity:
4510                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4511                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4512                     }
4513                     break;
4514                 case R.styleable.View_foregroundTintMode:
4515                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4516                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4517                     }
4518                     break;
4519                 case R.styleable.View_foregroundTint:
4520                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4521                         setForegroundTintList(a.getColorStateList(attr));
4522                     }
4523                     break;
4524                 case R.styleable.View_foregroundInsidePadding:
4525                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4526                         if (mForegroundInfo == null) {
4527                             mForegroundInfo = new ForegroundInfo();
4528                         }
4529                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4530                                 mForegroundInfo.mInsidePadding);
4531                     }
4532                     break;
4533                 case R.styleable.View_scrollIndicators:
4534                     final int scrollIndicators =
4535                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4536                                     & SCROLL_INDICATORS_PFLAG3_MASK;
4537                     if (scrollIndicators != 0) {
4538                         mPrivateFlags3 |= scrollIndicators;
4539                         initializeScrollIndicators = true;
4540                     }
4541                     break;
4542                 case R.styleable.View_pointerIcon:
4543                     final int resourceId = a.getResourceId(attr, 0);
4544                     if (resourceId != 0) {
4545                         setPointerIcon(PointerIcon.load(
4546                                 context.getResources(), resourceId));
4547                     } else {
4548                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4549                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4550                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4551                         }
4552                     }
4553                     break;
4554                 case R.styleable.View_forceHasOverlappingRendering:
4555                     if (a.peekValue(attr) != null) {
4556                         forceHasOverlappingRendering(a.getBoolean(attr, true));
4557                     }
4558                     break;
4559 
4560             }
4561         }
4562 
4563         setOverScrollMode(overScrollMode);
4564 
4565         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4566         // the resolved layout direction). Those cached values will be used later during padding
4567         // resolution.
4568         mUserPaddingStart = startPadding;
4569         mUserPaddingEnd = endPadding;
4570 
4571         if (background != null) {
4572             setBackground(background);
4573         }
4574 
4575         // setBackground above will record that padding is currently provided by the background.
4576         // If we have padding specified via xml, record that here instead and use it.
4577         mLeftPaddingDefined = leftPaddingDefined;
4578         mRightPaddingDefined = rightPaddingDefined;
4579 
4580         if (padding >= 0) {
4581             leftPadding = padding;
4582             topPadding = padding;
4583             rightPadding = padding;
4584             bottomPadding = padding;
4585             mUserPaddingLeftInitial = padding;
4586             mUserPaddingRightInitial = padding;
4587         }
4588 
4589         if (isRtlCompatibilityMode()) {
4590             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4591             // left / right padding are used if defined (meaning here nothing to do). If they are not
4592             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4593             // start / end and resolve them as left / right (layout direction is not taken into account).
4594             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4595             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4596             // defined.
4597             if (!mLeftPaddingDefined && startPaddingDefined) {
4598                 leftPadding = startPadding;
4599             }
4600             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4601             if (!mRightPaddingDefined && endPaddingDefined) {
4602                 rightPadding = endPadding;
4603             }
4604             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4605         } else {
4606             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4607             // values defined. Otherwise, left /right values are used.
4608             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4609             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4610             // defined.
4611             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4612 
4613             if (mLeftPaddingDefined && !hasRelativePadding) {
4614                 mUserPaddingLeftInitial = leftPadding;
4615             }
4616             if (mRightPaddingDefined && !hasRelativePadding) {
4617                 mUserPaddingRightInitial = rightPadding;
4618             }
4619         }
4620 
4621         internalSetPadding(
4622                 mUserPaddingLeftInitial,
4623                 topPadding >= 0 ? topPadding : mPaddingTop,
4624                 mUserPaddingRightInitial,
4625                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4626 
4627         if (viewFlagMasks != 0) {
4628             setFlags(viewFlagValues, viewFlagMasks);
4629         }
4630 
4631         if (initializeScrollbars) {
4632             initializeScrollbarsInternal(a);
4633         }
4634 
4635         if (initializeScrollIndicators) {
4636             initializeScrollIndicatorsInternal();
4637         }
4638 
4639         a.recycle();
4640 
4641         // Needs to be called after mViewFlags is set
4642         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4643             recomputePadding();
4644         }
4645 
4646         if (x != 0 || y != 0) {
4647             scrollTo(x, y);
4648         }
4649 
4650         if (transformSet) {
4651             setTranslationX(tx);
4652             setTranslationY(ty);
4653             setTranslationZ(tz);
4654             setElevation(elevation);
4655             setRotation(rotation);
4656             setRotationX(rotationX);
4657             setRotationY(rotationY);
4658             setScaleX(sx);
4659             setScaleY(sy);
4660         }
4661 
4662         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4663             setScrollContainer(true);
4664         }
4665 
4666         computeOpaqueFlags();
4667     }
4668 
4669     /**
4670      * An implementation of OnClickListener that attempts to lazily load a
4671      * named click handling method from a parent or ancestor context.
4672      */
4673     private static class DeclaredOnClickListener implements OnClickListener {
4674         private final View mHostView;
4675         private final String mMethodName;
4676 
4677         private Method mResolvedMethod;
4678         private Context mResolvedContext;
4679 
DeclaredOnClickListener(@onNull View hostView, @NonNull String methodName)4680         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4681             mHostView = hostView;
4682             mMethodName = methodName;
4683         }
4684 
4685         @Override
onClick(@onNull View v)4686         public void onClick(@NonNull View v) {
4687             if (mResolvedMethod == null) {
4688                 resolveMethod(mHostView.getContext(), mMethodName);
4689             }
4690 
4691             try {
4692                 mResolvedMethod.invoke(mResolvedContext, v);
4693             } catch (IllegalAccessException e) {
4694                 throw new IllegalStateException(
4695                         "Could not execute non-public method for android:onClick", e);
4696             } catch (InvocationTargetException e) {
4697                 throw new IllegalStateException(
4698                         "Could not execute method for android:onClick", e);
4699             }
4700         }
4701 
4702         @NonNull
resolveMethod(@ullable Context context, @NonNull String name)4703         private void resolveMethod(@Nullable Context context, @NonNull String name) {
4704             while (context != null) {
4705                 try {
4706                     if (!context.isRestricted()) {
4707                         final Method method = context.getClass().getMethod(mMethodName, View.class);
4708                         if (method != null) {
4709                             mResolvedMethod = method;
4710                             mResolvedContext = context;
4711                             return;
4712                         }
4713                     }
4714                 } catch (NoSuchMethodException e) {
4715                     // Failed to find method, keep searching up the hierarchy.
4716                 }
4717 
4718                 if (context instanceof ContextWrapper) {
4719                     context = ((ContextWrapper) context).getBaseContext();
4720                 } else {
4721                     // Can't search up the hierarchy, null out and fail.
4722                     context = null;
4723                 }
4724             }
4725 
4726             final int id = mHostView.getId();
4727             final String idText = id == NO_ID ? "" : " with id '"
4728                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4729             throw new IllegalStateException("Could not find method " + mMethodName
4730                     + "(View) in a parent or ancestor Context for android:onClick "
4731                     + "attribute defined on view " + mHostView.getClass() + idText);
4732         }
4733     }
4734 
4735     /**
4736      * Non-public constructor for use in testing
4737      */
View()4738     View() {
4739         mResources = null;
4740         mRenderNode = RenderNode.create(getClass().getName(), this);
4741     }
4742 
getAttributeMap()4743     private static SparseArray<String> getAttributeMap() {
4744         if (mAttributeMap == null) {
4745             mAttributeMap = new SparseArray<>();
4746         }
4747         return mAttributeMap;
4748     }
4749 
saveAttributeData(@ullable AttributeSet attrs, @NonNull TypedArray t)4750     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4751         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4752         final int indexCount = t.getIndexCount();
4753         final String[] attributes = new String[(attrsCount + indexCount) * 2];
4754 
4755         int i = 0;
4756 
4757         // Store raw XML attributes.
4758         for (int j = 0; j < attrsCount; ++j) {
4759             attributes[i] = attrs.getAttributeName(j);
4760             attributes[i + 1] = attrs.getAttributeValue(j);
4761             i += 2;
4762         }
4763 
4764         // Store resolved styleable attributes.
4765         final Resources res = t.getResources();
4766         final SparseArray<String> attributeMap = getAttributeMap();
4767         for (int j = 0; j < indexCount; ++j) {
4768             final int index = t.getIndex(j);
4769             if (!t.hasValueOrEmpty(index)) {
4770                 // Value is undefined. Skip it.
4771                 continue;
4772             }
4773 
4774             final int resourceId = t.getResourceId(index, 0);
4775             if (resourceId == 0) {
4776                 // Value is not a reference. Skip it.
4777                 continue;
4778             }
4779 
4780             String resourceName = attributeMap.get(resourceId);
4781             if (resourceName == null) {
4782                 try {
4783                     resourceName = res.getResourceName(resourceId);
4784                 } catch (Resources.NotFoundException e) {
4785                     resourceName = "0x" + Integer.toHexString(resourceId);
4786                 }
4787                 attributeMap.put(resourceId, resourceName);
4788             }
4789 
4790             attributes[i] = resourceName;
4791             attributes[i + 1] = t.getString(index);
4792             i += 2;
4793         }
4794 
4795         // Trim to fit contents.
4796         final String[] trimmed = new String[i];
4797         System.arraycopy(attributes, 0, trimmed, 0, i);
4798         mAttributes = trimmed;
4799     }
4800 
toString()4801     public String toString() {
4802         StringBuilder out = new StringBuilder(128);
4803         out.append(getClass().getName());
4804         out.append('{');
4805         out.append(Integer.toHexString(System.identityHashCode(this)));
4806         out.append(' ');
4807         switch (mViewFlags&VISIBILITY_MASK) {
4808             case VISIBLE: out.append('V'); break;
4809             case INVISIBLE: out.append('I'); break;
4810             case GONE: out.append('G'); break;
4811             default: out.append('.'); break;
4812         }
4813         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4814         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4815         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4816         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4817         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4818         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4819         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4820         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4821         out.append(' ');
4822         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4823         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4824         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4825         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4826             out.append('p');
4827         } else {
4828             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4829         }
4830         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4831         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4832         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4833         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4834         out.append(' ');
4835         out.append(mLeft);
4836         out.append(',');
4837         out.append(mTop);
4838         out.append('-');
4839         out.append(mRight);
4840         out.append(',');
4841         out.append(mBottom);
4842         final int id = getId();
4843         if (id != NO_ID) {
4844             out.append(" #");
4845             out.append(Integer.toHexString(id));
4846             final Resources r = mResources;
4847             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4848                 try {
4849                     String pkgname;
4850                     switch (id&0xff000000) {
4851                         case 0x7f000000:
4852                             pkgname="app";
4853                             break;
4854                         case 0x01000000:
4855                             pkgname="android";
4856                             break;
4857                         default:
4858                             pkgname = r.getResourcePackageName(id);
4859                             break;
4860                     }
4861                     String typename = r.getResourceTypeName(id);
4862                     String entryname = r.getResourceEntryName(id);
4863                     out.append(" ");
4864                     out.append(pkgname);
4865                     out.append(":");
4866                     out.append(typename);
4867                     out.append("/");
4868                     out.append(entryname);
4869                 } catch (Resources.NotFoundException e) {
4870                 }
4871             }
4872         }
4873         out.append("}");
4874         return out.toString();
4875     }
4876 
4877     /**
4878      * <p>
4879      * Initializes the fading edges from a given set of styled attributes. This
4880      * method should be called by subclasses that need fading edges and when an
4881      * instance of these subclasses is created programmatically rather than
4882      * being inflated from XML. This method is automatically called when the XML
4883      * is inflated.
4884      * </p>
4885      *
4886      * @param a the styled attributes set to initialize the fading edges from
4887      *
4888      * @removed
4889      */
initializeFadingEdge(TypedArray a)4890     protected void initializeFadingEdge(TypedArray a) {
4891         // This method probably shouldn't have been included in the SDK to begin with.
4892         // It relies on 'a' having been initialized using an attribute filter array that is
4893         // not publicly available to the SDK. The old method has been renamed
4894         // to initializeFadingEdgeInternal and hidden for framework use only;
4895         // this one initializes using defaults to make it safe to call for apps.
4896 
4897         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4898 
4899         initializeFadingEdgeInternal(arr);
4900 
4901         arr.recycle();
4902     }
4903 
4904     /**
4905      * <p>
4906      * Initializes the fading edges from a given set of styled attributes. This
4907      * method should be called by subclasses that need fading edges and when an
4908      * instance of these subclasses is created programmatically rather than
4909      * being inflated from XML. This method is automatically called when the XML
4910      * is inflated.
4911      * </p>
4912      *
4913      * @param a the styled attributes set to initialize the fading edges from
4914      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4915      */
initializeFadingEdgeInternal(TypedArray a)4916     protected void initializeFadingEdgeInternal(TypedArray a) {
4917         initScrollCache();
4918 
4919         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4920                 R.styleable.View_fadingEdgeLength,
4921                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4922     }
4923 
4924     /**
4925      * Returns the size of the vertical faded edges used to indicate that more
4926      * content in this view is visible.
4927      *
4928      * @return The size in pixels of the vertical faded edge or 0 if vertical
4929      *         faded edges are not enabled for this view.
4930      * @attr ref android.R.styleable#View_fadingEdgeLength
4931      */
getVerticalFadingEdgeLength()4932     public int getVerticalFadingEdgeLength() {
4933         if (isVerticalFadingEdgeEnabled()) {
4934             ScrollabilityCache cache = mScrollCache;
4935             if (cache != null) {
4936                 return cache.fadingEdgeLength;
4937             }
4938         }
4939         return 0;
4940     }
4941 
4942     /**
4943      * Set the size of the faded edge used to indicate that more content in this
4944      * view is available.  Will not change whether the fading edge is enabled; use
4945      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4946      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4947      * for the vertical or horizontal fading edges.
4948      *
4949      * @param length The size in pixels of the faded edge used to indicate that more
4950      *        content in this view is visible.
4951      */
setFadingEdgeLength(int length)4952     public void setFadingEdgeLength(int length) {
4953         initScrollCache();
4954         mScrollCache.fadingEdgeLength = length;
4955     }
4956 
4957     /**
4958      * Returns the size of the horizontal faded edges used to indicate that more
4959      * content in this view is visible.
4960      *
4961      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4962      *         faded edges are not enabled for this view.
4963      * @attr ref android.R.styleable#View_fadingEdgeLength
4964      */
getHorizontalFadingEdgeLength()4965     public int getHorizontalFadingEdgeLength() {
4966         if (isHorizontalFadingEdgeEnabled()) {
4967             ScrollabilityCache cache = mScrollCache;
4968             if (cache != null) {
4969                 return cache.fadingEdgeLength;
4970             }
4971         }
4972         return 0;
4973     }
4974 
4975     /**
4976      * Returns the width of the vertical scrollbar.
4977      *
4978      * @return The width in pixels of the vertical scrollbar or 0 if there
4979      *         is no vertical scrollbar.
4980      */
getVerticalScrollbarWidth()4981     public int getVerticalScrollbarWidth() {
4982         ScrollabilityCache cache = mScrollCache;
4983         if (cache != null) {
4984             ScrollBarDrawable scrollBar = cache.scrollBar;
4985             if (scrollBar != null) {
4986                 int size = scrollBar.getSize(true);
4987                 if (size <= 0) {
4988                     size = cache.scrollBarSize;
4989                 }
4990                 return size;
4991             }
4992             return 0;
4993         }
4994         return 0;
4995     }
4996 
4997     /**
4998      * Returns the height of the horizontal scrollbar.
4999      *
5000      * @return The height in pixels of the horizontal scrollbar or 0 if
5001      *         there is no horizontal scrollbar.
5002      */
getHorizontalScrollbarHeight()5003     protected int getHorizontalScrollbarHeight() {
5004         ScrollabilityCache cache = mScrollCache;
5005         if (cache != null) {
5006             ScrollBarDrawable scrollBar = cache.scrollBar;
5007             if (scrollBar != null) {
5008                 int size = scrollBar.getSize(false);
5009                 if (size <= 0) {
5010                     size = cache.scrollBarSize;
5011                 }
5012                 return size;
5013             }
5014             return 0;
5015         }
5016         return 0;
5017     }
5018 
5019     /**
5020      * <p>
5021      * Initializes the scrollbars from a given set of styled attributes. This
5022      * method should be called by subclasses that need scrollbars and when an
5023      * instance of these subclasses is created programmatically rather than
5024      * being inflated from XML. This method is automatically called when the XML
5025      * is inflated.
5026      * </p>
5027      *
5028      * @param a the styled attributes set to initialize the scrollbars from
5029      *
5030      * @removed
5031      */
initializeScrollbars(TypedArray a)5032     protected void initializeScrollbars(TypedArray a) {
5033         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5034         // using the View filter array which is not available to the SDK. As such, internal
5035         // framework usage now uses initializeScrollbarsInternal and we grab a default
5036         // TypedArray with the right filter instead here.
5037         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5038 
5039         initializeScrollbarsInternal(arr);
5040 
5041         // We ignored the method parameter. Recycle the one we actually did use.
5042         arr.recycle();
5043     }
5044 
5045     /**
5046      * <p>
5047      * Initializes the scrollbars from a given set of styled attributes. This
5048      * method should be called by subclasses that need scrollbars and when an
5049      * instance of these subclasses is created programmatically rather than
5050      * being inflated from XML. This method is automatically called when the XML
5051      * is inflated.
5052      * </p>
5053      *
5054      * @param a the styled attributes set to initialize the scrollbars from
5055      * @hide
5056      */
initializeScrollbarsInternal(TypedArray a)5057     protected void initializeScrollbarsInternal(TypedArray a) {
5058         initScrollCache();
5059 
5060         final ScrollabilityCache scrollabilityCache = mScrollCache;
5061 
5062         if (scrollabilityCache.scrollBar == null) {
5063             scrollabilityCache.scrollBar = new ScrollBarDrawable();
5064             scrollabilityCache.scrollBar.setState(getDrawableState());
5065             scrollabilityCache.scrollBar.setCallback(this);
5066         }
5067 
5068         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5069 
5070         if (!fadeScrollbars) {
5071             scrollabilityCache.state = ScrollabilityCache.ON;
5072         }
5073         scrollabilityCache.fadeScrollBars = fadeScrollbars;
5074 
5075 
5076         scrollabilityCache.scrollBarFadeDuration = a.getInt(
5077                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5078                         .getScrollBarFadeDuration());
5079         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5080                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
5081                 ViewConfiguration.getScrollDefaultDelay());
5082 
5083 
5084         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5085                 com.android.internal.R.styleable.View_scrollbarSize,
5086                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
5087 
5088         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5089         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5090 
5091         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5092         if (thumb != null) {
5093             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5094         }
5095 
5096         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5097                 false);
5098         if (alwaysDraw) {
5099             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5100         }
5101 
5102         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5103         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5104 
5105         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5106         if (thumb != null) {
5107             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5108         }
5109 
5110         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5111                 false);
5112         if (alwaysDraw) {
5113             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5114         }
5115 
5116         // Apply layout direction to the new Drawables if needed
5117         final int layoutDirection = getLayoutDirection();
5118         if (track != null) {
5119             track.setLayoutDirection(layoutDirection);
5120         }
5121         if (thumb != null) {
5122             thumb.setLayoutDirection(layoutDirection);
5123         }
5124 
5125         // Re-apply user/background padding so that scrollbar(s) get added
5126         resolvePadding();
5127     }
5128 
initializeScrollIndicatorsInternal()5129     private void initializeScrollIndicatorsInternal() {
5130         // Some day maybe we'll break this into top/left/start/etc. and let the
5131         // client control it. Until then, you can have any scroll indicator you
5132         // want as long as it's a 1dp foreground-colored rectangle.
5133         if (mScrollIndicatorDrawable == null) {
5134             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5135         }
5136     }
5137 
5138     /**
5139      * <p>
5140      * Initalizes the scrollability cache if necessary.
5141      * </p>
5142      */
initScrollCache()5143     private void initScrollCache() {
5144         if (mScrollCache == null) {
5145             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5146         }
5147     }
5148 
getScrollCache()5149     private ScrollabilityCache getScrollCache() {
5150         initScrollCache();
5151         return mScrollCache;
5152     }
5153 
5154     /**
5155      * Set the position of the vertical scroll bar. Should be one of
5156      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5157      * {@link #SCROLLBAR_POSITION_RIGHT}.
5158      *
5159      * @param position Where the vertical scroll bar should be positioned.
5160      */
setVerticalScrollbarPosition(int position)5161     public void setVerticalScrollbarPosition(int position) {
5162         if (mVerticalScrollbarPosition != position) {
5163             mVerticalScrollbarPosition = position;
5164             computeOpaqueFlags();
5165             resolvePadding();
5166         }
5167     }
5168 
5169     /**
5170      * @return The position where the vertical scroll bar will show, if applicable.
5171      * @see #setVerticalScrollbarPosition(int)
5172      */
getVerticalScrollbarPosition()5173     public int getVerticalScrollbarPosition() {
5174         return mVerticalScrollbarPosition;
5175     }
5176 
isOnScrollbar(float x, float y)5177     boolean isOnScrollbar(float x, float y) {
5178         if (mScrollCache == null) {
5179             return false;
5180         }
5181         x += getScrollX();
5182         y += getScrollY();
5183         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5184             final Rect bounds = mScrollCache.mScrollBarBounds;
5185             getVerticalScrollBarBounds(bounds);
5186             if (bounds.contains((int)x, (int)y)) {
5187                 return true;
5188             }
5189         }
5190         if (isHorizontalScrollBarEnabled()) {
5191             final Rect bounds = mScrollCache.mScrollBarBounds;
5192             getHorizontalScrollBarBounds(bounds);
5193             if (bounds.contains((int)x, (int)y)) {
5194                 return true;
5195             }
5196         }
5197         return false;
5198     }
5199 
isOnScrollbarThumb(float x, float y)5200     boolean isOnScrollbarThumb(float x, float y) {
5201         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5202     }
5203 
isOnVerticalScrollbarThumb(float x, float y)5204     private boolean isOnVerticalScrollbarThumb(float x, float y) {
5205         if (mScrollCache == null) {
5206             return false;
5207         }
5208         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5209             x += getScrollX();
5210             y += getScrollY();
5211             final Rect bounds = mScrollCache.mScrollBarBounds;
5212             getVerticalScrollBarBounds(bounds);
5213             final int range = computeVerticalScrollRange();
5214             final int offset = computeVerticalScrollOffset();
5215             final int extent = computeVerticalScrollExtent();
5216             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5217                     extent, range);
5218             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5219                     extent, range, offset);
5220             final int thumbTop = bounds.top + thumbOffset;
5221             if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5222                     && y <= thumbTop + thumbLength) {
5223                 return true;
5224             }
5225         }
5226         return false;
5227     }
5228 
isOnHorizontalScrollbarThumb(float x, float y)5229     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5230         if (mScrollCache == null) {
5231             return false;
5232         }
5233         if (isHorizontalScrollBarEnabled()) {
5234             x += getScrollX();
5235             y += getScrollY();
5236             final Rect bounds = mScrollCache.mScrollBarBounds;
5237             getHorizontalScrollBarBounds(bounds);
5238             final int range = computeHorizontalScrollRange();
5239             final int offset = computeHorizontalScrollOffset();
5240             final int extent = computeHorizontalScrollExtent();
5241             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5242                     extent, range);
5243             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5244                     extent, range, offset);
5245             final int thumbLeft = bounds.left + thumbOffset;
5246             if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5247                     && y <= bounds.bottom) {
5248                 return true;
5249             }
5250         }
5251         return false;
5252     }
5253 
isDraggingScrollBar()5254     boolean isDraggingScrollBar() {
5255         return mScrollCache != null
5256                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5257     }
5258 
5259     /**
5260      * Sets the state of all scroll indicators.
5261      * <p>
5262      * See {@link #setScrollIndicators(int, int)} for usage information.
5263      *
5264      * @param indicators a bitmask of indicators that should be enabled, or
5265      *                   {@code 0} to disable all indicators
5266      * @see #setScrollIndicators(int, int)
5267      * @see #getScrollIndicators()
5268      * @attr ref android.R.styleable#View_scrollIndicators
5269      */
setScrollIndicators(@crollIndicators int indicators)5270     public void setScrollIndicators(@ScrollIndicators int indicators) {
5271         setScrollIndicators(indicators,
5272                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5273     }
5274 
5275     /**
5276      * Sets the state of the scroll indicators specified by the mask. To change
5277      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5278      * <p>
5279      * When a scroll indicator is enabled, it will be displayed if the view
5280      * can scroll in the direction of the indicator.
5281      * <p>
5282      * Multiple indicator types may be enabled or disabled by passing the
5283      * logical OR of the desired types. If multiple types are specified, they
5284      * will all be set to the same enabled state.
5285      * <p>
5286      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5287      *
5288      * @param indicators the indicator direction, or the logical OR of multiple
5289      *             indicator directions. One or more of:
5290      *             <ul>
5291      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5292      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5293      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5294      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5295      *               <li>{@link #SCROLL_INDICATOR_START}</li>
5296      *               <li>{@link #SCROLL_INDICATOR_END}</li>
5297      *             </ul>
5298      * @see #setScrollIndicators(int)
5299      * @see #getScrollIndicators()
5300      * @attr ref android.R.styleable#View_scrollIndicators
5301      */
setScrollIndicators(@crollIndicators int indicators, @ScrollIndicators int mask)5302     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5303         // Shift and sanitize mask.
5304         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5305         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5306 
5307         // Shift and mask indicators.
5308         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5309         indicators &= mask;
5310 
5311         // Merge with non-masked flags.
5312         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5313 
5314         if (mPrivateFlags3 != updatedFlags) {
5315             mPrivateFlags3 = updatedFlags;
5316 
5317             if (indicators != 0) {
5318                 initializeScrollIndicatorsInternal();
5319             }
5320             invalidate();
5321         }
5322     }
5323 
5324     /**
5325      * Returns a bitmask representing the enabled scroll indicators.
5326      * <p>
5327      * For example, if the top and left scroll indicators are enabled and all
5328      * other indicators are disabled, the return value will be
5329      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5330      * <p>
5331      * To check whether the bottom scroll indicator is enabled, use the value
5332      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5333      *
5334      * @return a bitmask representing the enabled scroll indicators
5335      */
5336     @ScrollIndicators
getScrollIndicators()5337     public int getScrollIndicators() {
5338         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5339                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5340     }
5341 
getListenerInfo()5342     ListenerInfo getListenerInfo() {
5343         if (mListenerInfo != null) {
5344             return mListenerInfo;
5345         }
5346         mListenerInfo = new ListenerInfo();
5347         return mListenerInfo;
5348     }
5349 
5350     /**
5351      * Register a callback to be invoked when the scroll X or Y positions of
5352      * this view change.
5353      * <p>
5354      * <b>Note:</b> Some views handle scrolling independently from View and may
5355      * have their own separate listeners for scroll-type events. For example,
5356      * {@link android.widget.ListView ListView} allows clients to register an
5357      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5358      * to listen for changes in list scroll position.
5359      *
5360      * @param l The listener to notify when the scroll X or Y position changes.
5361      * @see android.view.View#getScrollX()
5362      * @see android.view.View#getScrollY()
5363      */
setOnScrollChangeListener(OnScrollChangeListener l)5364     public void setOnScrollChangeListener(OnScrollChangeListener l) {
5365         getListenerInfo().mOnScrollChangeListener = l;
5366     }
5367 
5368     /**
5369      * Register a callback to be invoked when focus of this view changed.
5370      *
5371      * @param l The callback that will run.
5372      */
setOnFocusChangeListener(OnFocusChangeListener l)5373     public void setOnFocusChangeListener(OnFocusChangeListener l) {
5374         getListenerInfo().mOnFocusChangeListener = l;
5375     }
5376 
5377     /**
5378      * Add a listener that will be called when the bounds of the view change due to
5379      * layout processing.
5380      *
5381      * @param listener The listener that will be called when layout bounds change.
5382      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)5383     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5384         ListenerInfo li = getListenerInfo();
5385         if (li.mOnLayoutChangeListeners == null) {
5386             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5387         }
5388         if (!li.mOnLayoutChangeListeners.contains(listener)) {
5389             li.mOnLayoutChangeListeners.add(listener);
5390         }
5391     }
5392 
5393     /**
5394      * Remove a listener for layout changes.
5395      *
5396      * @param listener The listener for layout bounds change.
5397      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)5398     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5399         ListenerInfo li = mListenerInfo;
5400         if (li == null || li.mOnLayoutChangeListeners == null) {
5401             return;
5402         }
5403         li.mOnLayoutChangeListeners.remove(listener);
5404     }
5405 
5406     /**
5407      * Add a listener for attach state changes.
5408      *
5409      * This listener will be called whenever this view is attached or detached
5410      * from a window. Remove the listener using
5411      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5412      *
5413      * @param listener Listener to attach
5414      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5415      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)5416     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5417         ListenerInfo li = getListenerInfo();
5418         if (li.mOnAttachStateChangeListeners == null) {
5419             li.mOnAttachStateChangeListeners
5420                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5421         }
5422         li.mOnAttachStateChangeListeners.add(listener);
5423     }
5424 
5425     /**
5426      * Remove a listener for attach state changes. The listener will receive no further
5427      * notification of window attach/detach events.
5428      *
5429      * @param listener Listener to remove
5430      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5431      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)5432     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5433         ListenerInfo li = mListenerInfo;
5434         if (li == null || li.mOnAttachStateChangeListeners == null) {
5435             return;
5436         }
5437         li.mOnAttachStateChangeListeners.remove(listener);
5438     }
5439 
5440     /**
5441      * Returns the focus-change callback registered for this view.
5442      *
5443      * @return The callback, or null if one is not registered.
5444      */
getOnFocusChangeListener()5445     public OnFocusChangeListener getOnFocusChangeListener() {
5446         ListenerInfo li = mListenerInfo;
5447         return li != null ? li.mOnFocusChangeListener : null;
5448     }
5449 
5450     /**
5451      * Register a callback to be invoked when this view is clicked. If this view is not
5452      * clickable, it becomes clickable.
5453      *
5454      * @param l The callback that will run
5455      *
5456      * @see #setClickable(boolean)
5457      */
setOnClickListener(@ullable OnClickListener l)5458     public void setOnClickListener(@Nullable OnClickListener l) {
5459         if (!isClickable()) {
5460             setClickable(true);
5461         }
5462         getListenerInfo().mOnClickListener = l;
5463     }
5464 
5465     /**
5466      * Return whether this view has an attached OnClickListener.  Returns
5467      * true if there is a listener, false if there is none.
5468      */
hasOnClickListeners()5469     public boolean hasOnClickListeners() {
5470         ListenerInfo li = mListenerInfo;
5471         return (li != null && li.mOnClickListener != null);
5472     }
5473 
5474     /**
5475      * Register a callback to be invoked when this view is clicked and held. If this view is not
5476      * long clickable, it becomes long clickable.
5477      *
5478      * @param l The callback that will run
5479      *
5480      * @see #setLongClickable(boolean)
5481      */
setOnLongClickListener(@ullable OnLongClickListener l)5482     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5483         if (!isLongClickable()) {
5484             setLongClickable(true);
5485         }
5486         getListenerInfo().mOnLongClickListener = l;
5487     }
5488 
5489     /**
5490      * Register a callback to be invoked when this view is context clicked. If the view is not
5491      * context clickable, it becomes context clickable.
5492      *
5493      * @param l The callback that will run
5494      * @see #setContextClickable(boolean)
5495      */
setOnContextClickListener(@ullable OnContextClickListener l)5496     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5497         if (!isContextClickable()) {
5498             setContextClickable(true);
5499         }
5500         getListenerInfo().mOnContextClickListener = l;
5501     }
5502 
5503     /**
5504      * Register a callback to be invoked when the context menu for this view is
5505      * being built. If this view is not long clickable, it becomes long clickable.
5506      *
5507      * @param l The callback that will run
5508      *
5509      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)5510     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5511         if (!isLongClickable()) {
5512             setLongClickable(true);
5513         }
5514         getListenerInfo().mOnCreateContextMenuListener = l;
5515     }
5516 
5517     /**
5518      * Set an observer to collect stats for each frame rendered for this view.
5519      *
5520      * @hide
5521      */
addFrameMetricsListener(Window window, Window.OnFrameMetricsAvailableListener listener, Handler handler)5522     public void addFrameMetricsListener(Window window,
5523             Window.OnFrameMetricsAvailableListener listener,
5524             Handler handler) {
5525         if (mAttachInfo != null) {
5526             if (mAttachInfo.mHardwareRenderer != null) {
5527                 if (mFrameMetricsObservers == null) {
5528                     mFrameMetricsObservers = new ArrayList<>();
5529                 }
5530 
5531                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5532                         handler.getLooper(), listener);
5533                 mFrameMetricsObservers.add(fmo);
5534                 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
5535             } else {
5536                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5537             }
5538         } else {
5539             if (mFrameMetricsObservers == null) {
5540                 mFrameMetricsObservers = new ArrayList<>();
5541             }
5542 
5543             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5544                     handler.getLooper(), listener);
5545             mFrameMetricsObservers.add(fmo);
5546         }
5547     }
5548 
5549     /**
5550      * Remove observer configured to collect frame stats for this view.
5551      *
5552      * @hide
5553      */
removeFrameMetricsListener( Window.OnFrameMetricsAvailableListener listener)5554     public void removeFrameMetricsListener(
5555             Window.OnFrameMetricsAvailableListener listener) {
5556         ThreadedRenderer renderer = getHardwareRenderer();
5557         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5558         if (fmo == null) {
5559             throw new IllegalArgumentException(
5560                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
5561         }
5562 
5563         if (mFrameMetricsObservers != null) {
5564             mFrameMetricsObservers.remove(fmo);
5565             if (renderer != null) {
5566                 renderer.removeFrameMetricsObserver(fmo);
5567             }
5568         }
5569     }
5570 
registerPendingFrameMetricsObservers()5571     private void registerPendingFrameMetricsObservers() {
5572         if (mFrameMetricsObservers != null) {
5573             ThreadedRenderer renderer = getHardwareRenderer();
5574             if (renderer != null) {
5575                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5576                     renderer.addFrameMetricsObserver(fmo);
5577                 }
5578             } else {
5579                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5580             }
5581         }
5582     }
5583 
findFrameMetricsObserver( Window.OnFrameMetricsAvailableListener listener)5584     private FrameMetricsObserver findFrameMetricsObserver(
5585             Window.OnFrameMetricsAvailableListener listener) {
5586         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5587             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5588             if (observer.mListener == listener) {
5589                 return observer;
5590             }
5591         }
5592 
5593         return null;
5594     }
5595 
5596     /**
5597      * Call this view's OnClickListener, if it is defined.  Performs all normal
5598      * actions associated with clicking: reporting accessibility event, playing
5599      * a sound, etc.
5600      *
5601      * @return True there was an assigned OnClickListener that was called, false
5602      *         otherwise is returned.
5603      */
performClick()5604     public boolean performClick() {
5605         final boolean result;
5606         final ListenerInfo li = mListenerInfo;
5607         if (li != null && li.mOnClickListener != null) {
5608             playSoundEffect(SoundEffectConstants.CLICK);
5609             li.mOnClickListener.onClick(this);
5610             result = true;
5611         } else {
5612             result = false;
5613         }
5614 
5615         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5616         return result;
5617     }
5618 
5619     /**
5620      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5621      * this only calls the listener, and does not do any associated clicking
5622      * actions like reporting an accessibility event.
5623      *
5624      * @return True there was an assigned OnClickListener that was called, false
5625      *         otherwise is returned.
5626      */
callOnClick()5627     public boolean callOnClick() {
5628         ListenerInfo li = mListenerInfo;
5629         if (li != null && li.mOnClickListener != null) {
5630             li.mOnClickListener.onClick(this);
5631             return true;
5632         }
5633         return false;
5634     }
5635 
5636     /**
5637      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5638      * context menu if the OnLongClickListener did not consume the event.
5639      *
5640      * @return {@code true} if one of the above receivers consumed the event,
5641      *         {@code false} otherwise
5642      */
performLongClick()5643     public boolean performLongClick() {
5644         return performLongClickInternal(mLongClickX, mLongClickY);
5645     }
5646 
5647     /**
5648      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5649      * context menu if the OnLongClickListener did not consume the event,
5650      * anchoring it to an (x,y) coordinate.
5651      *
5652      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5653      *          to disable anchoring
5654      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5655      *          to disable anchoring
5656      * @return {@code true} if one of the above receivers consumed the event,
5657      *         {@code false} otherwise
5658      */
performLongClick(float x, float y)5659     public boolean performLongClick(float x, float y) {
5660         mLongClickX = x;
5661         mLongClickY = y;
5662         final boolean handled = performLongClick();
5663         mLongClickX = Float.NaN;
5664         mLongClickY = Float.NaN;
5665         return handled;
5666     }
5667 
5668     /**
5669      * Calls this view's OnLongClickListener, if it is defined. Invokes the
5670      * context menu if the OnLongClickListener did not consume the event,
5671      * optionally anchoring it to an (x,y) coordinate.
5672      *
5673      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5674      *          to disable anchoring
5675      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5676      *          to disable anchoring
5677      * @return {@code true} if one of the above receivers consumed the event,
5678      *         {@code false} otherwise
5679      */
performLongClickInternal(float x, float y)5680     private boolean performLongClickInternal(float x, float y) {
5681         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5682 
5683         boolean handled = false;
5684         final ListenerInfo li = mListenerInfo;
5685         if (li != null && li.mOnLongClickListener != null) {
5686             handled = li.mOnLongClickListener.onLongClick(View.this);
5687         }
5688         if (!handled) {
5689             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5690             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5691         }
5692         if (handled) {
5693             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5694         }
5695         return handled;
5696     }
5697 
5698     /**
5699      * Call this view's OnContextClickListener, if it is defined.
5700      *
5701      * @param x the x coordinate of the context click
5702      * @param y the y coordinate of the context click
5703      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5704      *         otherwise.
5705      */
performContextClick(float x, float y)5706     public boolean performContextClick(float x, float y) {
5707         return performContextClick();
5708     }
5709 
5710     /**
5711      * Call this view's OnContextClickListener, if it is defined.
5712      *
5713      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5714      *         otherwise.
5715      */
performContextClick()5716     public boolean performContextClick() {
5717         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5718 
5719         boolean handled = false;
5720         ListenerInfo li = mListenerInfo;
5721         if (li != null && li.mOnContextClickListener != null) {
5722             handled = li.mOnContextClickListener.onContextClick(View.this);
5723         }
5724         if (handled) {
5725             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5726         }
5727         return handled;
5728     }
5729 
5730     /**
5731      * Performs button-related actions during a touch down event.
5732      *
5733      * @param event The event.
5734      * @return True if the down was consumed.
5735      *
5736      * @hide
5737      */
performButtonActionOnTouchDown(MotionEvent event)5738     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5739         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5740             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5741             showContextMenu(event.getX(), event.getY());
5742             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5743             return true;
5744         }
5745         return false;
5746     }
5747 
5748     /**
5749      * Shows the context menu for this view.
5750      *
5751      * @return {@code true} if the context menu was shown, {@code false}
5752      *         otherwise
5753      * @see #showContextMenu(float, float)
5754      */
showContextMenu()5755     public boolean showContextMenu() {
5756         return getParent().showContextMenuForChild(this);
5757     }
5758 
5759     /**
5760      * Shows the context menu for this view anchored to the specified
5761      * view-relative coordinate.
5762      *
5763      * @param x the X coordinate in pixels relative to the view to which the
5764      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5765      * @param y the Y coordinate in pixels relative to the view to which the
5766      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5767      * @return {@code true} if the context menu was shown, {@code false}
5768      *         otherwise
5769      */
showContextMenu(float x, float y)5770     public boolean showContextMenu(float x, float y) {
5771         return getParent().showContextMenuForChild(this, x, y);
5772     }
5773 
5774     /**
5775      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5776      *
5777      * @param callback Callback that will control the lifecycle of the action mode
5778      * @return The new action mode if it is started, null otherwise
5779      *
5780      * @see ActionMode
5781      * @see #startActionMode(android.view.ActionMode.Callback, int)
5782      */
startActionMode(ActionMode.Callback callback)5783     public ActionMode startActionMode(ActionMode.Callback callback) {
5784         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5785     }
5786 
5787     /**
5788      * Start an action mode with the given type.
5789      *
5790      * @param callback Callback that will control the lifecycle of the action mode
5791      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5792      * @return The new action mode if it is started, null otherwise
5793      *
5794      * @see ActionMode
5795      */
startActionMode(ActionMode.Callback callback, int type)5796     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5797         ViewParent parent = getParent();
5798         if (parent == null) return null;
5799         try {
5800             return parent.startActionModeForChild(this, callback, type);
5801         } catch (AbstractMethodError ame) {
5802             // Older implementations of custom views might not implement this.
5803             return parent.startActionModeForChild(this, callback);
5804         }
5805     }
5806 
5807     /**
5808      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5809      * Context, creating a unique View identifier to retrieve the result.
5810      *
5811      * @param intent The Intent to be started.
5812      * @param requestCode The request code to use.
5813      * @hide
5814      */
startActivityForResult(Intent intent, int requestCode)5815     public void startActivityForResult(Intent intent, int requestCode) {
5816         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5817         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5818     }
5819 
5820     /**
5821      * If this View corresponds to the calling who, dispatches the activity result.
5822      * @param who The identifier for the targeted View to receive the result.
5823      * @param requestCode The integer request code originally supplied to
5824      *                    startActivityForResult(), allowing you to identify who this
5825      *                    result came from.
5826      * @param resultCode The integer result code returned by the child activity
5827      *                   through its setResult().
5828      * @param data An Intent, which can return result data to the caller
5829      *               (various data can be attached to Intent "extras").
5830      * @return {@code true} if the activity result was dispatched.
5831      * @hide
5832      */
dispatchActivityResult( String who, int requestCode, int resultCode, Intent data)5833     public boolean dispatchActivityResult(
5834             String who, int requestCode, int resultCode, Intent data) {
5835         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5836             onActivityResult(requestCode, resultCode, data);
5837             mStartActivityRequestWho = null;
5838             return true;
5839         }
5840         return false;
5841     }
5842 
5843     /**
5844      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5845      *
5846      * @param requestCode The integer request code originally supplied to
5847      *                    startActivityForResult(), allowing you to identify who this
5848      *                    result came from.
5849      * @param resultCode The integer result code returned by the child activity
5850      *                   through its setResult().
5851      * @param data An Intent, which can return result data to the caller
5852      *               (various data can be attached to Intent "extras").
5853      * @hide
5854      */
onActivityResult(int requestCode, int resultCode, Intent data)5855     public void onActivityResult(int requestCode, int resultCode, Intent data) {
5856         // Do nothing.
5857     }
5858 
5859     /**
5860      * Register a callback to be invoked when a hardware key is pressed in this view.
5861      * Key presses in software input methods will generally not trigger the methods of
5862      * this listener.
5863      * @param l the key listener to attach to this view
5864      */
setOnKeyListener(OnKeyListener l)5865     public void setOnKeyListener(OnKeyListener l) {
5866         getListenerInfo().mOnKeyListener = l;
5867     }
5868 
5869     /**
5870      * Register a callback to be invoked when a touch event is sent to this view.
5871      * @param l the touch listener to attach to this view
5872      */
setOnTouchListener(OnTouchListener l)5873     public void setOnTouchListener(OnTouchListener l) {
5874         getListenerInfo().mOnTouchListener = l;
5875     }
5876 
5877     /**
5878      * Register a callback to be invoked when a generic motion event is sent to this view.
5879      * @param l the generic motion listener to attach to this view
5880      */
setOnGenericMotionListener(OnGenericMotionListener l)5881     public void setOnGenericMotionListener(OnGenericMotionListener l) {
5882         getListenerInfo().mOnGenericMotionListener = l;
5883     }
5884 
5885     /**
5886      * Register a callback to be invoked when a hover event is sent to this view.
5887      * @param l the hover listener to attach to this view
5888      */
setOnHoverListener(OnHoverListener l)5889     public void setOnHoverListener(OnHoverListener l) {
5890         getListenerInfo().mOnHoverListener = l;
5891     }
5892 
5893     /**
5894      * Register a drag event listener callback object for this View. The parameter is
5895      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5896      * View, the system calls the
5897      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5898      * @param l An implementation of {@link android.view.View.OnDragListener}.
5899      */
setOnDragListener(OnDragListener l)5900     public void setOnDragListener(OnDragListener l) {
5901         getListenerInfo().mOnDragListener = l;
5902     }
5903 
5904     /**
5905      * Give this view focus. This will cause
5906      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5907      *
5908      * Note: this does not check whether this {@link View} should get focus, it just
5909      * gives it focus no matter what.  It should only be called internally by framework
5910      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5911      *
5912      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5913      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5914      *        focus moved when requestFocus() is called. It may not always
5915      *        apply, in which case use the default View.FOCUS_DOWN.
5916      * @param previouslyFocusedRect The rectangle of the view that had focus
5917      *        prior in this View's coordinate system.
5918      */
handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)5919     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5920         if (DBG) {
5921             System.out.println(this + " requestFocus()");
5922         }
5923 
5924         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5925             mPrivateFlags |= PFLAG_FOCUSED;
5926 
5927             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5928 
5929             if (mParent != null) {
5930                 mParent.requestChildFocus(this, this);
5931             }
5932 
5933             if (mAttachInfo != null) {
5934                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5935             }
5936 
5937             onFocusChanged(true, direction, previouslyFocusedRect);
5938             refreshDrawableState();
5939         }
5940     }
5941 
5942     /**
5943      * Populates <code>outRect</code> with the hotspot bounds. By default,
5944      * the hotspot bounds are identical to the screen bounds.
5945      *
5946      * @param outRect rect to populate with hotspot bounds
5947      * @hide Only for internal use by views and widgets.
5948      */
getHotspotBounds(Rect outRect)5949     public void getHotspotBounds(Rect outRect) {
5950         final Drawable background = getBackground();
5951         if (background != null) {
5952             background.getHotspotBounds(outRect);
5953         } else {
5954             getBoundsOnScreen(outRect);
5955         }
5956     }
5957 
5958     /**
5959      * Request that a rectangle of this view be visible on the screen,
5960      * scrolling if necessary just enough.
5961      *
5962      * <p>A View should call this if it maintains some notion of which part
5963      * of its content is interesting.  For example, a text editing view
5964      * should call this when its cursor moves.
5965      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
5966      * It should not be affected by which part of the View is currently visible or its scroll
5967      * position.
5968      *
5969      * @param rectangle The rectangle in the View's content coordinate space
5970      * @return Whether any parent scrolled.
5971      */
requestRectangleOnScreen(Rect rectangle)5972     public boolean requestRectangleOnScreen(Rect rectangle) {
5973         return requestRectangleOnScreen(rectangle, false);
5974     }
5975 
5976     /**
5977      * Request that a rectangle of this view be visible on the screen,
5978      * scrolling if necessary just enough.
5979      *
5980      * <p>A View should call this if it maintains some notion of which part
5981      * of its content is interesting.  For example, a text editing view
5982      * should call this when its cursor moves.
5983      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
5984      * It should not be affected by which part of the View is currently visible or its scroll
5985      * position.
5986      * <p>When <code>immediate</code> is set to true, scrolling will not be
5987      * animated.
5988      *
5989      * @param rectangle The rectangle in the View's content coordinate space
5990      * @param immediate True to forbid animated scrolling, false otherwise
5991      * @return Whether any parent scrolled.
5992      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)5993     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5994         if (mParent == null) {
5995             return false;
5996         }
5997 
5998         View child = this;
5999 
6000         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6001         position.set(rectangle);
6002 
6003         ViewParent parent = mParent;
6004         boolean scrolled = false;
6005         while (parent != null) {
6006             rectangle.set((int) position.left, (int) position.top,
6007                     (int) position.right, (int) position.bottom);
6008 
6009             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6010 
6011             if (!(parent instanceof View)) {
6012                 break;
6013             }
6014 
6015             // move it from child's content coordinate space to parent's content coordinate space
6016             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6017 
6018             child = (View) parent;
6019             parent = child.getParent();
6020         }
6021 
6022         return scrolled;
6023     }
6024 
6025     /**
6026      * Called when this view wants to give up focus. If focus is cleared
6027      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6028      * <p>
6029      * <strong>Note:</strong> When a View clears focus the framework is trying
6030      * to give focus to the first focusable View from the top. Hence, if this
6031      * View is the first from the top that can take focus, then all callbacks
6032      * related to clearing focus will be invoked after which the framework will
6033      * give focus to this view.
6034      * </p>
6035      */
clearFocus()6036     public void clearFocus() {
6037         if (DBG) {
6038             System.out.println(this + " clearFocus()");
6039         }
6040 
6041         clearFocusInternal(null, true, true);
6042     }
6043 
6044     /**
6045      * Clears focus from the view, optionally propagating the change up through
6046      * the parent hierarchy and requesting that the root view place new focus.
6047      *
6048      * @param propagate whether to propagate the change up through the parent
6049      *            hierarchy
6050      * @param refocus when propagate is true, specifies whether to request the
6051      *            root view place new focus
6052      */
clearFocusInternal(View focused, boolean propagate, boolean refocus)6053     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6054         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6055             mPrivateFlags &= ~PFLAG_FOCUSED;
6056 
6057             if (propagate && mParent != null) {
6058                 mParent.clearChildFocus(this);
6059             }
6060 
6061             onFocusChanged(false, 0, null);
6062             refreshDrawableState();
6063 
6064             if (propagate && (!refocus || !rootViewRequestFocus())) {
6065                 notifyGlobalFocusCleared(this);
6066             }
6067         }
6068     }
6069 
notifyGlobalFocusCleared(View oldFocus)6070     void notifyGlobalFocusCleared(View oldFocus) {
6071         if (oldFocus != null && mAttachInfo != null) {
6072             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6073         }
6074     }
6075 
rootViewRequestFocus()6076     boolean rootViewRequestFocus() {
6077         final View root = getRootView();
6078         return root != null && root.requestFocus();
6079     }
6080 
6081     /**
6082      * Called internally by the view system when a new view is getting focus.
6083      * This is what clears the old focus.
6084      * <p>
6085      * <b>NOTE:</b> The parent view's focused child must be updated manually
6086      * after calling this method. Otherwise, the view hierarchy may be left in
6087      * an inconstent state.
6088      */
unFocus(View focused)6089     void unFocus(View focused) {
6090         if (DBG) {
6091             System.out.println(this + " unFocus()");
6092         }
6093 
6094         clearFocusInternal(focused, false, false);
6095     }
6096 
6097     /**
6098      * Returns true if this view has focus itself, or is the ancestor of the
6099      * view that has focus.
6100      *
6101      * @return True if this view has or contains focus, false otherwise.
6102      */
6103     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()6104     public boolean hasFocus() {
6105         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6106     }
6107 
6108     /**
6109      * Returns true if this view is focusable or if it contains a reachable View
6110      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6111      * is a View whose parents do not block descendants focus.
6112      *
6113      * Only {@link #VISIBLE} views are considered focusable.
6114      *
6115      * @return True if the view is focusable or if the view contains a focusable
6116      *         View, false otherwise.
6117      *
6118      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6119      * @see ViewGroup#getTouchscreenBlocksFocus()
6120      */
hasFocusable()6121     public boolean hasFocusable() {
6122         if (!isFocusableInTouchMode()) {
6123             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6124                 final ViewGroup g = (ViewGroup) p;
6125                 if (g.shouldBlockFocusForTouchscreen()) {
6126                     return false;
6127                 }
6128             }
6129         }
6130         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6131     }
6132 
6133     /**
6134      * Called by the view system when the focus state of this view changes.
6135      * When the focus change event is caused by directional navigation, direction
6136      * and previouslyFocusedRect provide insight into where the focus is coming from.
6137      * When overriding, be sure to call up through to the super class so that
6138      * the standard focus handling will occur.
6139      *
6140      * @param gainFocus True if the View has focus; false otherwise.
6141      * @param direction The direction focus has moved when requestFocus()
6142      *                  is called to give this view focus. Values are
6143      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6144      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6145      *                  It may not always apply, in which case use the default.
6146      * @param previouslyFocusedRect The rectangle, in this view's coordinate
6147      *        system, of the previously focused view.  If applicable, this will be
6148      *        passed in as finer grained information about where the focus is coming
6149      *        from (in addition to direction).  Will be <code>null</code> otherwise.
6150      */
6151     @CallSuper
onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)6152     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6153             @Nullable Rect previouslyFocusedRect) {
6154         if (gainFocus) {
6155             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6156         } else {
6157             notifyViewAccessibilityStateChangedIfNeeded(
6158                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6159         }
6160 
6161         InputMethodManager imm = InputMethodManager.peekInstance();
6162         if (!gainFocus) {
6163             if (isPressed()) {
6164                 setPressed(false);
6165             }
6166             if (imm != null && mAttachInfo != null
6167                     && mAttachInfo.mHasWindowFocus) {
6168                 imm.focusOut(this);
6169             }
6170             onFocusLost();
6171         } else if (imm != null && mAttachInfo != null
6172                 && mAttachInfo.mHasWindowFocus) {
6173             imm.focusIn(this);
6174         }
6175 
6176         invalidate(true);
6177         ListenerInfo li = mListenerInfo;
6178         if (li != null && li.mOnFocusChangeListener != null) {
6179             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6180         }
6181 
6182         if (mAttachInfo != null) {
6183             mAttachInfo.mKeyDispatchState.reset(this);
6184         }
6185     }
6186 
6187     /**
6188      * Sends an accessibility event of the given type. If accessibility is
6189      * not enabled this method has no effect. The default implementation calls
6190      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6191      * to populate information about the event source (this View), then calls
6192      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6193      * populate the text content of the event source including its descendants,
6194      * and last calls
6195      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6196      * on its parent to request sending of the event to interested parties.
6197      * <p>
6198      * If an {@link AccessibilityDelegate} has been specified via calling
6199      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6200      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6201      * responsible for handling this call.
6202      * </p>
6203      *
6204      * @param eventType The type of the event to send, as defined by several types from
6205      * {@link android.view.accessibility.AccessibilityEvent}, such as
6206      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6207      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6208      *
6209      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6210      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6211      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6212      * @see AccessibilityDelegate
6213      */
sendAccessibilityEvent(int eventType)6214     public void sendAccessibilityEvent(int eventType) {
6215         if (mAccessibilityDelegate != null) {
6216             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6217         } else {
6218             sendAccessibilityEventInternal(eventType);
6219         }
6220     }
6221 
6222     /**
6223      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6224      * {@link AccessibilityEvent} to make an announcement which is related to some
6225      * sort of a context change for which none of the events representing UI transitions
6226      * is a good fit. For example, announcing a new page in a book. If accessibility
6227      * is not enabled this method does nothing.
6228      *
6229      * @param text The announcement text.
6230      */
announceForAccessibility(CharSequence text)6231     public void announceForAccessibility(CharSequence text) {
6232         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6233             AccessibilityEvent event = AccessibilityEvent.obtain(
6234                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
6235             onInitializeAccessibilityEvent(event);
6236             event.getText().add(text);
6237             event.setContentDescription(null);
6238             mParent.requestSendAccessibilityEvent(this, event);
6239         }
6240     }
6241 
6242     /**
6243      * @see #sendAccessibilityEvent(int)
6244      *
6245      * Note: Called from the default {@link AccessibilityDelegate}.
6246      *
6247      * @hide
6248      */
sendAccessibilityEventInternal(int eventType)6249     public void sendAccessibilityEventInternal(int eventType) {
6250         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6251             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6252         }
6253     }
6254 
6255     /**
6256      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6257      * takes as an argument an empty {@link AccessibilityEvent} and does not
6258      * perform a check whether accessibility is enabled.
6259      * <p>
6260      * If an {@link AccessibilityDelegate} has been specified via calling
6261      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6262      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6263      * is responsible for handling this call.
6264      * </p>
6265      *
6266      * @param event The event to send.
6267      *
6268      * @see #sendAccessibilityEvent(int)
6269      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)6270     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6271         if (mAccessibilityDelegate != null) {
6272             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6273         } else {
6274             sendAccessibilityEventUncheckedInternal(event);
6275         }
6276     }
6277 
6278     /**
6279      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6280      *
6281      * Note: Called from the default {@link AccessibilityDelegate}.
6282      *
6283      * @hide
6284      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)6285     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6286         if (!isShown()) {
6287             return;
6288         }
6289         onInitializeAccessibilityEvent(event);
6290         // Only a subset of accessibility events populates text content.
6291         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6292             dispatchPopulateAccessibilityEvent(event);
6293         }
6294         // In the beginning we called #isShown(), so we know that getParent() is not null.
6295         getParent().requestSendAccessibilityEvent(this, event);
6296     }
6297 
6298     /**
6299      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6300      * to its children for adding their text content to the event. Note that the
6301      * event text is populated in a separate dispatch path since we add to the
6302      * event not only the text of the source but also the text of all its descendants.
6303      * A typical implementation will call
6304      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6305      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6306      * on each child. Override this method if custom population of the event text
6307      * content is required.
6308      * <p>
6309      * If an {@link AccessibilityDelegate} has been specified via calling
6310      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6311      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6312      * is responsible for handling this call.
6313      * </p>
6314      * <p>
6315      * <em>Note:</em> Accessibility events of certain types are not dispatched for
6316      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6317      * </p>
6318      *
6319      * @param event The event.
6320      *
6321      * @return True if the event population was completed.
6322      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)6323     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6324         if (mAccessibilityDelegate != null) {
6325             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6326         } else {
6327             return dispatchPopulateAccessibilityEventInternal(event);
6328         }
6329     }
6330 
6331     /**
6332      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6333      *
6334      * Note: Called from the default {@link AccessibilityDelegate}.
6335      *
6336      * @hide
6337      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)6338     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6339         onPopulateAccessibilityEvent(event);
6340         return false;
6341     }
6342 
6343     /**
6344      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6345      * giving a chance to this View to populate the accessibility event with its
6346      * text content. While this method is free to modify event
6347      * attributes other than text content, doing so should normally be performed in
6348      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6349      * <p>
6350      * Example: Adding formatted date string to an accessibility event in addition
6351      *          to the text added by the super implementation:
6352      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6353      *     super.onPopulateAccessibilityEvent(event);
6354      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6355      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6356      *         mCurrentDate.getTimeInMillis(), flags);
6357      *     event.getText().add(selectedDateUtterance);
6358      * }</pre>
6359      * <p>
6360      * If an {@link AccessibilityDelegate} has been specified via calling
6361      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6362      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6363      * is responsible for handling this call.
6364      * </p>
6365      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6366      * information to the event, in case the default implementation has basic information to add.
6367      * </p>
6368      *
6369      * @param event The accessibility event which to populate.
6370      *
6371      * @see #sendAccessibilityEvent(int)
6372      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6373      */
6374     @CallSuper
onPopulateAccessibilityEvent(AccessibilityEvent event)6375     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6376         if (mAccessibilityDelegate != null) {
6377             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6378         } else {
6379             onPopulateAccessibilityEventInternal(event);
6380         }
6381     }
6382 
6383     /**
6384      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6385      *
6386      * Note: Called from the default {@link AccessibilityDelegate}.
6387      *
6388      * @hide
6389      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)6390     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6391     }
6392 
6393     /**
6394      * Initializes an {@link AccessibilityEvent} with information about
6395      * this View which is the event source. In other words, the source of
6396      * an accessibility event is the view whose state change triggered firing
6397      * the event.
6398      * <p>
6399      * Example: Setting the password property of an event in addition
6400      *          to properties set by the super implementation:
6401      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6402      *     super.onInitializeAccessibilityEvent(event);
6403      *     event.setPassword(true);
6404      * }</pre>
6405      * <p>
6406      * If an {@link AccessibilityDelegate} has been specified via calling
6407      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6408      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6409      * is responsible for handling this call.
6410      * </p>
6411      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6412      * information to the event, in case the default implementation has basic information to add.
6413      * </p>
6414      * @param event The event to initialize.
6415      *
6416      * @see #sendAccessibilityEvent(int)
6417      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6418      */
6419     @CallSuper
onInitializeAccessibilityEvent(AccessibilityEvent event)6420     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6421         if (mAccessibilityDelegate != null) {
6422             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6423         } else {
6424             onInitializeAccessibilityEventInternal(event);
6425         }
6426     }
6427 
6428     /**
6429      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6430      *
6431      * Note: Called from the default {@link AccessibilityDelegate}.
6432      *
6433      * @hide
6434      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)6435     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6436         event.setSource(this);
6437         event.setClassName(getAccessibilityClassName());
6438         event.setPackageName(getContext().getPackageName());
6439         event.setEnabled(isEnabled());
6440         event.setContentDescription(mContentDescription);
6441 
6442         switch (event.getEventType()) {
6443             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6444                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
6445                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6446                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6447                 event.setItemCount(focusablesTempList.size());
6448                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6449                 if (mAttachInfo != null) {
6450                     focusablesTempList.clear();
6451                 }
6452             } break;
6453             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6454                 CharSequence text = getIterableTextForAccessibility();
6455                 if (text != null && text.length() > 0) {
6456                     event.setFromIndex(getAccessibilitySelectionStart());
6457                     event.setToIndex(getAccessibilitySelectionEnd());
6458                     event.setItemCount(text.length());
6459                 }
6460             } break;
6461         }
6462     }
6463 
6464     /**
6465      * Returns an {@link AccessibilityNodeInfo} representing this view from the
6466      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6467      * This method is responsible for obtaining an accessibility node info from a
6468      * pool of reusable instances and calling
6469      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6470      * initialize the former.
6471      * <p>
6472      * Note: The client is responsible for recycling the obtained instance by calling
6473      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6474      * </p>
6475      *
6476      * @return A populated {@link AccessibilityNodeInfo}.
6477      *
6478      * @see AccessibilityNodeInfo
6479      */
createAccessibilityNodeInfo()6480     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6481         if (mAccessibilityDelegate != null) {
6482             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6483         } else {
6484             return createAccessibilityNodeInfoInternal();
6485         }
6486     }
6487 
6488     /**
6489      * @see #createAccessibilityNodeInfo()
6490      *
6491      * @hide
6492      */
createAccessibilityNodeInfoInternal()6493     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6494         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6495         if (provider != null) {
6496             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6497         } else {
6498             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6499             onInitializeAccessibilityNodeInfo(info);
6500             return info;
6501         }
6502     }
6503 
6504     /**
6505      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6506      * The base implementation sets:
6507      * <ul>
6508      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6509      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6510      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6511      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6512      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6513      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6514      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6515      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6516      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6517      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6518      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6519      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6520      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6521      * </ul>
6522      * <p>
6523      * Subclasses should override this method, call the super implementation,
6524      * and set additional attributes.
6525      * </p>
6526      * <p>
6527      * If an {@link AccessibilityDelegate} has been specified via calling
6528      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6529      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6530      * is responsible for handling this call.
6531      * </p>
6532      *
6533      * @param info The instance to initialize.
6534      */
6535     @CallSuper
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)6536     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6537         if (mAccessibilityDelegate != null) {
6538             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6539         } else {
6540             onInitializeAccessibilityNodeInfoInternal(info);
6541         }
6542     }
6543 
6544     /**
6545      * Gets the location of this view in screen coordinates.
6546      *
6547      * @param outRect The output location
6548      * @hide
6549      */
getBoundsOnScreen(Rect outRect)6550     public void getBoundsOnScreen(Rect outRect) {
6551         getBoundsOnScreen(outRect, false);
6552     }
6553 
6554     /**
6555      * Gets the location of this view in screen coordinates.
6556      *
6557      * @param outRect The output location
6558      * @param clipToParent Whether to clip child bounds to the parent ones.
6559      * @hide
6560      */
getBoundsOnScreen(Rect outRect, boolean clipToParent)6561     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6562         if (mAttachInfo == null) {
6563             return;
6564         }
6565 
6566         RectF position = mAttachInfo.mTmpTransformRect;
6567         position.set(0, 0, mRight - mLeft, mBottom - mTop);
6568 
6569         if (!hasIdentityMatrix()) {
6570             getMatrix().mapRect(position);
6571         }
6572 
6573         position.offset(mLeft, mTop);
6574 
6575         ViewParent parent = mParent;
6576         while (parent instanceof View) {
6577             View parentView = (View) parent;
6578 
6579             position.offset(-parentView.mScrollX, -parentView.mScrollY);
6580 
6581             if (clipToParent) {
6582                 position.left = Math.max(position.left, 0);
6583                 position.top = Math.max(position.top, 0);
6584                 position.right = Math.min(position.right, parentView.getWidth());
6585                 position.bottom = Math.min(position.bottom, parentView.getHeight());
6586             }
6587 
6588             if (!parentView.hasIdentityMatrix()) {
6589                 parentView.getMatrix().mapRect(position);
6590             }
6591 
6592             position.offset(parentView.mLeft, parentView.mTop);
6593 
6594             parent = parentView.mParent;
6595         }
6596 
6597         if (parent instanceof ViewRootImpl) {
6598             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6599             position.offset(0, -viewRootImpl.mCurScrollY);
6600         }
6601 
6602         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6603 
6604         outRect.set(Math.round(position.left), Math.round(position.top),
6605                 Math.round(position.right), Math.round(position.bottom));
6606     }
6607 
6608     /**
6609      * Return the class name of this object to be used for accessibility purposes.
6610      * Subclasses should only override this if they are implementing something that
6611      * should be seen as a completely new class of view when used by accessibility,
6612      * unrelated to the class it is deriving from.  This is used to fill in
6613      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6614      */
getAccessibilityClassName()6615     public CharSequence getAccessibilityClassName() {
6616         return View.class.getName();
6617     }
6618 
6619     /**
6620      * Called when assist structure is being retrieved from a view as part of
6621      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6622      * @param structure Fill in with structured view data.  The default implementation
6623      * fills in all data that can be inferred from the view itself.
6624      */
onProvideStructure(ViewStructure structure)6625     public void onProvideStructure(ViewStructure structure) {
6626         final int id = mID;
6627         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6628                 && (id&0x0000ffff) != 0) {
6629             String pkg, type, entry;
6630             try {
6631                 final Resources res = getResources();
6632                 entry = res.getResourceEntryName(id);
6633                 type = res.getResourceTypeName(id);
6634                 pkg = res.getResourcePackageName(id);
6635             } catch (Resources.NotFoundException e) {
6636                 entry = type = pkg = null;
6637             }
6638             structure.setId(id, pkg, type, entry);
6639         } else {
6640             structure.setId(id, null, null, null);
6641         }
6642         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6643         if (!hasIdentityMatrix()) {
6644             structure.setTransformation(getMatrix());
6645         }
6646         structure.setElevation(getZ());
6647         structure.setVisibility(getVisibility());
6648         structure.setEnabled(isEnabled());
6649         if (isClickable()) {
6650             structure.setClickable(true);
6651         }
6652         if (isFocusable()) {
6653             structure.setFocusable(true);
6654         }
6655         if (isFocused()) {
6656             structure.setFocused(true);
6657         }
6658         if (isAccessibilityFocused()) {
6659             structure.setAccessibilityFocused(true);
6660         }
6661         if (isSelected()) {
6662             structure.setSelected(true);
6663         }
6664         if (isActivated()) {
6665             structure.setActivated(true);
6666         }
6667         if (isLongClickable()) {
6668             structure.setLongClickable(true);
6669         }
6670         if (this instanceof Checkable) {
6671             structure.setCheckable(true);
6672             if (((Checkable)this).isChecked()) {
6673                 structure.setChecked(true);
6674             }
6675         }
6676         if (isContextClickable()) {
6677             structure.setContextClickable(true);
6678         }
6679         structure.setClassName(getAccessibilityClassName().toString());
6680         structure.setContentDescription(getContentDescription());
6681     }
6682 
6683     /**
6684      * Called when assist structure is being retrieved from a view as part of
6685      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6686      * generate additional virtual structure under this view.  The defaullt implementation
6687      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6688      * view's virtual accessibility nodes, if any.  You can override this for a more
6689      * optimal implementation providing this data.
6690      */
onProvideVirtualStructure(ViewStructure structure)6691     public void onProvideVirtualStructure(ViewStructure structure) {
6692         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6693         if (provider != null) {
6694             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6695             structure.setChildCount(1);
6696             ViewStructure root = structure.newChild(0);
6697             populateVirtualStructure(root, provider, info);
6698             info.recycle();
6699         }
6700     }
6701 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info)6702     private void populateVirtualStructure(ViewStructure structure,
6703             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6704         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6705                 null, null, null);
6706         Rect rect = structure.getTempRect();
6707         info.getBoundsInParent(rect);
6708         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6709         structure.setVisibility(VISIBLE);
6710         structure.setEnabled(info.isEnabled());
6711         if (info.isClickable()) {
6712             structure.setClickable(true);
6713         }
6714         if (info.isFocusable()) {
6715             structure.setFocusable(true);
6716         }
6717         if (info.isFocused()) {
6718             structure.setFocused(true);
6719         }
6720         if (info.isAccessibilityFocused()) {
6721             structure.setAccessibilityFocused(true);
6722         }
6723         if (info.isSelected()) {
6724             structure.setSelected(true);
6725         }
6726         if (info.isLongClickable()) {
6727             structure.setLongClickable(true);
6728         }
6729         if (info.isCheckable()) {
6730             structure.setCheckable(true);
6731             if (info.isChecked()) {
6732                 structure.setChecked(true);
6733             }
6734         }
6735         if (info.isContextClickable()) {
6736             structure.setContextClickable(true);
6737         }
6738         CharSequence cname = info.getClassName();
6739         structure.setClassName(cname != null ? cname.toString() : null);
6740         structure.setContentDescription(info.getContentDescription());
6741         if (info.getText() != null || info.getError() != null) {
6742             structure.setText(info.getText(), info.getTextSelectionStart(),
6743                     info.getTextSelectionEnd());
6744         }
6745         final int NCHILDREN = info.getChildCount();
6746         if (NCHILDREN > 0) {
6747             structure.setChildCount(NCHILDREN);
6748             for (int i=0; i<NCHILDREN; i++) {
6749                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6750                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6751                 ViewStructure child = structure.newChild(i);
6752                 populateVirtualStructure(child, provider, cinfo);
6753                 cinfo.recycle();
6754             }
6755         }
6756     }
6757 
6758     /**
6759      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6760      * implementation calls {@link #onProvideStructure} and
6761      * {@link #onProvideVirtualStructure}.
6762      */
dispatchProvideStructure(ViewStructure structure)6763     public void dispatchProvideStructure(ViewStructure structure) {
6764         if (!isAssistBlocked()) {
6765             onProvideStructure(structure);
6766             onProvideVirtualStructure(structure);
6767         } else {
6768             structure.setClassName(getAccessibilityClassName().toString());
6769             structure.setAssistBlocked(true);
6770         }
6771     }
6772 
6773     /**
6774      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6775      *
6776      * Note: Called from the default {@link AccessibilityDelegate}.
6777      *
6778      * @hide
6779      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)6780     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6781         if (mAttachInfo == null) {
6782             return;
6783         }
6784 
6785         Rect bounds = mAttachInfo.mTmpInvalRect;
6786 
6787         getDrawingRect(bounds);
6788         info.setBoundsInParent(bounds);
6789 
6790         getBoundsOnScreen(bounds, true);
6791         info.setBoundsInScreen(bounds);
6792 
6793         ViewParent parent = getParentForAccessibility();
6794         if (parent instanceof View) {
6795             info.setParent((View) parent);
6796         }
6797 
6798         if (mID != View.NO_ID) {
6799             View rootView = getRootView();
6800             if (rootView == null) {
6801                 rootView = this;
6802             }
6803 
6804             View label = rootView.findLabelForView(this, mID);
6805             if (label != null) {
6806                 info.setLabeledBy(label);
6807             }
6808 
6809             if ((mAttachInfo.mAccessibilityFetchFlags
6810                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6811                     && Resources.resourceHasPackage(mID)) {
6812                 try {
6813                     String viewId = getResources().getResourceName(mID);
6814                     info.setViewIdResourceName(viewId);
6815                 } catch (Resources.NotFoundException nfe) {
6816                     /* ignore */
6817                 }
6818             }
6819         }
6820 
6821         if (mLabelForId != View.NO_ID) {
6822             View rootView = getRootView();
6823             if (rootView == null) {
6824                 rootView = this;
6825             }
6826             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6827             if (labeled != null) {
6828                 info.setLabelFor(labeled);
6829             }
6830         }
6831 
6832         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6833             View rootView = getRootView();
6834             if (rootView == null) {
6835                 rootView = this;
6836             }
6837             View next = rootView.findViewInsideOutShouldExist(this,
6838                     mAccessibilityTraversalBeforeId);
6839             if (next != null && next.includeForAccessibility()) {
6840                 info.setTraversalBefore(next);
6841             }
6842         }
6843 
6844         if (mAccessibilityTraversalAfterId != View.NO_ID) {
6845             View rootView = getRootView();
6846             if (rootView == null) {
6847                 rootView = this;
6848             }
6849             View next = rootView.findViewInsideOutShouldExist(this,
6850                     mAccessibilityTraversalAfterId);
6851             if (next != null && next.includeForAccessibility()) {
6852                 info.setTraversalAfter(next);
6853             }
6854         }
6855 
6856         info.setVisibleToUser(isVisibleToUser());
6857 
6858         if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6859                 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6860             info.setImportantForAccessibility(isImportantForAccessibility());
6861         } else {
6862             info.setImportantForAccessibility(true);
6863         }
6864 
6865         info.setPackageName(mContext.getPackageName());
6866         info.setClassName(getAccessibilityClassName());
6867         info.setContentDescription(getContentDescription());
6868 
6869         info.setEnabled(isEnabled());
6870         info.setClickable(isClickable());
6871         info.setFocusable(isFocusable());
6872         info.setFocused(isFocused());
6873         info.setAccessibilityFocused(isAccessibilityFocused());
6874         info.setSelected(isSelected());
6875         info.setLongClickable(isLongClickable());
6876         info.setContextClickable(isContextClickable());
6877         info.setLiveRegion(getAccessibilityLiveRegion());
6878 
6879         // TODO: These make sense only if we are in an AdapterView but all
6880         // views can be selected. Maybe from accessibility perspective
6881         // we should report as selectable view in an AdapterView.
6882         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6883         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6884 
6885         if (isFocusable()) {
6886             if (isFocused()) {
6887                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6888             } else {
6889                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6890             }
6891         }
6892 
6893         if (!isAccessibilityFocused()) {
6894             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6895         } else {
6896             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6897         }
6898 
6899         if (isClickable() && isEnabled()) {
6900             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6901         }
6902 
6903         if (isLongClickable() && isEnabled()) {
6904             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6905         }
6906 
6907         if (isContextClickable() && isEnabled()) {
6908             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6909         }
6910 
6911         CharSequence text = getIterableTextForAccessibility();
6912         if (text != null && text.length() > 0) {
6913             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6914 
6915             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6916             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6917             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6918             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6919                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6920                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6921         }
6922 
6923         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6924         populateAccessibilityNodeInfoDrawingOrderInParent(info);
6925     }
6926 
6927     /**
6928      * Determine the order in which this view will be drawn relative to its siblings for a11y
6929      *
6930      * @param info The info whose drawing order should be populated
6931      */
populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)6932     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
6933         /*
6934          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
6935          * drawing order may not be well-defined, and some Views with custom drawing order may
6936          * not be initialized sufficiently to respond properly getChildDrawingOrder.
6937          */
6938         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
6939             info.setDrawingOrder(0);
6940             return;
6941         }
6942         int drawingOrderInParent = 1;
6943         // Iterate up the hierarchy if parents are not important for a11y
6944         View viewAtDrawingLevel = this;
6945         final ViewParent parent = getParentForAccessibility();
6946         while (viewAtDrawingLevel != parent) {
6947             final ViewParent currentParent = viewAtDrawingLevel.getParent();
6948             if (!(currentParent instanceof ViewGroup)) {
6949                 // Should only happen for the Decor
6950                 drawingOrderInParent = 0;
6951                 break;
6952             } else {
6953                 final ViewGroup parentGroup = (ViewGroup) currentParent;
6954                 final int childCount = parentGroup.getChildCount();
6955                 if (childCount > 1) {
6956                     List<View> preorderedList = parentGroup.buildOrderedChildList();
6957                     if (preorderedList != null) {
6958                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
6959                         for (int i = 0; i < childDrawIndex; i++) {
6960                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
6961                         }
6962                     } else {
6963                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
6964                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
6965                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
6966                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
6967                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
6968                         if (childDrawIndex != 0) {
6969                             for (int i = 0; i < numChildrenToIterate; i++) {
6970                                 final int otherDrawIndex = (customOrder ?
6971                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
6972                                 if (otherDrawIndex < childDrawIndex) {
6973                                     drawingOrderInParent +=
6974                                             numViewsForAccessibility(parentGroup.getChildAt(i));
6975                                 }
6976                             }
6977                         }
6978                     }
6979                 }
6980             }
6981             viewAtDrawingLevel = (View) currentParent;
6982         }
6983         info.setDrawingOrder(drawingOrderInParent);
6984     }
6985 
numViewsForAccessibility(View view)6986     private static int numViewsForAccessibility(View view) {
6987         if (view != null) {
6988             if (view.includeForAccessibility()) {
6989                 return 1;
6990             } else if (view instanceof ViewGroup) {
6991                 return ((ViewGroup) view).getNumChildrenForAccessibility();
6992             }
6993         }
6994         return 0;
6995     }
6996 
findLabelForView(View view, int labeledId)6997     private View findLabelForView(View view, int labeledId) {
6998         if (mMatchLabelForPredicate == null) {
6999             mMatchLabelForPredicate = new MatchLabelForPredicate();
7000         }
7001         mMatchLabelForPredicate.mLabeledId = labeledId;
7002         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7003     }
7004 
7005     /**
7006      * Computes whether this view is visible to the user. Such a view is
7007      * attached, visible, all its predecessors are visible, it is not clipped
7008      * entirely by its predecessors, and has an alpha greater than zero.
7009      *
7010      * @return Whether the view is visible on the screen.
7011      *
7012      * @hide
7013      */
isVisibleToUser()7014     protected boolean isVisibleToUser() {
7015         return isVisibleToUser(null);
7016     }
7017 
7018     /**
7019      * Computes whether the given portion of this view is visible to the user.
7020      * Such a view is attached, visible, all its predecessors are visible,
7021      * has an alpha greater than zero, and the specified portion is not
7022      * clipped entirely by its predecessors.
7023      *
7024      * @param boundInView the portion of the view to test; coordinates should be relative; may be
7025      *                    <code>null</code>, and the entire view will be tested in this case.
7026      *                    When <code>true</code> is returned by the function, the actual visible
7027      *                    region will be stored in this parameter; that is, if boundInView is fully
7028      *                    contained within the view, no modification will be made, otherwise regions
7029      *                    outside of the visible area of the view will be clipped.
7030      *
7031      * @return Whether the specified portion of the view is visible on the screen.
7032      *
7033      * @hide
7034      */
isVisibleToUser(Rect boundInView)7035     protected boolean isVisibleToUser(Rect boundInView) {
7036         if (mAttachInfo != null) {
7037             // Attached to invisible window means this view is not visible.
7038             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7039                 return false;
7040             }
7041             // An invisible predecessor or one with alpha zero means
7042             // that this view is not visible to the user.
7043             Object current = this;
7044             while (current instanceof View) {
7045                 View view = (View) current;
7046                 // We have attach info so this view is attached and there is no
7047                 // need to check whether we reach to ViewRootImpl on the way up.
7048                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7049                         view.getVisibility() != VISIBLE) {
7050                     return false;
7051                 }
7052                 current = view.mParent;
7053             }
7054             // Check if the view is entirely covered by its predecessors.
7055             Rect visibleRect = mAttachInfo.mTmpInvalRect;
7056             Point offset = mAttachInfo.mPoint;
7057             if (!getGlobalVisibleRect(visibleRect, offset)) {
7058                 return false;
7059             }
7060             // Check if the visible portion intersects the rectangle of interest.
7061             if (boundInView != null) {
7062                 visibleRect.offset(-offset.x, -offset.y);
7063                 return boundInView.intersect(visibleRect);
7064             }
7065             return true;
7066         }
7067         return false;
7068     }
7069 
7070     /**
7071      * Returns the delegate for implementing accessibility support via
7072      * composition. For more details see {@link AccessibilityDelegate}.
7073      *
7074      * @return The delegate, or null if none set.
7075      *
7076      * @hide
7077      */
getAccessibilityDelegate()7078     public AccessibilityDelegate getAccessibilityDelegate() {
7079         return mAccessibilityDelegate;
7080     }
7081 
7082     /**
7083      * Sets a delegate for implementing accessibility support via composition
7084      * (as opposed to inheritance). For more details, see
7085      * {@link AccessibilityDelegate}.
7086      * <p>
7087      * <strong>Note:</strong> On platform versions prior to
7088      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7089      * views in the {@code android.widget.*} package are called <i>before</i>
7090      * host methods. This prevents certain properties such as class name from
7091      * being modified by overriding
7092      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7093      * as any changes will be overwritten by the host class.
7094      * <p>
7095      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7096      * methods are called <i>after</i> host methods, which all properties to be
7097      * modified without being overwritten by the host class.
7098      *
7099      * @param delegate the object to which accessibility method calls should be
7100      *                 delegated
7101      * @see AccessibilityDelegate
7102      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)7103     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7104         mAccessibilityDelegate = delegate;
7105     }
7106 
7107     /**
7108      * Gets the provider for managing a virtual view hierarchy rooted at this View
7109      * and reported to {@link android.accessibilityservice.AccessibilityService}s
7110      * that explore the window content.
7111      * <p>
7112      * If this method returns an instance, this instance is responsible for managing
7113      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7114      * View including the one representing the View itself. Similarly the returned
7115      * instance is responsible for performing accessibility actions on any virtual
7116      * view or the root view itself.
7117      * </p>
7118      * <p>
7119      * If an {@link AccessibilityDelegate} has been specified via calling
7120      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7121      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7122      * is responsible for handling this call.
7123      * </p>
7124      *
7125      * @return The provider.
7126      *
7127      * @see AccessibilityNodeProvider
7128      */
getAccessibilityNodeProvider()7129     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7130         if (mAccessibilityDelegate != null) {
7131             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7132         } else {
7133             return null;
7134         }
7135     }
7136 
7137     /**
7138      * Gets the unique identifier of this view on the screen for accessibility purposes.
7139      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7140      *
7141      * @return The view accessibility id.
7142      *
7143      * @hide
7144      */
getAccessibilityViewId()7145     public int getAccessibilityViewId() {
7146         if (mAccessibilityViewId == NO_ID) {
7147             mAccessibilityViewId = sNextAccessibilityViewId++;
7148         }
7149         return mAccessibilityViewId;
7150     }
7151 
7152     /**
7153      * Gets the unique identifier of the window in which this View reseides.
7154      *
7155      * @return The window accessibility id.
7156      *
7157      * @hide
7158      */
getAccessibilityWindowId()7159     public int getAccessibilityWindowId() {
7160         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7161                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7162     }
7163 
7164     /**
7165      * Returns the {@link View}'s content description.
7166      * <p>
7167      * <strong>Note:</strong> Do not override this method, as it will have no
7168      * effect on the content description presented to accessibility services.
7169      * You must call {@link #setContentDescription(CharSequence)} to modify the
7170      * content description.
7171      *
7172      * @return the content description
7173      * @see #setContentDescription(CharSequence)
7174      * @attr ref android.R.styleable#View_contentDescription
7175      */
7176     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()7177     public CharSequence getContentDescription() {
7178         return mContentDescription;
7179     }
7180 
7181     /**
7182      * Sets the {@link View}'s content description.
7183      * <p>
7184      * A content description briefly describes the view and is primarily used
7185      * for accessibility support to determine how a view should be presented to
7186      * the user. In the case of a view with no textual representation, such as
7187      * {@link android.widget.ImageButton}, a useful content description
7188      * explains what the view does. For example, an image button with a phone
7189      * icon that is used to place a call may use "Call" as its content
7190      * description. An image of a floppy disk that is used to save a file may
7191      * use "Save".
7192      *
7193      * @param contentDescription The content description.
7194      * @see #getContentDescription()
7195      * @attr ref android.R.styleable#View_contentDescription
7196      */
7197     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)7198     public void setContentDescription(CharSequence contentDescription) {
7199         if (mContentDescription == null) {
7200             if (contentDescription == null) {
7201                 return;
7202             }
7203         } else if (mContentDescription.equals(contentDescription)) {
7204             return;
7205         }
7206         mContentDescription = contentDescription;
7207         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7208         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7209             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7210             notifySubtreeAccessibilityStateChangedIfNeeded();
7211         } else {
7212             notifyViewAccessibilityStateChangedIfNeeded(
7213                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7214         }
7215     }
7216 
7217     /**
7218      * Sets the id of a view before which this one is visited in accessibility traversal.
7219      * A screen-reader must visit the content of this view before the content of the one
7220      * it precedes. For example, if view B is set to be before view A, then a screen-reader
7221      * will traverse the entire content of B before traversing the entire content of A,
7222      * regardles of what traversal strategy it is using.
7223      * <p>
7224      * Views that do not have specified before/after relationships are traversed in order
7225      * determined by the screen-reader.
7226      * </p>
7227      * <p>
7228      * Setting that this view is before a view that is not important for accessibility
7229      * or if this view is not important for accessibility will have no effect as the
7230      * screen-reader is not aware of unimportant views.
7231      * </p>
7232      *
7233      * @param beforeId The id of a view this one precedes in accessibility traversal.
7234      *
7235      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7236      *
7237      * @see #setImportantForAccessibility(int)
7238      */
7239     @RemotableViewMethod
setAccessibilityTraversalBefore(int beforeId)7240     public void setAccessibilityTraversalBefore(int beforeId) {
7241         if (mAccessibilityTraversalBeforeId == beforeId) {
7242             return;
7243         }
7244         mAccessibilityTraversalBeforeId = beforeId;
7245         notifyViewAccessibilityStateChangedIfNeeded(
7246                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7247     }
7248 
7249     /**
7250      * Gets the id of a view before which this one is visited in accessibility traversal.
7251      *
7252      * @return The id of a view this one precedes in accessibility traversal if
7253      *         specified, otherwise {@link #NO_ID}.
7254      *
7255      * @see #setAccessibilityTraversalBefore(int)
7256      */
getAccessibilityTraversalBefore()7257     public int getAccessibilityTraversalBefore() {
7258         return mAccessibilityTraversalBeforeId;
7259     }
7260 
7261     /**
7262      * Sets the id of a view after which this one is visited in accessibility traversal.
7263      * A screen-reader must visit the content of the other view before the content of this
7264      * one. For example, if view B is set to be after view A, then a screen-reader
7265      * will traverse the entire content of A before traversing the entire content of B,
7266      * regardles of what traversal strategy it is using.
7267      * <p>
7268      * Views that do not have specified before/after relationships are traversed in order
7269      * determined by the screen-reader.
7270      * </p>
7271      * <p>
7272      * Setting that this view is after a view that is not important for accessibility
7273      * or if this view is not important for accessibility will have no effect as the
7274      * screen-reader is not aware of unimportant views.
7275      * </p>
7276      *
7277      * @param afterId The id of a view this one succedees in accessibility traversal.
7278      *
7279      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7280      *
7281      * @see #setImportantForAccessibility(int)
7282      */
7283     @RemotableViewMethod
setAccessibilityTraversalAfter(int afterId)7284     public void setAccessibilityTraversalAfter(int afterId) {
7285         if (mAccessibilityTraversalAfterId == afterId) {
7286             return;
7287         }
7288         mAccessibilityTraversalAfterId = afterId;
7289         notifyViewAccessibilityStateChangedIfNeeded(
7290                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7291     }
7292 
7293     /**
7294      * Gets the id of a view after which this one is visited in accessibility traversal.
7295      *
7296      * @return The id of a view this one succeedes in accessibility traversal if
7297      *         specified, otherwise {@link #NO_ID}.
7298      *
7299      * @see #setAccessibilityTraversalAfter(int)
7300      */
getAccessibilityTraversalAfter()7301     public int getAccessibilityTraversalAfter() {
7302         return mAccessibilityTraversalAfterId;
7303     }
7304 
7305     /**
7306      * Gets the id of a view for which this view serves as a label for
7307      * accessibility purposes.
7308      *
7309      * @return The labeled view id.
7310      */
7311     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()7312     public int getLabelFor() {
7313         return mLabelForId;
7314     }
7315 
7316     /**
7317      * Sets the id of a view for which this view serves as a label for
7318      * accessibility purposes.
7319      *
7320      * @param id The labeled view id.
7321      */
7322     @RemotableViewMethod
setLabelFor(@dRes int id)7323     public void setLabelFor(@IdRes int id) {
7324         if (mLabelForId == id) {
7325             return;
7326         }
7327         mLabelForId = id;
7328         if (mLabelForId != View.NO_ID
7329                 && mID == View.NO_ID) {
7330             mID = generateViewId();
7331         }
7332         notifyViewAccessibilityStateChangedIfNeeded(
7333                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7334     }
7335 
7336     /**
7337      * Invoked whenever this view loses focus, either by losing window focus or by losing
7338      * focus within its window. This method can be used to clear any state tied to the
7339      * focus. For instance, if a button is held pressed with the trackball and the window
7340      * loses focus, this method can be used to cancel the press.
7341      *
7342      * Subclasses of View overriding this method should always call super.onFocusLost().
7343      *
7344      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7345      * @see #onWindowFocusChanged(boolean)
7346      *
7347      * @hide pending API council approval
7348      */
7349     @CallSuper
onFocusLost()7350     protected void onFocusLost() {
7351         resetPressedState();
7352     }
7353 
resetPressedState()7354     private void resetPressedState() {
7355         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7356             return;
7357         }
7358 
7359         if (isPressed()) {
7360             setPressed(false);
7361 
7362             if (!mHasPerformedLongPress) {
7363                 removeLongPressCallback();
7364             }
7365         }
7366     }
7367 
7368     /**
7369      * Returns true if this view has focus
7370      *
7371      * @return True if this view has focus, false otherwise.
7372      */
7373     @ViewDebug.ExportedProperty(category = "focus")
isFocused()7374     public boolean isFocused() {
7375         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7376     }
7377 
7378     /**
7379      * Find the view in the hierarchy rooted at this view that currently has
7380      * focus.
7381      *
7382      * @return The view that currently has focus, or null if no focused view can
7383      *         be found.
7384      */
findFocus()7385     public View findFocus() {
7386         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7387     }
7388 
7389     /**
7390      * Indicates whether this view is one of the set of scrollable containers in
7391      * its window.
7392      *
7393      * @return whether this view is one of the set of scrollable containers in
7394      * its window
7395      *
7396      * @attr ref android.R.styleable#View_isScrollContainer
7397      */
isScrollContainer()7398     public boolean isScrollContainer() {
7399         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7400     }
7401 
7402     /**
7403      * Change whether this view is one of the set of scrollable containers in
7404      * its window.  This will be used to determine whether the window can
7405      * resize or must pan when a soft input area is open -- scrollable
7406      * containers allow the window to use resize mode since the container
7407      * will appropriately shrink.
7408      *
7409      * @attr ref android.R.styleable#View_isScrollContainer
7410      */
setScrollContainer(boolean isScrollContainer)7411     public void setScrollContainer(boolean isScrollContainer) {
7412         if (isScrollContainer) {
7413             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7414                 mAttachInfo.mScrollContainers.add(this);
7415                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7416             }
7417             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7418         } else {
7419             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7420                 mAttachInfo.mScrollContainers.remove(this);
7421             }
7422             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7423         }
7424     }
7425 
7426     /**
7427      * Returns the quality of the drawing cache.
7428      *
7429      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7430      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7431      *
7432      * @see #setDrawingCacheQuality(int)
7433      * @see #setDrawingCacheEnabled(boolean)
7434      * @see #isDrawingCacheEnabled()
7435      *
7436      * @attr ref android.R.styleable#View_drawingCacheQuality
7437      */
7438     @DrawingCacheQuality
getDrawingCacheQuality()7439     public int getDrawingCacheQuality() {
7440         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7441     }
7442 
7443     /**
7444      * Set the drawing cache quality of this view. This value is used only when the
7445      * drawing cache is enabled
7446      *
7447      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7448      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7449      *
7450      * @see #getDrawingCacheQuality()
7451      * @see #setDrawingCacheEnabled(boolean)
7452      * @see #isDrawingCacheEnabled()
7453      *
7454      * @attr ref android.R.styleable#View_drawingCacheQuality
7455      */
setDrawingCacheQuality(@rawingCacheQuality int quality)7456     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7457         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7458     }
7459 
7460     /**
7461      * Returns whether the screen should remain on, corresponding to the current
7462      * value of {@link #KEEP_SCREEN_ON}.
7463      *
7464      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7465      *
7466      * @see #setKeepScreenOn(boolean)
7467      *
7468      * @attr ref android.R.styleable#View_keepScreenOn
7469      */
getKeepScreenOn()7470     public boolean getKeepScreenOn() {
7471         return (mViewFlags & KEEP_SCREEN_ON) != 0;
7472     }
7473 
7474     /**
7475      * Controls whether the screen should remain on, modifying the
7476      * value of {@link #KEEP_SCREEN_ON}.
7477      *
7478      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7479      *
7480      * @see #getKeepScreenOn()
7481      *
7482      * @attr ref android.R.styleable#View_keepScreenOn
7483      */
setKeepScreenOn(boolean keepScreenOn)7484     public void setKeepScreenOn(boolean keepScreenOn) {
7485         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7486     }
7487 
7488     /**
7489      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7490      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7491      *
7492      * @attr ref android.R.styleable#View_nextFocusLeft
7493      */
getNextFocusLeftId()7494     public int getNextFocusLeftId() {
7495         return mNextFocusLeftId;
7496     }
7497 
7498     /**
7499      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7500      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7501      * decide automatically.
7502      *
7503      * @attr ref android.R.styleable#View_nextFocusLeft
7504      */
setNextFocusLeftId(int nextFocusLeftId)7505     public void setNextFocusLeftId(int nextFocusLeftId) {
7506         mNextFocusLeftId = nextFocusLeftId;
7507     }
7508 
7509     /**
7510      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7511      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7512      *
7513      * @attr ref android.R.styleable#View_nextFocusRight
7514      */
getNextFocusRightId()7515     public int getNextFocusRightId() {
7516         return mNextFocusRightId;
7517     }
7518 
7519     /**
7520      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7521      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7522      * decide automatically.
7523      *
7524      * @attr ref android.R.styleable#View_nextFocusRight
7525      */
setNextFocusRightId(int nextFocusRightId)7526     public void setNextFocusRightId(int nextFocusRightId) {
7527         mNextFocusRightId = nextFocusRightId;
7528     }
7529 
7530     /**
7531      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7532      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7533      *
7534      * @attr ref android.R.styleable#View_nextFocusUp
7535      */
getNextFocusUpId()7536     public int getNextFocusUpId() {
7537         return mNextFocusUpId;
7538     }
7539 
7540     /**
7541      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7542      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7543      * decide automatically.
7544      *
7545      * @attr ref android.R.styleable#View_nextFocusUp
7546      */
setNextFocusUpId(int nextFocusUpId)7547     public void setNextFocusUpId(int nextFocusUpId) {
7548         mNextFocusUpId = nextFocusUpId;
7549     }
7550 
7551     /**
7552      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7553      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7554      *
7555      * @attr ref android.R.styleable#View_nextFocusDown
7556      */
getNextFocusDownId()7557     public int getNextFocusDownId() {
7558         return mNextFocusDownId;
7559     }
7560 
7561     /**
7562      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7563      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7564      * decide automatically.
7565      *
7566      * @attr ref android.R.styleable#View_nextFocusDown
7567      */
setNextFocusDownId(int nextFocusDownId)7568     public void setNextFocusDownId(int nextFocusDownId) {
7569         mNextFocusDownId = nextFocusDownId;
7570     }
7571 
7572     /**
7573      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7574      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7575      *
7576      * @attr ref android.R.styleable#View_nextFocusForward
7577      */
getNextFocusForwardId()7578     public int getNextFocusForwardId() {
7579         return mNextFocusForwardId;
7580     }
7581 
7582     /**
7583      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7584      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7585      * decide automatically.
7586      *
7587      * @attr ref android.R.styleable#View_nextFocusForward
7588      */
setNextFocusForwardId(int nextFocusForwardId)7589     public void setNextFocusForwardId(int nextFocusForwardId) {
7590         mNextFocusForwardId = nextFocusForwardId;
7591     }
7592 
7593     /**
7594      * Returns the visibility of this view and all of its ancestors
7595      *
7596      * @return True if this view and all of its ancestors are {@link #VISIBLE}
7597      */
isShown()7598     public boolean isShown() {
7599         View current = this;
7600         //noinspection ConstantConditions
7601         do {
7602             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7603                 return false;
7604             }
7605             ViewParent parent = current.mParent;
7606             if (parent == null) {
7607                 return false; // We are not attached to the view root
7608             }
7609             if (!(parent instanceof View)) {
7610                 return true;
7611             }
7612             current = (View) parent;
7613         } while (current != null);
7614 
7615         return false;
7616     }
7617 
7618     /**
7619      * Called by the view hierarchy when the content insets for a window have
7620      * changed, to allow it to adjust its content to fit within those windows.
7621      * The content insets tell you the space that the status bar, input method,
7622      * and other system windows infringe on the application's window.
7623      *
7624      * <p>You do not normally need to deal with this function, since the default
7625      * window decoration given to applications takes care of applying it to the
7626      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7627      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7628      * and your content can be placed under those system elements.  You can then
7629      * use this method within your view hierarchy if you have parts of your UI
7630      * which you would like to ensure are not being covered.
7631      *
7632      * <p>The default implementation of this method simply applies the content
7633      * insets to the view's padding, consuming that content (modifying the
7634      * insets to be 0), and returning true.  This behavior is off by default, but can
7635      * be enabled through {@link #setFitsSystemWindows(boolean)}.
7636      *
7637      * <p>This function's traversal down the hierarchy is depth-first.  The same content
7638      * insets object is propagated down the hierarchy, so any changes made to it will
7639      * be seen by all following views (including potentially ones above in
7640      * the hierarchy since this is a depth-first traversal).  The first view
7641      * that returns true will abort the entire traversal.
7642      *
7643      * <p>The default implementation works well for a situation where it is
7644      * used with a container that covers the entire window, allowing it to
7645      * apply the appropriate insets to its content on all edges.  If you need
7646      * a more complicated layout (such as two different views fitting system
7647      * windows, one on the top of the window, and one on the bottom),
7648      * you can override the method and handle the insets however you would like.
7649      * Note that the insets provided by the framework are always relative to the
7650      * far edges of the window, not accounting for the location of the called view
7651      * within that window.  (In fact when this method is called you do not yet know
7652      * where the layout will place the view, as it is done before layout happens.)
7653      *
7654      * <p>Note: unlike many View methods, there is no dispatch phase to this
7655      * call.  If you are overriding it in a ViewGroup and want to allow the
7656      * call to continue to your children, you must be sure to call the super
7657      * implementation.
7658      *
7659      * <p>Here is a sample layout that makes use of fitting system windows
7660      * to have controls for a video view placed inside of the window decorations
7661      * that it hides and shows.  This can be used with code like the second
7662      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7663      *
7664      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7665      *
7666      * @param insets Current content insets of the window.  Prior to
7667      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7668      * the insets or else you and Android will be unhappy.
7669      *
7670      * @return {@code true} if this view applied the insets and it should not
7671      * continue propagating further down the hierarchy, {@code false} otherwise.
7672      * @see #getFitsSystemWindows()
7673      * @see #setFitsSystemWindows(boolean)
7674      * @see #setSystemUiVisibility(int)
7675      *
7676      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7677      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7678      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7679      * to implement handling their own insets.
7680      */
fitSystemWindows(Rect insets)7681     protected boolean fitSystemWindows(Rect insets) {
7682         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7683             if (insets == null) {
7684                 // Null insets by definition have already been consumed.
7685                 // This call cannot apply insets since there are none to apply,
7686                 // so return false.
7687                 return false;
7688             }
7689             // If we're not in the process of dispatching the newer apply insets call,
7690             // that means we're not in the compatibility path. Dispatch into the newer
7691             // apply insets path and take things from there.
7692             try {
7693                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7694                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7695             } finally {
7696                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7697             }
7698         } else {
7699             // We're being called from the newer apply insets path.
7700             // Perform the standard fallback behavior.
7701             return fitSystemWindowsInt(insets);
7702         }
7703     }
7704 
fitSystemWindowsInt(Rect insets)7705     private boolean fitSystemWindowsInt(Rect insets) {
7706         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7707             mUserPaddingStart = UNDEFINED_PADDING;
7708             mUserPaddingEnd = UNDEFINED_PADDING;
7709             Rect localInsets = sThreadLocal.get();
7710             if (localInsets == null) {
7711                 localInsets = new Rect();
7712                 sThreadLocal.set(localInsets);
7713             }
7714             boolean res = computeFitSystemWindows(insets, localInsets);
7715             mUserPaddingLeftInitial = localInsets.left;
7716             mUserPaddingRightInitial = localInsets.right;
7717             internalSetPadding(localInsets.left, localInsets.top,
7718                     localInsets.right, localInsets.bottom);
7719             return res;
7720         }
7721         return false;
7722     }
7723 
7724     /**
7725      * Called when the view should apply {@link WindowInsets} according to its internal policy.
7726      *
7727      * <p>This method should be overridden by views that wish to apply a policy different from or
7728      * in addition to the default behavior. Clients that wish to force a view subtree
7729      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7730      *
7731      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7732      * it will be called during dispatch instead of this method. The listener may optionally
7733      * call this method from its own implementation if it wishes to apply the view's default
7734      * insets policy in addition to its own.</p>
7735      *
7736      * <p>Implementations of this method should either return the insets parameter unchanged
7737      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7738      * that this view applied itself. This allows new inset types added in future platform
7739      * versions to pass through existing implementations unchanged without being erroneously
7740      * consumed.</p>
7741      *
7742      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7743      * property is set then the view will consume the system window insets and apply them
7744      * as padding for the view.</p>
7745      *
7746      * @param insets Insets to apply
7747      * @return The supplied insets with any applied insets consumed
7748      */
onApplyWindowInsets(WindowInsets insets)7749     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7750         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7751             // We weren't called from within a direct call to fitSystemWindows,
7752             // call into it as a fallback in case we're in a class that overrides it
7753             // and has logic to perform.
7754             if (fitSystemWindows(insets.getSystemWindowInsets())) {
7755                 return insets.consumeSystemWindowInsets();
7756             }
7757         } else {
7758             // We were called from within a direct call to fitSystemWindows.
7759             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7760                 return insets.consumeSystemWindowInsets();
7761             }
7762         }
7763         return insets;
7764     }
7765 
7766     /**
7767      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7768      * window insets to this view. The listener's
7769      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7770      * method will be called instead of the view's
7771      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7772      *
7773      * @param listener Listener to set
7774      *
7775      * @see #onApplyWindowInsets(WindowInsets)
7776      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)7777     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7778         getListenerInfo().mOnApplyWindowInsetsListener = listener;
7779     }
7780 
7781     /**
7782      * Request to apply the given window insets to this view or another view in its subtree.
7783      *
7784      * <p>This method should be called by clients wishing to apply insets corresponding to areas
7785      * obscured by window decorations or overlays. This can include the status and navigation bars,
7786      * action bars, input methods and more. New inset categories may be added in the future.
7787      * The method returns the insets provided minus any that were applied by this view or its
7788      * children.</p>
7789      *
7790      * <p>Clients wishing to provide custom behavior should override the
7791      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7792      * {@link OnApplyWindowInsetsListener} via the
7793      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7794      * method.</p>
7795      *
7796      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7797      * </p>
7798      *
7799      * @param insets Insets to apply
7800      * @return The provided insets minus the insets that were consumed
7801      */
dispatchApplyWindowInsets(WindowInsets insets)7802     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7803         try {
7804             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7805             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7806                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7807             } else {
7808                 return onApplyWindowInsets(insets);
7809             }
7810         } finally {
7811             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7812         }
7813     }
7814 
7815     /**
7816      * Compute the view's coordinate within the surface.
7817      *
7818      * <p>Computes the coordinates of this view in its surface. The argument
7819      * must be an array of two integers. After the method returns, the array
7820      * contains the x and y location in that order.</p>
7821      * @hide
7822      * @param location an array of two integers in which to hold the coordinates
7823      */
getLocationInSurface(@ize2) int[] location)7824     public void getLocationInSurface(@Size(2) int[] location) {
7825         getLocationInWindow(location);
7826         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7827             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7828             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7829         }
7830     }
7831 
7832     /**
7833      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7834      * only available if the view is attached.
7835      *
7836      * @return WindowInsets from the top of the view hierarchy or null if View is detached
7837      */
getRootWindowInsets()7838     public WindowInsets getRootWindowInsets() {
7839         if (mAttachInfo != null) {
7840             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7841         }
7842         return null;
7843     }
7844 
7845     /**
7846      * @hide Compute the insets that should be consumed by this view and the ones
7847      * that should propagate to those under it.
7848      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)7849     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7850         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7851                 || mAttachInfo == null
7852                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7853                         && !mAttachInfo.mOverscanRequested)) {
7854             outLocalInsets.set(inoutInsets);
7855             inoutInsets.set(0, 0, 0, 0);
7856             return true;
7857         } else {
7858             // The application wants to take care of fitting system window for
7859             // the content...  however we still need to take care of any overscan here.
7860             final Rect overscan = mAttachInfo.mOverscanInsets;
7861             outLocalInsets.set(overscan);
7862             inoutInsets.left -= overscan.left;
7863             inoutInsets.top -= overscan.top;
7864             inoutInsets.right -= overscan.right;
7865             inoutInsets.bottom -= overscan.bottom;
7866             return false;
7867         }
7868     }
7869 
7870     /**
7871      * Compute insets that should be consumed by this view and the ones that should propagate
7872      * to those under it.
7873      *
7874      * @param in Insets currently being processed by this View, likely received as a parameter
7875      *           to {@link #onApplyWindowInsets(WindowInsets)}.
7876      * @param outLocalInsets A Rect that will receive the insets that should be consumed
7877      *                       by this view
7878      * @return Insets that should be passed along to views under this one
7879      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)7880     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7881         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7882                 || mAttachInfo == null
7883                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7884             outLocalInsets.set(in.getSystemWindowInsets());
7885             return in.consumeSystemWindowInsets();
7886         } else {
7887             outLocalInsets.set(0, 0, 0, 0);
7888             return in;
7889         }
7890     }
7891 
7892     /**
7893      * Sets whether or not this view should account for system screen decorations
7894      * such as the status bar and inset its content; that is, controlling whether
7895      * the default implementation of {@link #fitSystemWindows(Rect)} will be
7896      * executed.  See that method for more details.
7897      *
7898      * <p>Note that if you are providing your own implementation of
7899      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7900      * flag to true -- your implementation will be overriding the default
7901      * implementation that checks this flag.
7902      *
7903      * @param fitSystemWindows If true, then the default implementation of
7904      * {@link #fitSystemWindows(Rect)} will be executed.
7905      *
7906      * @attr ref android.R.styleable#View_fitsSystemWindows
7907      * @see #getFitsSystemWindows()
7908      * @see #fitSystemWindows(Rect)
7909      * @see #setSystemUiVisibility(int)
7910      */
setFitsSystemWindows(boolean fitSystemWindows)7911     public void setFitsSystemWindows(boolean fitSystemWindows) {
7912         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7913     }
7914 
7915     /**
7916      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7917      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7918      * will be executed.
7919      *
7920      * @return {@code true} if the default implementation of
7921      * {@link #fitSystemWindows(Rect)} will be executed.
7922      *
7923      * @attr ref android.R.styleable#View_fitsSystemWindows
7924      * @see #setFitsSystemWindows(boolean)
7925      * @see #fitSystemWindows(Rect)
7926      * @see #setSystemUiVisibility(int)
7927      */
7928     @ViewDebug.ExportedProperty
getFitsSystemWindows()7929     public boolean getFitsSystemWindows() {
7930         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7931     }
7932 
7933     /** @hide */
fitsSystemWindows()7934     public boolean fitsSystemWindows() {
7935         return getFitsSystemWindows();
7936     }
7937 
7938     /**
7939      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7940      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7941      */
requestFitSystemWindows()7942     public void requestFitSystemWindows() {
7943         if (mParent != null) {
7944             mParent.requestFitSystemWindows();
7945         }
7946     }
7947 
7948     /**
7949      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7950      */
requestApplyInsets()7951     public void requestApplyInsets() {
7952         requestFitSystemWindows();
7953     }
7954 
7955     /**
7956      * For use by PhoneWindow to make its own system window fitting optional.
7957      * @hide
7958      */
makeOptionalFitsSystemWindows()7959     public void makeOptionalFitsSystemWindows() {
7960         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7961     }
7962 
7963     /**
7964      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7965      * treat them as such.
7966      * @hide
7967      */
getOutsets(Rect outOutsetRect)7968     public void getOutsets(Rect outOutsetRect) {
7969         if (mAttachInfo != null) {
7970             outOutsetRect.set(mAttachInfo.mOutsets);
7971         } else {
7972             outOutsetRect.setEmpty();
7973         }
7974     }
7975 
7976     /**
7977      * Returns the visibility status for this view.
7978      *
7979      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7980      * @attr ref android.R.styleable#View_visibility
7981      */
7982     @ViewDebug.ExportedProperty(mapping = {
7983         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7984         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7985         @ViewDebug.IntToString(from = GONE,      to = "GONE")
7986     })
7987     @Visibility
getVisibility()7988     public int getVisibility() {
7989         return mViewFlags & VISIBILITY_MASK;
7990     }
7991 
7992     /**
7993      * Set the enabled state of this view.
7994      *
7995      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7996      * @attr ref android.R.styleable#View_visibility
7997      */
7998     @RemotableViewMethod
setVisibility(@isibility int visibility)7999     public void setVisibility(@Visibility int visibility) {
8000         setFlags(visibility, VISIBILITY_MASK);
8001     }
8002 
8003     /**
8004      * Returns the enabled status for this view. The interpretation of the
8005      * enabled state varies by subclass.
8006      *
8007      * @return True if this view is enabled, false otherwise.
8008      */
8009     @ViewDebug.ExportedProperty
isEnabled()8010     public boolean isEnabled() {
8011         return (mViewFlags & ENABLED_MASK) == ENABLED;
8012     }
8013 
8014     /**
8015      * Set the enabled state of this view. The interpretation of the enabled
8016      * state varies by subclass.
8017      *
8018      * @param enabled True if this view is enabled, false otherwise.
8019      */
8020     @RemotableViewMethod
setEnabled(boolean enabled)8021     public void setEnabled(boolean enabled) {
8022         if (enabled == isEnabled()) return;
8023 
8024         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8025 
8026         /*
8027          * The View most likely has to change its appearance, so refresh
8028          * the drawable state.
8029          */
8030         refreshDrawableState();
8031 
8032         // Invalidate too, since the default behavior for views is to be
8033         // be drawn at 50% alpha rather than to change the drawable.
8034         invalidate(true);
8035 
8036         if (!enabled) {
8037             cancelPendingInputEvents();
8038         }
8039     }
8040 
8041     /**
8042      * Set whether this view can receive the focus.
8043      *
8044      * Setting this to false will also ensure that this view is not focusable
8045      * in touch mode.
8046      *
8047      * @param focusable If true, this view can receive the focus.
8048      *
8049      * @see #setFocusableInTouchMode(boolean)
8050      * @attr ref android.R.styleable#View_focusable
8051      */
setFocusable(boolean focusable)8052     public void setFocusable(boolean focusable) {
8053         if (!focusable) {
8054             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8055         }
8056         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8057     }
8058 
8059     /**
8060      * Set whether this view can receive focus while in touch mode.
8061      *
8062      * Setting this to true will also ensure that this view is focusable.
8063      *
8064      * @param focusableInTouchMode If true, this view can receive the focus while
8065      *   in touch mode.
8066      *
8067      * @see #setFocusable(boolean)
8068      * @attr ref android.R.styleable#View_focusableInTouchMode
8069      */
setFocusableInTouchMode(boolean focusableInTouchMode)8070     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8071         // Focusable in touch mode should always be set before the focusable flag
8072         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8073         // which, in touch mode, will not successfully request focus on this view
8074         // because the focusable in touch mode flag is not set
8075         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8076         if (focusableInTouchMode) {
8077             setFlags(FOCUSABLE, FOCUSABLE_MASK);
8078         }
8079     }
8080 
8081     /**
8082      * Set whether this view should have sound effects enabled for events such as
8083      * clicking and touching.
8084      *
8085      * <p>You may wish to disable sound effects for a view if you already play sounds,
8086      * for instance, a dial key that plays dtmf tones.
8087      *
8088      * @param soundEffectsEnabled whether sound effects are enabled for this view.
8089      * @see #isSoundEffectsEnabled()
8090      * @see #playSoundEffect(int)
8091      * @attr ref android.R.styleable#View_soundEffectsEnabled
8092      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)8093     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8094         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8095     }
8096 
8097     /**
8098      * @return whether this view should have sound effects enabled for events such as
8099      *     clicking and touching.
8100      *
8101      * @see #setSoundEffectsEnabled(boolean)
8102      * @see #playSoundEffect(int)
8103      * @attr ref android.R.styleable#View_soundEffectsEnabled
8104      */
8105     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()8106     public boolean isSoundEffectsEnabled() {
8107         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8108     }
8109 
8110     /**
8111      * Set whether this view should have haptic feedback for events such as
8112      * long presses.
8113      *
8114      * <p>You may wish to disable haptic feedback if your view already controls
8115      * its own haptic feedback.
8116      *
8117      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8118      * @see #isHapticFeedbackEnabled()
8119      * @see #performHapticFeedback(int)
8120      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8121      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)8122     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8123         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8124     }
8125 
8126     /**
8127      * @return whether this view should have haptic feedback enabled for events
8128      * long presses.
8129      *
8130      * @see #setHapticFeedbackEnabled(boolean)
8131      * @see #performHapticFeedback(int)
8132      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8133      */
8134     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()8135     public boolean isHapticFeedbackEnabled() {
8136         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8137     }
8138 
8139     /**
8140      * Returns the layout direction for this view.
8141      *
8142      * @return One of {@link #LAYOUT_DIRECTION_LTR},
8143      *   {@link #LAYOUT_DIRECTION_RTL},
8144      *   {@link #LAYOUT_DIRECTION_INHERIT} or
8145      *   {@link #LAYOUT_DIRECTION_LOCALE}.
8146      *
8147      * @attr ref android.R.styleable#View_layoutDirection
8148      *
8149      * @hide
8150      */
8151     @ViewDebug.ExportedProperty(category = "layout", mapping = {
8152         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8153         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8154         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8155         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8156     })
8157     @LayoutDir
getRawLayoutDirection()8158     public int getRawLayoutDirection() {
8159         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8160     }
8161 
8162     /**
8163      * Set the layout direction for this view. This will propagate a reset of layout direction
8164      * resolution to the view's children and resolve layout direction for this view.
8165      *
8166      * @param layoutDirection the layout direction to set. Should be one of:
8167      *
8168      * {@link #LAYOUT_DIRECTION_LTR},
8169      * {@link #LAYOUT_DIRECTION_RTL},
8170      * {@link #LAYOUT_DIRECTION_INHERIT},
8171      * {@link #LAYOUT_DIRECTION_LOCALE}.
8172      *
8173      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8174      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8175      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8176      *
8177      * @attr ref android.R.styleable#View_layoutDirection
8178      */
8179     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)8180     public void setLayoutDirection(@LayoutDir int layoutDirection) {
8181         if (getRawLayoutDirection() != layoutDirection) {
8182             // Reset the current layout direction and the resolved one
8183             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8184             resetRtlProperties();
8185             // Set the new layout direction (filtered)
8186             mPrivateFlags2 |=
8187                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8188             // We need to resolve all RTL properties as they all depend on layout direction
8189             resolveRtlPropertiesIfNeeded();
8190             requestLayout();
8191             invalidate(true);
8192         }
8193     }
8194 
8195     /**
8196      * Returns the resolved layout direction for this view.
8197      *
8198      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8199      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8200      *
8201      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8202      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8203      *
8204      * @attr ref android.R.styleable#View_layoutDirection
8205      */
8206     @ViewDebug.ExportedProperty(category = "layout", mapping = {
8207         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8208         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8209     })
8210     @ResolvedLayoutDir
getLayoutDirection()8211     public int getLayoutDirection() {
8212         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8213         if (targetSdkVersion < JELLY_BEAN_MR1) {
8214             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8215             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8216         }
8217         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8218                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8219     }
8220 
8221     /**
8222      * Indicates whether or not this view's layout is right-to-left. This is resolved from
8223      * layout attribute and/or the inherited value from the parent
8224      *
8225      * @return true if the layout is right-to-left.
8226      *
8227      * @hide
8228      */
8229     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()8230     public boolean isLayoutRtl() {
8231         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8232     }
8233 
8234     /**
8235      * Indicates whether the view is currently tracking transient state that the
8236      * app should not need to concern itself with saving and restoring, but that
8237      * the framework should take special note to preserve when possible.
8238      *
8239      * <p>A view with transient state cannot be trivially rebound from an external
8240      * data source, such as an adapter binding item views in a list. This may be
8241      * because the view is performing an animation, tracking user selection
8242      * of content, or similar.</p>
8243      *
8244      * @return true if the view has transient state
8245      */
8246     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()8247     public boolean hasTransientState() {
8248         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8249     }
8250 
8251     /**
8252      * Set whether this view is currently tracking transient state that the
8253      * framework should attempt to preserve when possible. This flag is reference counted,
8254      * so every call to setHasTransientState(true) should be paired with a later call
8255      * to setHasTransientState(false).
8256      *
8257      * <p>A view with transient state cannot be trivially rebound from an external
8258      * data source, such as an adapter binding item views in a list. This may be
8259      * because the view is performing an animation, tracking user selection
8260      * of content, or similar.</p>
8261      *
8262      * @param hasTransientState true if this view has transient state
8263      */
setHasTransientState(boolean hasTransientState)8264     public void setHasTransientState(boolean hasTransientState) {
8265         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8266                 mTransientStateCount - 1;
8267         if (mTransientStateCount < 0) {
8268             mTransientStateCount = 0;
8269             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8270                     "unmatched pair of setHasTransientState calls");
8271         } else if ((hasTransientState && mTransientStateCount == 1) ||
8272                 (!hasTransientState && mTransientStateCount == 0)) {
8273             // update flag if we've just incremented up from 0 or decremented down to 0
8274             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8275                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8276             if (mParent != null) {
8277                 try {
8278                     mParent.childHasTransientStateChanged(this, hasTransientState);
8279                 } catch (AbstractMethodError e) {
8280                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8281                             " does not fully implement ViewParent", e);
8282                 }
8283             }
8284         }
8285     }
8286 
8287     /**
8288      * Returns true if this view is currently attached to a window.
8289      */
isAttachedToWindow()8290     public boolean isAttachedToWindow() {
8291         return mAttachInfo != null;
8292     }
8293 
8294     /**
8295      * Returns true if this view has been through at least one layout since it
8296      * was last attached to or detached from a window.
8297      */
isLaidOut()8298     public boolean isLaidOut() {
8299         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8300     }
8301 
8302     /**
8303      * If this view doesn't do any drawing on its own, set this flag to
8304      * allow further optimizations. By default, this flag is not set on
8305      * View, but could be set on some View subclasses such as ViewGroup.
8306      *
8307      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8308      * you should clear this flag.
8309      *
8310      * @param willNotDraw whether or not this View draw on its own
8311      */
setWillNotDraw(boolean willNotDraw)8312     public void setWillNotDraw(boolean willNotDraw) {
8313         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8314     }
8315 
8316     /**
8317      * Returns whether or not this View draws on its own.
8318      *
8319      * @return true if this view has nothing to draw, false otherwise
8320      */
8321     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()8322     public boolean willNotDraw() {
8323         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8324     }
8325 
8326     /**
8327      * When a View's drawing cache is enabled, drawing is redirected to an
8328      * offscreen bitmap. Some views, like an ImageView, must be able to
8329      * bypass this mechanism if they already draw a single bitmap, to avoid
8330      * unnecessary usage of the memory.
8331      *
8332      * @param willNotCacheDrawing true if this view does not cache its
8333      *        drawing, false otherwise
8334      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)8335     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8336         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8337     }
8338 
8339     /**
8340      * Returns whether or not this View can cache its drawing or not.
8341      *
8342      * @return true if this view does not cache its drawing, false otherwise
8343      */
8344     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()8345     public boolean willNotCacheDrawing() {
8346         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8347     }
8348 
8349     /**
8350      * Indicates whether this view reacts to click events or not.
8351      *
8352      * @return true if the view is clickable, false otherwise
8353      *
8354      * @see #setClickable(boolean)
8355      * @attr ref android.R.styleable#View_clickable
8356      */
8357     @ViewDebug.ExportedProperty
isClickable()8358     public boolean isClickable() {
8359         return (mViewFlags & CLICKABLE) == CLICKABLE;
8360     }
8361 
8362     /**
8363      * Enables or disables click events for this view. When a view
8364      * is clickable it will change its state to "pressed" on every click.
8365      * Subclasses should set the view clickable to visually react to
8366      * user's clicks.
8367      *
8368      * @param clickable true to make the view clickable, false otherwise
8369      *
8370      * @see #isClickable()
8371      * @attr ref android.R.styleable#View_clickable
8372      */
setClickable(boolean clickable)8373     public void setClickable(boolean clickable) {
8374         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8375     }
8376 
8377     /**
8378      * Indicates whether this view reacts to long click events or not.
8379      *
8380      * @return true if the view is long clickable, false otherwise
8381      *
8382      * @see #setLongClickable(boolean)
8383      * @attr ref android.R.styleable#View_longClickable
8384      */
isLongClickable()8385     public boolean isLongClickable() {
8386         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8387     }
8388 
8389     /**
8390      * Enables or disables long click events for this view. When a view is long
8391      * clickable it reacts to the user holding down the button for a longer
8392      * duration than a tap. This event can either launch the listener or a
8393      * context menu.
8394      *
8395      * @param longClickable true to make the view long clickable, false otherwise
8396      * @see #isLongClickable()
8397      * @attr ref android.R.styleable#View_longClickable
8398      */
setLongClickable(boolean longClickable)8399     public void setLongClickable(boolean longClickable) {
8400         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8401     }
8402 
8403     /**
8404      * Indicates whether this view reacts to context clicks or not.
8405      *
8406      * @return true if the view is context clickable, false otherwise
8407      * @see #setContextClickable(boolean)
8408      * @attr ref android.R.styleable#View_contextClickable
8409      */
isContextClickable()8410     public boolean isContextClickable() {
8411         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8412     }
8413 
8414     /**
8415      * Enables or disables context clicking for this view. This event can launch the listener.
8416      *
8417      * @param contextClickable true to make the view react to a context click, false otherwise
8418      * @see #isContextClickable()
8419      * @attr ref android.R.styleable#View_contextClickable
8420      */
setContextClickable(boolean contextClickable)8421     public void setContextClickable(boolean contextClickable) {
8422         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8423     }
8424 
8425     /**
8426      * Sets the pressed state for this view and provides a touch coordinate for
8427      * animation hinting.
8428      *
8429      * @param pressed Pass true to set the View's internal state to "pressed",
8430      *            or false to reverts the View's internal state from a
8431      *            previously set "pressed" state.
8432      * @param x The x coordinate of the touch that caused the press
8433      * @param y The y coordinate of the touch that caused the press
8434      */
setPressed(boolean pressed, float x, float y)8435     private void setPressed(boolean pressed, float x, float y) {
8436         if (pressed) {
8437             drawableHotspotChanged(x, y);
8438         }
8439 
8440         setPressed(pressed);
8441     }
8442 
8443     /**
8444      * Sets the pressed state for this view.
8445      *
8446      * @see #isClickable()
8447      * @see #setClickable(boolean)
8448      *
8449      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8450      *        the View's internal state from a previously set "pressed" state.
8451      */
setPressed(boolean pressed)8452     public void setPressed(boolean pressed) {
8453         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8454 
8455         if (pressed) {
8456             mPrivateFlags |= PFLAG_PRESSED;
8457         } else {
8458             mPrivateFlags &= ~PFLAG_PRESSED;
8459         }
8460 
8461         if (needsRefresh) {
8462             refreshDrawableState();
8463         }
8464         dispatchSetPressed(pressed);
8465     }
8466 
8467     /**
8468      * Dispatch setPressed to all of this View's children.
8469      *
8470      * @see #setPressed(boolean)
8471      *
8472      * @param pressed The new pressed state
8473      */
dispatchSetPressed(boolean pressed)8474     protected void dispatchSetPressed(boolean pressed) {
8475     }
8476 
8477     /**
8478      * Indicates whether the view is currently in pressed state. Unless
8479      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8480      * the pressed state.
8481      *
8482      * @see #setPressed(boolean)
8483      * @see #isClickable()
8484      * @see #setClickable(boolean)
8485      *
8486      * @return true if the view is currently pressed, false otherwise
8487      */
8488     @ViewDebug.ExportedProperty
isPressed()8489     public boolean isPressed() {
8490         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8491     }
8492 
8493     /**
8494      * @hide
8495      * Indicates whether this view will participate in data collection through
8496      * {@link ViewStructure}.  If true, it will not provide any data
8497      * for itself or its children.  If false, the normal data collection will be allowed.
8498      *
8499      * @return Returns false if assist data collection is not blocked, else true.
8500      *
8501      * @see #setAssistBlocked(boolean)
8502      * @attr ref android.R.styleable#View_assistBlocked
8503      */
isAssistBlocked()8504     public boolean isAssistBlocked() {
8505         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8506     }
8507 
8508     /**
8509      * @hide
8510      * Controls whether assist data collection from this view and its children is enabled
8511      * (that is, whether {@link #onProvideStructure} and
8512      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8513      * allowing normal assist collection.  Setting this to false will disable assist collection.
8514      *
8515      * @param enabled Set to true to <em>disable</em> assist data collection, or false
8516      * (the default) to allow it.
8517      *
8518      * @see #isAssistBlocked()
8519      * @see #onProvideStructure
8520      * @see #onProvideVirtualStructure
8521      * @attr ref android.R.styleable#View_assistBlocked
8522      */
setAssistBlocked(boolean enabled)8523     public void setAssistBlocked(boolean enabled) {
8524         if (enabled) {
8525             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8526         } else {
8527             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8528         }
8529     }
8530 
8531     /**
8532      * Indicates whether this view will save its state (that is,
8533      * whether its {@link #onSaveInstanceState} method will be called).
8534      *
8535      * @return Returns true if the view state saving is enabled, else false.
8536      *
8537      * @see #setSaveEnabled(boolean)
8538      * @attr ref android.R.styleable#View_saveEnabled
8539      */
isSaveEnabled()8540     public boolean isSaveEnabled() {
8541         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8542     }
8543 
8544     /**
8545      * Controls whether the saving of this view's state is
8546      * enabled (that is, whether its {@link #onSaveInstanceState} method
8547      * will be called).  Note that even if freezing is enabled, the
8548      * view still must have an id assigned to it (via {@link #setId(int)})
8549      * for its state to be saved.  This flag can only disable the
8550      * saving of this view; any child views may still have their state saved.
8551      *
8552      * @param enabled Set to false to <em>disable</em> state saving, or true
8553      * (the default) to allow it.
8554      *
8555      * @see #isSaveEnabled()
8556      * @see #setId(int)
8557      * @see #onSaveInstanceState()
8558      * @attr ref android.R.styleable#View_saveEnabled
8559      */
setSaveEnabled(boolean enabled)8560     public void setSaveEnabled(boolean enabled) {
8561         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8562     }
8563 
8564     /**
8565      * Gets whether the framework should discard touches when the view's
8566      * window is obscured by another visible window.
8567      * Refer to the {@link View} security documentation for more details.
8568      *
8569      * @return True if touch filtering is enabled.
8570      *
8571      * @see #setFilterTouchesWhenObscured(boolean)
8572      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8573      */
8574     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()8575     public boolean getFilterTouchesWhenObscured() {
8576         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8577     }
8578 
8579     /**
8580      * Sets whether the framework should discard touches when the view's
8581      * window is obscured by another visible window.
8582      * Refer to the {@link View} security documentation for more details.
8583      *
8584      * @param enabled True if touch filtering should be enabled.
8585      *
8586      * @see #getFilterTouchesWhenObscured
8587      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8588      */
setFilterTouchesWhenObscured(boolean enabled)8589     public void setFilterTouchesWhenObscured(boolean enabled) {
8590         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8591                 FILTER_TOUCHES_WHEN_OBSCURED);
8592     }
8593 
8594     /**
8595      * Indicates whether the entire hierarchy under this view will save its
8596      * state when a state saving traversal occurs from its parent.  The default
8597      * is true; if false, these views will not be saved unless
8598      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8599      *
8600      * @return Returns true if the view state saving from parent is enabled, else false.
8601      *
8602      * @see #setSaveFromParentEnabled(boolean)
8603      */
isSaveFromParentEnabled()8604     public boolean isSaveFromParentEnabled() {
8605         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8606     }
8607 
8608     /**
8609      * Controls whether the entire hierarchy under this view will save its
8610      * state when a state saving traversal occurs from its parent.  The default
8611      * is true; if false, these views will not be saved unless
8612      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8613      *
8614      * @param enabled Set to false to <em>disable</em> state saving, or true
8615      * (the default) to allow it.
8616      *
8617      * @see #isSaveFromParentEnabled()
8618      * @see #setId(int)
8619      * @see #onSaveInstanceState()
8620      */
setSaveFromParentEnabled(boolean enabled)8621     public void setSaveFromParentEnabled(boolean enabled) {
8622         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8623     }
8624 
8625 
8626     /**
8627      * Returns whether this View is able to take focus.
8628      *
8629      * @return True if this view can take focus, or false otherwise.
8630      * @attr ref android.R.styleable#View_focusable
8631      */
8632     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()8633     public final boolean isFocusable() {
8634         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8635     }
8636 
8637     /**
8638      * When a view is focusable, it may not want to take focus when in touch mode.
8639      * For example, a button would like focus when the user is navigating via a D-pad
8640      * so that the user can click on it, but once the user starts touching the screen,
8641      * the button shouldn't take focus
8642      * @return Whether the view is focusable in touch mode.
8643      * @attr ref android.R.styleable#View_focusableInTouchMode
8644      */
8645     @ViewDebug.ExportedProperty
isFocusableInTouchMode()8646     public final boolean isFocusableInTouchMode() {
8647         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8648     }
8649 
8650     /**
8651      * Find the nearest view in the specified direction that can take focus.
8652      * This does not actually give focus to that view.
8653      *
8654      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8655      *
8656      * @return The nearest focusable in the specified direction, or null if none
8657      *         can be found.
8658      */
focusSearch(@ocusRealDirection int direction)8659     public View focusSearch(@FocusRealDirection int direction) {
8660         if (mParent != null) {
8661             return mParent.focusSearch(this, direction);
8662         } else {
8663             return null;
8664         }
8665     }
8666 
8667     /**
8668      * This method is the last chance for the focused view and its ancestors to
8669      * respond to an arrow key. This is called when the focused view did not
8670      * consume the key internally, nor could the view system find a new view in
8671      * the requested direction to give focus to.
8672      *
8673      * @param focused The currently focused view.
8674      * @param direction The direction focus wants to move. One of FOCUS_UP,
8675      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8676      * @return True if the this view consumed this unhandled move.
8677      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)8678     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8679         return false;
8680     }
8681 
8682     /**
8683      * If a user manually specified the next view id for a particular direction,
8684      * use the root to look up the view.
8685      * @param root The root view of the hierarchy containing this view.
8686      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8687      * or FOCUS_BACKWARD.
8688      * @return The user specified next view, or null if there is none.
8689      */
findUserSetNextFocus(View root, @FocusDirection int direction)8690     View findUserSetNextFocus(View root, @FocusDirection int direction) {
8691         switch (direction) {
8692             case FOCUS_LEFT:
8693                 if (mNextFocusLeftId == View.NO_ID) return null;
8694                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8695             case FOCUS_RIGHT:
8696                 if (mNextFocusRightId == View.NO_ID) return null;
8697                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
8698             case FOCUS_UP:
8699                 if (mNextFocusUpId == View.NO_ID) return null;
8700                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
8701             case FOCUS_DOWN:
8702                 if (mNextFocusDownId == View.NO_ID) return null;
8703                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
8704             case FOCUS_FORWARD:
8705                 if (mNextFocusForwardId == View.NO_ID) return null;
8706                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8707             case FOCUS_BACKWARD: {
8708                 if (mID == View.NO_ID) return null;
8709                 final int id = mID;
8710                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8711                     @Override
8712                     public boolean apply(View t) {
8713                         return t.mNextFocusForwardId == id;
8714                     }
8715                 });
8716             }
8717         }
8718         return null;
8719     }
8720 
findViewInsideOutShouldExist(View root, int id)8721     private View findViewInsideOutShouldExist(View root, int id) {
8722         if (mMatchIdPredicate == null) {
8723             mMatchIdPredicate = new MatchIdPredicate();
8724         }
8725         mMatchIdPredicate.mId = id;
8726         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8727         if (result == null) {
8728             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8729         }
8730         return result;
8731     }
8732 
8733     /**
8734      * Find and return all focusable views that are descendants of this view,
8735      * possibly including this view if it is focusable itself.
8736      *
8737      * @param direction The direction of the focus
8738      * @return A list of focusable views
8739      */
getFocusables(@ocusDirection int direction)8740     public ArrayList<View> getFocusables(@FocusDirection int direction) {
8741         ArrayList<View> result = new ArrayList<View>(24);
8742         addFocusables(result, direction);
8743         return result;
8744     }
8745 
8746     /**
8747      * Add any focusable views that are descendants of this view (possibly
8748      * including this view if it is focusable itself) to views.  If we are in touch mode,
8749      * only add views that are also focusable in touch mode.
8750      *
8751      * @param views Focusable views found so far
8752      * @param direction The direction of the focus
8753      */
addFocusables(ArrayList<View> views, @FocusDirection int direction)8754     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8755         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8756     }
8757 
8758     /**
8759      * Adds any focusable views that are descendants of this view (possibly
8760      * including this view if it is focusable itself) to views. This method
8761      * adds all focusable views regardless if we are in touch mode or
8762      * only views focusable in touch mode if we are in touch mode or
8763      * only views that can take accessibility focus if accessibility is enabled
8764      * depending on the focusable mode parameter.
8765      *
8766      * @param views Focusable views found so far or null if all we are interested is
8767      *        the number of focusables.
8768      * @param direction The direction of the focus.
8769      * @param focusableMode The type of focusables to be added.
8770      *
8771      * @see #FOCUSABLES_ALL
8772      * @see #FOCUSABLES_TOUCH_MODE
8773      */
addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)8774     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8775             @FocusableMode int focusableMode) {
8776         if (views == null) {
8777             return;
8778         }
8779         if (!isFocusable()) {
8780             return;
8781         }
8782         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8783                 && !isFocusableInTouchMode()) {
8784             return;
8785         }
8786         views.add(this);
8787     }
8788 
8789     /**
8790      * Finds the Views that contain given text. The containment is case insensitive.
8791      * The search is performed by either the text that the View renders or the content
8792      * description that describes the view for accessibility purposes and the view does
8793      * not render or both. Clients can specify how the search is to be performed via
8794      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8795      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8796      *
8797      * @param outViews The output list of matching Views.
8798      * @param searched The text to match against.
8799      *
8800      * @see #FIND_VIEWS_WITH_TEXT
8801      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8802      * @see #setContentDescription(CharSequence)
8803      */
findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)8804     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8805             @FindViewFlags int flags) {
8806         if (getAccessibilityNodeProvider() != null) {
8807             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8808                 outViews.add(this);
8809             }
8810         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8811                 && (searched != null && searched.length() > 0)
8812                 && (mContentDescription != null && mContentDescription.length() > 0)) {
8813             String searchedLowerCase = searched.toString().toLowerCase();
8814             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8815             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8816                 outViews.add(this);
8817             }
8818         }
8819     }
8820 
8821     /**
8822      * Find and return all touchable views that are descendants of this view,
8823      * possibly including this view if it is touchable itself.
8824      *
8825      * @return A list of touchable views
8826      */
getTouchables()8827     public ArrayList<View> getTouchables() {
8828         ArrayList<View> result = new ArrayList<View>();
8829         addTouchables(result);
8830         return result;
8831     }
8832 
8833     /**
8834      * Add any touchable views that are descendants of this view (possibly
8835      * including this view if it is touchable itself) to views.
8836      *
8837      * @param views Touchable views found so far
8838      */
addTouchables(ArrayList<View> views)8839     public void addTouchables(ArrayList<View> views) {
8840         final int viewFlags = mViewFlags;
8841 
8842         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8843                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8844                 && (viewFlags & ENABLED_MASK) == ENABLED) {
8845             views.add(this);
8846         }
8847     }
8848 
8849     /**
8850      * Returns whether this View is accessibility focused.
8851      *
8852      * @return True if this View is accessibility focused.
8853      */
isAccessibilityFocused()8854     public boolean isAccessibilityFocused() {
8855         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8856     }
8857 
8858     /**
8859      * Call this to try to give accessibility focus to this view.
8860      *
8861      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8862      * returns false or the view is no visible or the view already has accessibility
8863      * focus.
8864      *
8865      * See also {@link #focusSearch(int)}, which is what you call to say that you
8866      * have focus, and you want your parent to look for the next one.
8867      *
8868      * @return Whether this view actually took accessibility focus.
8869      *
8870      * @hide
8871      */
requestAccessibilityFocus()8872     public boolean requestAccessibilityFocus() {
8873         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8874         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8875             return false;
8876         }
8877         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8878             return false;
8879         }
8880         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8881             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8882             ViewRootImpl viewRootImpl = getViewRootImpl();
8883             if (viewRootImpl != null) {
8884                 viewRootImpl.setAccessibilityFocus(this, null);
8885             }
8886             invalidate();
8887             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8888             return true;
8889         }
8890         return false;
8891     }
8892 
8893     /**
8894      * Call this to try to clear accessibility focus of this view.
8895      *
8896      * See also {@link #focusSearch(int)}, which is what you call to say that you
8897      * have focus, and you want your parent to look for the next one.
8898      *
8899      * @hide
8900      */
clearAccessibilityFocus()8901     public void clearAccessibilityFocus() {
8902         clearAccessibilityFocusNoCallbacks(0);
8903 
8904         // Clear the global reference of accessibility focus if this view or
8905         // any of its descendants had accessibility focus. This will NOT send
8906         // an event or update internal state if focus is cleared from a
8907         // descendant view, which may leave views in inconsistent states.
8908         final ViewRootImpl viewRootImpl = getViewRootImpl();
8909         if (viewRootImpl != null) {
8910             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8911             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8912                 viewRootImpl.setAccessibilityFocus(null, null);
8913             }
8914         }
8915     }
8916 
sendAccessibilityHoverEvent(int eventType)8917     private void sendAccessibilityHoverEvent(int eventType) {
8918         // Since we are not delivering to a client accessibility events from not
8919         // important views (unless the clinet request that) we need to fire the
8920         // event from the deepest view exposed to the client. As a consequence if
8921         // the user crosses a not exposed view the client will see enter and exit
8922         // of the exposed predecessor followed by and enter and exit of that same
8923         // predecessor when entering and exiting the not exposed descendant. This
8924         // is fine since the client has a clear idea which view is hovered at the
8925         // price of a couple more events being sent. This is a simple and
8926         // working solution.
8927         View source = this;
8928         while (true) {
8929             if (source.includeForAccessibility()) {
8930                 source.sendAccessibilityEvent(eventType);
8931                 return;
8932             }
8933             ViewParent parent = source.getParent();
8934             if (parent instanceof View) {
8935                 source = (View) parent;
8936             } else {
8937                 return;
8938             }
8939         }
8940     }
8941 
8942     /**
8943      * Clears accessibility focus without calling any callback methods
8944      * normally invoked in {@link #clearAccessibilityFocus()}. This method
8945      * is used separately from that one for clearing accessibility focus when
8946      * giving this focus to another view.
8947      *
8948      * @param action The action, if any, that led to focus being cleared. Set to
8949      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
8950      * the window.
8951      */
clearAccessibilityFocusNoCallbacks(int action)8952     void clearAccessibilityFocusNoCallbacks(int action) {
8953         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8954             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8955             invalidate();
8956             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8957                 AccessibilityEvent event = AccessibilityEvent.obtain(
8958                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8959                 event.setAction(action);
8960                 if (mAccessibilityDelegate != null) {
8961                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8962                 } else {
8963                     sendAccessibilityEventUnchecked(event);
8964                 }
8965             }
8966         }
8967     }
8968 
8969     /**
8970      * Call this to try to give focus to a specific view or to one of its
8971      * descendants.
8972      *
8973      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8974      * false), or if it is focusable and it is not focusable in touch mode
8975      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8976      *
8977      * See also {@link #focusSearch(int)}, which is what you call to say that you
8978      * have focus, and you want your parent to look for the next one.
8979      *
8980      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8981      * {@link #FOCUS_DOWN} and <code>null</code>.
8982      *
8983      * @return Whether this view or one of its descendants actually took focus.
8984      */
requestFocus()8985     public final boolean requestFocus() {
8986         return requestFocus(View.FOCUS_DOWN);
8987     }
8988 
8989     /**
8990      * Call this to try to give focus to a specific view or to one of its
8991      * descendants and give it a hint about what direction focus is heading.
8992      *
8993      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8994      * false), or if it is focusable and it is not focusable in touch mode
8995      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8996      *
8997      * See also {@link #focusSearch(int)}, which is what you call to say that you
8998      * have focus, and you want your parent to look for the next one.
8999      *
9000      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9001      * <code>null</code> set for the previously focused rectangle.
9002      *
9003      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9004      * @return Whether this view or one of its descendants actually took focus.
9005      */
requestFocus(int direction)9006     public final boolean requestFocus(int direction) {
9007         return requestFocus(direction, null);
9008     }
9009 
9010     /**
9011      * Call this to try to give focus to a specific view or to one of its descendants
9012      * and give it hints about the direction and a specific rectangle that the focus
9013      * is coming from.  The rectangle can help give larger views a finer grained hint
9014      * about where focus is coming from, and therefore, where to show selection, or
9015      * forward focus change internally.
9016      *
9017      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9018      * false), or if it is focusable and it is not focusable in touch mode
9019      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9020      *
9021      * A View will not take focus if it is not visible.
9022      *
9023      * A View will not take focus if one of its parents has
9024      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9025      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9026      *
9027      * See also {@link #focusSearch(int)}, which is what you call to say that you
9028      * have focus, and you want your parent to look for the next one.
9029      *
9030      * You may wish to override this method if your custom {@link View} has an internal
9031      * {@link View} that it wishes to forward the request to.
9032      *
9033      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9034      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9035      *        to give a finer grained hint about where focus is coming from.  May be null
9036      *        if there is no hint.
9037      * @return Whether this view or one of its descendants actually took focus.
9038      */
requestFocus(int direction, Rect previouslyFocusedRect)9039     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9040         return requestFocusNoSearch(direction, previouslyFocusedRect);
9041     }
9042 
requestFocusNoSearch(int direction, Rect previouslyFocusedRect)9043     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9044         // need to be focusable
9045         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9046                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9047             return false;
9048         }
9049 
9050         // need to be focusable in touch mode if in touch mode
9051         if (isInTouchMode() &&
9052             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9053                return false;
9054         }
9055 
9056         // need to not have any parents blocking us
9057         if (hasAncestorThatBlocksDescendantFocus()) {
9058             return false;
9059         }
9060 
9061         handleFocusGainInternal(direction, previouslyFocusedRect);
9062         return true;
9063     }
9064 
9065     /**
9066      * Call this to try to give focus to a specific view or to one of its descendants. This is a
9067      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9068      * touch mode to request focus when they are touched.
9069      *
9070      * @return Whether this view or one of its descendants actually took focus.
9071      *
9072      * @see #isInTouchMode()
9073      *
9074      */
requestFocusFromTouch()9075     public final boolean requestFocusFromTouch() {
9076         // Leave touch mode if we need to
9077         if (isInTouchMode()) {
9078             ViewRootImpl viewRoot = getViewRootImpl();
9079             if (viewRoot != null) {
9080                 viewRoot.ensureTouchMode(false);
9081             }
9082         }
9083         return requestFocus(View.FOCUS_DOWN);
9084     }
9085 
9086     /**
9087      * @return Whether any ancestor of this view blocks descendant focus.
9088      */
hasAncestorThatBlocksDescendantFocus()9089     private boolean hasAncestorThatBlocksDescendantFocus() {
9090         final boolean focusableInTouchMode = isFocusableInTouchMode();
9091         ViewParent ancestor = mParent;
9092         while (ancestor instanceof ViewGroup) {
9093             final ViewGroup vgAncestor = (ViewGroup) ancestor;
9094             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9095                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9096                 return true;
9097             } else {
9098                 ancestor = vgAncestor.getParent();
9099             }
9100         }
9101         return false;
9102     }
9103 
9104     /**
9105      * Gets the mode for determining whether this View is important for accessibility
9106      * which is if it fires accessibility events and if it is reported to
9107      * accessibility services that query the screen.
9108      *
9109      * @return The mode for determining whether a View is important for accessibility.
9110      *
9111      * @attr ref android.R.styleable#View_importantForAccessibility
9112      *
9113      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9114      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9115      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9116      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9117      */
9118     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9119             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9120             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9121             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9122             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9123                     to = "noHideDescendants")
9124         })
getImportantForAccessibility()9125     public int getImportantForAccessibility() {
9126         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9127                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9128     }
9129 
9130     /**
9131      * Sets the live region mode for this view. This indicates to accessibility
9132      * services whether they should automatically notify the user about changes
9133      * to the view's content description or text, or to the content descriptions
9134      * or text of the view's children (where applicable).
9135      * <p>
9136      * For example, in a login screen with a TextView that displays an "incorrect
9137      * password" notification, that view should be marked as a live region with
9138      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9139      * <p>
9140      * To disable change notifications for this view, use
9141      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9142      * mode for most views.
9143      * <p>
9144      * To indicate that the user should be notified of changes, use
9145      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9146      * <p>
9147      * If the view's changes should interrupt ongoing speech and notify the user
9148      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9149      *
9150      * @param mode The live region mode for this view, one of:
9151      *        <ul>
9152      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9153      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9154      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9155      *        </ul>
9156      * @attr ref android.R.styleable#View_accessibilityLiveRegion
9157      */
setAccessibilityLiveRegion(int mode)9158     public void setAccessibilityLiveRegion(int mode) {
9159         if (mode != getAccessibilityLiveRegion()) {
9160             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9161             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9162                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9163             notifyViewAccessibilityStateChangedIfNeeded(
9164                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9165         }
9166     }
9167 
9168     /**
9169      * Gets the live region mode for this View.
9170      *
9171      * @return The live region mode for the view.
9172      *
9173      * @attr ref android.R.styleable#View_accessibilityLiveRegion
9174      *
9175      * @see #setAccessibilityLiveRegion(int)
9176      */
getAccessibilityLiveRegion()9177     public int getAccessibilityLiveRegion() {
9178         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9179                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9180     }
9181 
9182     /**
9183      * Sets how to determine whether this view is important for accessibility
9184      * which is if it fires accessibility events and if it is reported to
9185      * accessibility services that query the screen.
9186      *
9187      * @param mode How to determine whether this view is important for accessibility.
9188      *
9189      * @attr ref android.R.styleable#View_importantForAccessibility
9190      *
9191      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9192      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9193      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9194      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9195      */
setImportantForAccessibility(int mode)9196     public void setImportantForAccessibility(int mode) {
9197         final int oldMode = getImportantForAccessibility();
9198         if (mode != oldMode) {
9199             final boolean hideDescendants =
9200                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9201 
9202             // If this node or its descendants are no longer important, try to
9203             // clear accessibility focus.
9204             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9205                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
9206                 if (focusHost != null) {
9207                     focusHost.clearAccessibilityFocus();
9208                 }
9209             }
9210 
9211             // If we're moving between AUTO and another state, we might not need
9212             // to send a subtree changed notification. We'll store the computed
9213             // importance, since we'll need to check it later to make sure.
9214             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9215                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9216             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9217             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9218             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9219                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9220             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9221                 notifySubtreeAccessibilityStateChangedIfNeeded();
9222             } else {
9223                 notifyViewAccessibilityStateChangedIfNeeded(
9224                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9225             }
9226         }
9227     }
9228 
9229     /**
9230      * Returns the view within this view's hierarchy that is hosting
9231      * accessibility focus.
9232      *
9233      * @param searchDescendants whether to search for focus in descendant views
9234      * @return the view hosting accessibility focus, or {@code null}
9235      */
findAccessibilityFocusHost(boolean searchDescendants)9236     private View findAccessibilityFocusHost(boolean searchDescendants) {
9237         if (isAccessibilityFocusedViewOrHost()) {
9238             return this;
9239         }
9240 
9241         if (searchDescendants) {
9242             final ViewRootImpl viewRoot = getViewRootImpl();
9243             if (viewRoot != null) {
9244                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
9245                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9246                     return focusHost;
9247                 }
9248             }
9249         }
9250 
9251         return null;
9252     }
9253 
9254     /**
9255      * Computes whether this view should be exposed for accessibility. In
9256      * general, views that are interactive or provide information are exposed
9257      * while views that serve only as containers are hidden.
9258      * <p>
9259      * If an ancestor of this view has importance
9260      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9261      * returns <code>false</code>.
9262      * <p>
9263      * Otherwise, the value is computed according to the view's
9264      * {@link #getImportantForAccessibility()} value:
9265      * <ol>
9266      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9267      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9268      * </code>
9269      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9270      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9271      * view satisfies any of the following:
9272      * <ul>
9273      * <li>Is actionable, e.g. {@link #isClickable()},
9274      * {@link #isLongClickable()}, or {@link #isFocusable()}
9275      * <li>Has an {@link AccessibilityDelegate}
9276      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9277      * {@link OnKeyListener}, etc.
9278      * <li>Is an accessibility live region, e.g.
9279      * {@link #getAccessibilityLiveRegion()} is not
9280      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9281      * </ul>
9282      * </ol>
9283      *
9284      * @return Whether the view is exposed for accessibility.
9285      * @see #setImportantForAccessibility(int)
9286      * @see #getImportantForAccessibility()
9287      */
isImportantForAccessibility()9288     public boolean isImportantForAccessibility() {
9289         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9290                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9291         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9292                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9293             return false;
9294         }
9295 
9296         // Check parent mode to ensure we're not hidden.
9297         ViewParent parent = mParent;
9298         while (parent instanceof View) {
9299             if (((View) parent).getImportantForAccessibility()
9300                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9301                 return false;
9302             }
9303             parent = parent.getParent();
9304         }
9305 
9306         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9307                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9308                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9309     }
9310 
9311     /**
9312      * Gets the parent for accessibility purposes. Note that the parent for
9313      * accessibility is not necessary the immediate parent. It is the first
9314      * predecessor that is important for accessibility.
9315      *
9316      * @return The parent for accessibility purposes.
9317      */
getParentForAccessibility()9318     public ViewParent getParentForAccessibility() {
9319         if (mParent instanceof View) {
9320             View parentView = (View) mParent;
9321             if (parentView.includeForAccessibility()) {
9322                 return mParent;
9323             } else {
9324                 return mParent.getParentForAccessibility();
9325             }
9326         }
9327         return null;
9328     }
9329 
9330     /**
9331      * Adds the children of this View relevant for accessibility to the given list
9332      * as output. Since some Views are not important for accessibility the added
9333      * child views are not necessarily direct children of this view, rather they are
9334      * the first level of descendants important for accessibility.
9335      *
9336      * @param outChildren The output list that will receive children for accessibility.
9337      */
addChildrenForAccessibility(ArrayList<View> outChildren)9338     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9339 
9340     }
9341 
9342     /**
9343      * Whether to regard this view for accessibility. A view is regarded for
9344      * accessibility if it is important for accessibility or the querying
9345      * accessibility service has explicitly requested that view not
9346      * important for accessibility are regarded.
9347      *
9348      * @return Whether to regard the view for accessibility.
9349      *
9350      * @hide
9351      */
includeForAccessibility()9352     public boolean includeForAccessibility() {
9353         if (mAttachInfo != null) {
9354             return (mAttachInfo.mAccessibilityFetchFlags
9355                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9356                     || isImportantForAccessibility();
9357         }
9358         return false;
9359     }
9360 
9361     /**
9362      * Returns whether the View is considered actionable from
9363      * accessibility perspective. Such view are important for
9364      * accessibility.
9365      *
9366      * @return True if the view is actionable for accessibility.
9367      *
9368      * @hide
9369      */
isActionableForAccessibility()9370     public boolean isActionableForAccessibility() {
9371         return (isClickable() || isLongClickable() || isFocusable());
9372     }
9373 
9374     /**
9375      * Returns whether the View has registered callbacks which makes it
9376      * important for accessibility.
9377      *
9378      * @return True if the view is actionable for accessibility.
9379      */
hasListenersForAccessibility()9380     private boolean hasListenersForAccessibility() {
9381         ListenerInfo info = getListenerInfo();
9382         return mTouchDelegate != null || info.mOnKeyListener != null
9383                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9384                 || info.mOnHoverListener != null || info.mOnDragListener != null;
9385     }
9386 
9387     /**
9388      * Notifies that the accessibility state of this view changed. The change
9389      * is local to this view and does not represent structural changes such
9390      * as children and parent. For example, the view became focusable. The
9391      * notification is at at most once every
9392      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9393      * to avoid unnecessary load to the system. Also once a view has a pending
9394      * notification this method is a NOP until the notification has been sent.
9395      *
9396      * @hide
9397      */
notifyViewAccessibilityStateChangedIfNeeded(int changeType)9398     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9399         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9400             return;
9401         }
9402         if (mSendViewStateChangedAccessibilityEvent == null) {
9403             mSendViewStateChangedAccessibilityEvent =
9404                     new SendViewStateChangedAccessibilityEvent();
9405         }
9406         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9407     }
9408 
9409     /**
9410      * Notifies that the accessibility state of this view changed. The change
9411      * is *not* local to this view and does represent structural changes such
9412      * as children and parent. For example, the view size changed. The
9413      * notification is at at most once every
9414      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9415      * to avoid unnecessary load to the system. Also once a view has a pending
9416      * notification this method is a NOP until the notification has been sent.
9417      *
9418      * @hide
9419      */
notifySubtreeAccessibilityStateChangedIfNeeded()9420     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9421         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9422             return;
9423         }
9424         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9425             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9426             if (mParent != null) {
9427                 try {
9428                     mParent.notifySubtreeAccessibilityStateChanged(
9429                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9430                 } catch (AbstractMethodError e) {
9431                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9432                             " does not fully implement ViewParent", e);
9433                 }
9434             }
9435         }
9436     }
9437 
9438     /**
9439      * Change the visibility of the View without triggering any other changes. This is
9440      * important for transitions, where visibility changes should not adjust focus or
9441      * trigger a new layout. This is only used when the visibility has already been changed
9442      * and we need a transient value during an animation. When the animation completes,
9443      * the original visibility value is always restored.
9444      *
9445      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9446      * @hide
9447      */
setTransitionVisibility(@isibility int visibility)9448     public void setTransitionVisibility(@Visibility int visibility) {
9449         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9450     }
9451 
9452     /**
9453      * Reset the flag indicating the accessibility state of the subtree rooted
9454      * at this view changed.
9455      */
resetSubtreeAccessibilityStateChanged()9456     void resetSubtreeAccessibilityStateChanged() {
9457         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9458     }
9459 
9460     /**
9461      * Report an accessibility action to this view's parents for delegated processing.
9462      *
9463      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9464      * call this method to delegate an accessibility action to a supporting parent. If the parent
9465      * returns true from its
9466      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9467      * method this method will return true to signify that the action was consumed.</p>
9468      *
9469      * <p>This method is useful for implementing nested scrolling child views. If
9470      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9471      * a custom view implementation may invoke this method to allow a parent to consume the
9472      * scroll first. If this method returns true the custom view should skip its own scrolling
9473      * behavior.</p>
9474      *
9475      * @param action Accessibility action to delegate
9476      * @param arguments Optional action arguments
9477      * @return true if the action was consumed by a parent
9478      */
dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments)9479     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9480         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9481             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9482                 return true;
9483             }
9484         }
9485         return false;
9486     }
9487 
9488     /**
9489      * Performs the specified accessibility action on the view. For
9490      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9491      * <p>
9492      * If an {@link AccessibilityDelegate} has been specified via calling
9493      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9494      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9495      * is responsible for handling this call.
9496      * </p>
9497      *
9498      * <p>The default implementation will delegate
9499      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9500      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9501      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9502      *
9503      * @param action The action to perform.
9504      * @param arguments Optional action arguments.
9505      * @return Whether the action was performed.
9506      */
performAccessibilityAction(int action, Bundle arguments)9507     public boolean performAccessibilityAction(int action, Bundle arguments) {
9508       if (mAccessibilityDelegate != null) {
9509           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9510       } else {
9511           return performAccessibilityActionInternal(action, arguments);
9512       }
9513     }
9514 
9515    /**
9516     * @see #performAccessibilityAction(int, Bundle)
9517     *
9518     * Note: Called from the default {@link AccessibilityDelegate}.
9519     *
9520     * @hide
9521     */
performAccessibilityActionInternal(int action, Bundle arguments)9522     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9523         if (isNestedScrollingEnabled()
9524                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9525                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9526                 || action == R.id.accessibilityActionScrollUp
9527                 || action == R.id.accessibilityActionScrollLeft
9528                 || action == R.id.accessibilityActionScrollDown
9529                 || action == R.id.accessibilityActionScrollRight)) {
9530             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9531                 return true;
9532             }
9533         }
9534 
9535         switch (action) {
9536             case AccessibilityNodeInfo.ACTION_CLICK: {
9537                 if (isClickable()) {
9538                     performClick();
9539                     return true;
9540                 }
9541             } break;
9542             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9543                 if (isLongClickable()) {
9544                     performLongClick();
9545                     return true;
9546                 }
9547             } break;
9548             case AccessibilityNodeInfo.ACTION_FOCUS: {
9549                 if (!hasFocus()) {
9550                     // Get out of touch mode since accessibility
9551                     // wants to move focus around.
9552                     getViewRootImpl().ensureTouchMode(false);
9553                     return requestFocus();
9554                 }
9555             } break;
9556             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9557                 if (hasFocus()) {
9558                     clearFocus();
9559                     return !isFocused();
9560                 }
9561             } break;
9562             case AccessibilityNodeInfo.ACTION_SELECT: {
9563                 if (!isSelected()) {
9564                     setSelected(true);
9565                     return isSelected();
9566                 }
9567             } break;
9568             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9569                 if (isSelected()) {
9570                     setSelected(false);
9571                     return !isSelected();
9572                 }
9573             } break;
9574             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9575                 if (!isAccessibilityFocused()) {
9576                     return requestAccessibilityFocus();
9577                 }
9578             } break;
9579             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9580                 if (isAccessibilityFocused()) {
9581                     clearAccessibilityFocus();
9582                     return true;
9583                 }
9584             } break;
9585             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9586                 if (arguments != null) {
9587                     final int granularity = arguments.getInt(
9588                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9589                     final boolean extendSelection = arguments.getBoolean(
9590                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9591                     return traverseAtGranularity(granularity, true, extendSelection);
9592                 }
9593             } break;
9594             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9595                 if (arguments != null) {
9596                     final int granularity = arguments.getInt(
9597                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9598                     final boolean extendSelection = arguments.getBoolean(
9599                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9600                     return traverseAtGranularity(granularity, false, extendSelection);
9601                 }
9602             } break;
9603             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9604                 CharSequence text = getIterableTextForAccessibility();
9605                 if (text == null) {
9606                     return false;
9607                 }
9608                 final int start = (arguments != null) ? arguments.getInt(
9609                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9610                 final int end = (arguments != null) ? arguments.getInt(
9611                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9612                 // Only cursor position can be specified (selection length == 0)
9613                 if ((getAccessibilitySelectionStart() != start
9614                         || getAccessibilitySelectionEnd() != end)
9615                         && (start == end)) {
9616                     setAccessibilitySelection(start, end);
9617                     notifyViewAccessibilityStateChangedIfNeeded(
9618                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9619                     return true;
9620                 }
9621             } break;
9622             case R.id.accessibilityActionShowOnScreen: {
9623                 if (mAttachInfo != null) {
9624                     final Rect r = mAttachInfo.mTmpInvalRect;
9625                     getDrawingRect(r);
9626                     return requestRectangleOnScreen(r, true);
9627                 }
9628             } break;
9629             case R.id.accessibilityActionContextClick: {
9630                 if (isContextClickable()) {
9631                     performContextClick();
9632                     return true;
9633                 }
9634             } break;
9635         }
9636         return false;
9637     }
9638 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)9639     private boolean traverseAtGranularity(int granularity, boolean forward,
9640             boolean extendSelection) {
9641         CharSequence text = getIterableTextForAccessibility();
9642         if (text == null || text.length() == 0) {
9643             return false;
9644         }
9645         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9646         if (iterator == null) {
9647             return false;
9648         }
9649         int current = getAccessibilitySelectionEnd();
9650         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9651             current = forward ? 0 : text.length();
9652         }
9653         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9654         if (range == null) {
9655             return false;
9656         }
9657         final int segmentStart = range[0];
9658         final int segmentEnd = range[1];
9659         int selectionStart;
9660         int selectionEnd;
9661         if (extendSelection && isAccessibilitySelectionExtendable()) {
9662             selectionStart = getAccessibilitySelectionStart();
9663             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9664                 selectionStart = forward ? segmentStart : segmentEnd;
9665             }
9666             selectionEnd = forward ? segmentEnd : segmentStart;
9667         } else {
9668             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9669         }
9670         setAccessibilitySelection(selectionStart, selectionEnd);
9671         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9672                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9673         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9674         return true;
9675     }
9676 
9677     /**
9678      * Gets the text reported for accessibility purposes.
9679      *
9680      * @return The accessibility text.
9681      *
9682      * @hide
9683      */
getIterableTextForAccessibility()9684     public CharSequence getIterableTextForAccessibility() {
9685         return getContentDescription();
9686     }
9687 
9688     /**
9689      * Gets whether accessibility selection can be extended.
9690      *
9691      * @return If selection is extensible.
9692      *
9693      * @hide
9694      */
isAccessibilitySelectionExtendable()9695     public boolean isAccessibilitySelectionExtendable() {
9696         return false;
9697     }
9698 
9699     /**
9700      * @hide
9701      */
getAccessibilitySelectionStart()9702     public int getAccessibilitySelectionStart() {
9703         return mAccessibilityCursorPosition;
9704     }
9705 
9706     /**
9707      * @hide
9708      */
getAccessibilitySelectionEnd()9709     public int getAccessibilitySelectionEnd() {
9710         return getAccessibilitySelectionStart();
9711     }
9712 
9713     /**
9714      * @hide
9715      */
setAccessibilitySelection(int start, int end)9716     public void setAccessibilitySelection(int start, int end) {
9717         if (start ==  end && end == mAccessibilityCursorPosition) {
9718             return;
9719         }
9720         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9721             mAccessibilityCursorPosition = start;
9722         } else {
9723             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9724         }
9725         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9726     }
9727 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)9728     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9729             int fromIndex, int toIndex) {
9730         if (mParent == null) {
9731             return;
9732         }
9733         AccessibilityEvent event = AccessibilityEvent.obtain(
9734                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9735         onInitializeAccessibilityEvent(event);
9736         onPopulateAccessibilityEvent(event);
9737         event.setFromIndex(fromIndex);
9738         event.setToIndex(toIndex);
9739         event.setAction(action);
9740         event.setMovementGranularity(granularity);
9741         mParent.requestSendAccessibilityEvent(this, event);
9742     }
9743 
9744     /**
9745      * @hide
9746      */
getIteratorForGranularity(int granularity)9747     public TextSegmentIterator getIteratorForGranularity(int granularity) {
9748         switch (granularity) {
9749             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9750                 CharSequence text = getIterableTextForAccessibility();
9751                 if (text != null && text.length() > 0) {
9752                     CharacterTextSegmentIterator iterator =
9753                         CharacterTextSegmentIterator.getInstance(
9754                                 mContext.getResources().getConfiguration().locale);
9755                     iterator.initialize(text.toString());
9756                     return iterator;
9757                 }
9758             } break;
9759             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9760                 CharSequence text = getIterableTextForAccessibility();
9761                 if (text != null && text.length() > 0) {
9762                     WordTextSegmentIterator iterator =
9763                         WordTextSegmentIterator.getInstance(
9764                                 mContext.getResources().getConfiguration().locale);
9765                     iterator.initialize(text.toString());
9766                     return iterator;
9767                 }
9768             } break;
9769             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9770                 CharSequence text = getIterableTextForAccessibility();
9771                 if (text != null && text.length() > 0) {
9772                     ParagraphTextSegmentIterator iterator =
9773                         ParagraphTextSegmentIterator.getInstance();
9774                     iterator.initialize(text.toString());
9775                     return iterator;
9776                 }
9777             } break;
9778         }
9779         return null;
9780     }
9781 
9782     /**
9783      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9784      * and {@link #onFinishTemporaryDetach()}.
9785      */
isTemporarilyDetached()9786     public final boolean isTemporarilyDetached() {
9787         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9788     }
9789 
9790     /**
9791      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9792      * a container View.
9793      */
9794     @CallSuper
dispatchStartTemporaryDetach()9795     public void dispatchStartTemporaryDetach() {
9796         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9797         onStartTemporaryDetach();
9798     }
9799 
9800     /**
9801      * This is called when a container is going to temporarily detach a child, with
9802      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9803      * It will either be followed by {@link #onFinishTemporaryDetach()} or
9804      * {@link #onDetachedFromWindow()} when the container is done.
9805      */
onStartTemporaryDetach()9806     public void onStartTemporaryDetach() {
9807         removeUnsetPressCallback();
9808         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9809     }
9810 
9811     /**
9812      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9813      * a container View.
9814      */
9815     @CallSuper
dispatchFinishTemporaryDetach()9816     public void dispatchFinishTemporaryDetach() {
9817         onFinishTemporaryDetach();
9818         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9819     }
9820 
9821     /**
9822      * Called after {@link #onStartTemporaryDetach} when the container is done
9823      * changing the view.
9824      */
onFinishTemporaryDetach()9825     public void onFinishTemporaryDetach() {
9826     }
9827 
9828     /**
9829      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9830      * for this view's window.  Returns null if the view is not currently attached
9831      * to the window.  Normally you will not need to use this directly, but
9832      * just use the standard high-level event callbacks like
9833      * {@link #onKeyDown(int, KeyEvent)}.
9834      */
getKeyDispatcherState()9835     public KeyEvent.DispatcherState getKeyDispatcherState() {
9836         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9837     }
9838 
9839     /**
9840      * Dispatch a key event before it is processed by any input method
9841      * associated with the view hierarchy.  This can be used to intercept
9842      * key events in special situations before the IME consumes them; a
9843      * typical example would be handling the BACK key to update the application's
9844      * UI instead of allowing the IME to see it and close itself.
9845      *
9846      * @param event The key event to be dispatched.
9847      * @return True if the event was handled, false otherwise.
9848      */
dispatchKeyEventPreIme(KeyEvent event)9849     public boolean dispatchKeyEventPreIme(KeyEvent event) {
9850         return onKeyPreIme(event.getKeyCode(), event);
9851     }
9852 
9853     /**
9854      * Dispatch a key event to the next view on the focus path. This path runs
9855      * from the top of the view tree down to the currently focused view. If this
9856      * view has focus, it will dispatch to itself. Otherwise it will dispatch
9857      * the next node down the focus path. This method also fires any key
9858      * listeners.
9859      *
9860      * @param event The key event to be dispatched.
9861      * @return True if the event was handled, false otherwise.
9862      */
dispatchKeyEvent(KeyEvent event)9863     public boolean dispatchKeyEvent(KeyEvent event) {
9864         if (mInputEventConsistencyVerifier != null) {
9865             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9866         }
9867 
9868         // Give any attached key listener a first crack at the event.
9869         //noinspection SimplifiableIfStatement
9870         ListenerInfo li = mListenerInfo;
9871         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9872                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9873             return true;
9874         }
9875 
9876         if (event.dispatch(this, mAttachInfo != null
9877                 ? mAttachInfo.mKeyDispatchState : null, this)) {
9878             return true;
9879         }
9880 
9881         if (mInputEventConsistencyVerifier != null) {
9882             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9883         }
9884         return false;
9885     }
9886 
9887     /**
9888      * Dispatches a key shortcut event.
9889      *
9890      * @param event The key event to be dispatched.
9891      * @return True if the event was handled by the view, false otherwise.
9892      */
dispatchKeyShortcutEvent(KeyEvent event)9893     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9894         return onKeyShortcut(event.getKeyCode(), event);
9895     }
9896 
9897     /**
9898      * Pass the touch screen motion event down to the target view, or this
9899      * view if it is the target.
9900      *
9901      * @param event The motion event to be dispatched.
9902      * @return True if the event was handled by the view, false otherwise.
9903      */
dispatchTouchEvent(MotionEvent event)9904     public boolean dispatchTouchEvent(MotionEvent event) {
9905         // If the event should be handled by accessibility focus first.
9906         if (event.isTargetAccessibilityFocus()) {
9907             // We don't have focus or no virtual descendant has it, do not handle the event.
9908             if (!isAccessibilityFocusedViewOrHost()) {
9909                 return false;
9910             }
9911             // We have focus and got the event, then use normal event dispatch.
9912             event.setTargetAccessibilityFocus(false);
9913         }
9914 
9915         boolean result = false;
9916 
9917         if (mInputEventConsistencyVerifier != null) {
9918             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9919         }
9920 
9921         final int actionMasked = event.getActionMasked();
9922         if (actionMasked == MotionEvent.ACTION_DOWN) {
9923             // Defensive cleanup for new gesture
9924             stopNestedScroll();
9925         }
9926 
9927         if (onFilterTouchEventForSecurity(event)) {
9928             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
9929                 result = true;
9930             }
9931             //noinspection SimplifiableIfStatement
9932             ListenerInfo li = mListenerInfo;
9933             if (li != null && li.mOnTouchListener != null
9934                     && (mViewFlags & ENABLED_MASK) == ENABLED
9935                     && li.mOnTouchListener.onTouch(this, event)) {
9936                 result = true;
9937             }
9938 
9939             if (!result && onTouchEvent(event)) {
9940                 result = true;
9941             }
9942         }
9943 
9944         if (!result && mInputEventConsistencyVerifier != null) {
9945             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9946         }
9947 
9948         // Clean up after nested scrolls if this is the end of a gesture;
9949         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9950         // of the gesture.
9951         if (actionMasked == MotionEvent.ACTION_UP ||
9952                 actionMasked == MotionEvent.ACTION_CANCEL ||
9953                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9954             stopNestedScroll();
9955         }
9956 
9957         return result;
9958     }
9959 
isAccessibilityFocusedViewOrHost()9960     boolean isAccessibilityFocusedViewOrHost() {
9961         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9962                 .getAccessibilityFocusedHost() == this);
9963     }
9964 
9965     /**
9966      * Filter the touch event to apply security policies.
9967      *
9968      * @param event The motion event to be filtered.
9969      * @return True if the event should be dispatched, false if the event should be dropped.
9970      *
9971      * @see #getFilterTouchesWhenObscured
9972      */
onFilterTouchEventForSecurity(MotionEvent event)9973     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9974         //noinspection RedundantIfStatement
9975         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9976                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9977             // Window is obscured, drop this touch.
9978             return false;
9979         }
9980         return true;
9981     }
9982 
9983     /**
9984      * Pass a trackball motion event down to the focused view.
9985      *
9986      * @param event The motion event to be dispatched.
9987      * @return True if the event was handled by the view, false otherwise.
9988      */
dispatchTrackballEvent(MotionEvent event)9989     public boolean dispatchTrackballEvent(MotionEvent event) {
9990         if (mInputEventConsistencyVerifier != null) {
9991             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9992         }
9993 
9994         return onTrackballEvent(event);
9995     }
9996 
9997     /**
9998      * Dispatch a generic motion event.
9999      * <p>
10000      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10001      * are delivered to the view under the pointer.  All other generic motion events are
10002      * delivered to the focused view.  Hover events are handled specially and are delivered
10003      * to {@link #onHoverEvent(MotionEvent)}.
10004      * </p>
10005      *
10006      * @param event The motion event to be dispatched.
10007      * @return True if the event was handled by the view, false otherwise.
10008      */
dispatchGenericMotionEvent(MotionEvent event)10009     public boolean dispatchGenericMotionEvent(MotionEvent event) {
10010         if (mInputEventConsistencyVerifier != null) {
10011             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10012         }
10013 
10014         final int source = event.getSource();
10015         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10016             final int action = event.getAction();
10017             if (action == MotionEvent.ACTION_HOVER_ENTER
10018                     || action == MotionEvent.ACTION_HOVER_MOVE
10019                     || action == MotionEvent.ACTION_HOVER_EXIT) {
10020                 if (dispatchHoverEvent(event)) {
10021                     return true;
10022                 }
10023             } else if (dispatchGenericPointerEvent(event)) {
10024                 return true;
10025             }
10026         } else if (dispatchGenericFocusedEvent(event)) {
10027             return true;
10028         }
10029 
10030         if (dispatchGenericMotionEventInternal(event)) {
10031             return true;
10032         }
10033 
10034         if (mInputEventConsistencyVerifier != null) {
10035             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10036         }
10037         return false;
10038     }
10039 
dispatchGenericMotionEventInternal(MotionEvent event)10040     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10041         //noinspection SimplifiableIfStatement
10042         ListenerInfo li = mListenerInfo;
10043         if (li != null && li.mOnGenericMotionListener != null
10044                 && (mViewFlags & ENABLED_MASK) == ENABLED
10045                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10046             return true;
10047         }
10048 
10049         if (onGenericMotionEvent(event)) {
10050             return true;
10051         }
10052 
10053         final int actionButton = event.getActionButton();
10054         switch (event.getActionMasked()) {
10055             case MotionEvent.ACTION_BUTTON_PRESS:
10056                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10057                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10058                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10059                     if (performContextClick(event.getX(), event.getY())) {
10060                         mInContextButtonPress = true;
10061                         setPressed(true, event.getX(), event.getY());
10062                         removeTapCallback();
10063                         removeLongPressCallback();
10064                         return true;
10065                     }
10066                 }
10067                 break;
10068 
10069             case MotionEvent.ACTION_BUTTON_RELEASE:
10070                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10071                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10072                     mInContextButtonPress = false;
10073                     mIgnoreNextUpEvent = true;
10074                 }
10075                 break;
10076         }
10077 
10078         if (mInputEventConsistencyVerifier != null) {
10079             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10080         }
10081         return false;
10082     }
10083 
10084     /**
10085      * Dispatch a hover event.
10086      * <p>
10087      * Do not call this method directly.
10088      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10089      * </p>
10090      *
10091      * @param event The motion event to be dispatched.
10092      * @return True if the event was handled by the view, false otherwise.
10093      */
dispatchHoverEvent(MotionEvent event)10094     protected boolean dispatchHoverEvent(MotionEvent event) {
10095         ListenerInfo li = mListenerInfo;
10096         //noinspection SimplifiableIfStatement
10097         if (li != null && li.mOnHoverListener != null
10098                 && (mViewFlags & ENABLED_MASK) == ENABLED
10099                 && li.mOnHoverListener.onHover(this, event)) {
10100             return true;
10101         }
10102 
10103         return onHoverEvent(event);
10104     }
10105 
10106     /**
10107      * Returns true if the view has a child to which it has recently sent
10108      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10109      * it does not have a hovered child, then it must be the innermost hovered view.
10110      * @hide
10111      */
hasHoveredChild()10112     protected boolean hasHoveredChild() {
10113         return false;
10114     }
10115 
10116     /**
10117      * Dispatch a generic motion event to the view under the first pointer.
10118      * <p>
10119      * Do not call this method directly.
10120      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10121      * </p>
10122      *
10123      * @param event The motion event to be dispatched.
10124      * @return True if the event was handled by the view, false otherwise.
10125      */
dispatchGenericPointerEvent(MotionEvent event)10126     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10127         return false;
10128     }
10129 
10130     /**
10131      * Dispatch a generic motion event to the currently focused view.
10132      * <p>
10133      * Do not call this method directly.
10134      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10135      * </p>
10136      *
10137      * @param event The motion event to be dispatched.
10138      * @return True if the event was handled by the view, false otherwise.
10139      */
dispatchGenericFocusedEvent(MotionEvent event)10140     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10141         return false;
10142     }
10143 
10144     /**
10145      * Dispatch a pointer event.
10146      * <p>
10147      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10148      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10149      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10150      * and should not be expected to handle other pointing device features.
10151      * </p>
10152      *
10153      * @param event The motion event to be dispatched.
10154      * @return True if the event was handled by the view, false otherwise.
10155      * @hide
10156      */
dispatchPointerEvent(MotionEvent event)10157     public final boolean dispatchPointerEvent(MotionEvent event) {
10158         if (event.isTouchEvent()) {
10159             return dispatchTouchEvent(event);
10160         } else {
10161             return dispatchGenericMotionEvent(event);
10162         }
10163     }
10164 
10165     /**
10166      * Called when the window containing this view gains or loses window focus.
10167      * ViewGroups should override to route to their children.
10168      *
10169      * @param hasFocus True if the window containing this view now has focus,
10170      *        false otherwise.
10171      */
dispatchWindowFocusChanged(boolean hasFocus)10172     public void dispatchWindowFocusChanged(boolean hasFocus) {
10173         onWindowFocusChanged(hasFocus);
10174     }
10175 
10176     /**
10177      * Called when the window containing this view gains or loses focus.  Note
10178      * that this is separate from view focus: to receive key events, both
10179      * your view and its window must have focus.  If a window is displayed
10180      * on top of yours that takes input focus, then your own window will lose
10181      * focus but the view focus will remain unchanged.
10182      *
10183      * @param hasWindowFocus True if the window containing this view now has
10184      *        focus, false otherwise.
10185      */
onWindowFocusChanged(boolean hasWindowFocus)10186     public void onWindowFocusChanged(boolean hasWindowFocus) {
10187         InputMethodManager imm = InputMethodManager.peekInstance();
10188         if (!hasWindowFocus) {
10189             if (isPressed()) {
10190                 setPressed(false);
10191             }
10192             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10193                 imm.focusOut(this);
10194             }
10195             removeLongPressCallback();
10196             removeTapCallback();
10197             onFocusLost();
10198         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10199             imm.focusIn(this);
10200         }
10201         refreshDrawableState();
10202     }
10203 
10204     /**
10205      * Returns true if this view is in a window that currently has window focus.
10206      * Note that this is not the same as the view itself having focus.
10207      *
10208      * @return True if this view is in a window that currently has window focus.
10209      */
hasWindowFocus()10210     public boolean hasWindowFocus() {
10211         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10212     }
10213 
10214     /**
10215      * Dispatch a view visibility change down the view hierarchy.
10216      * ViewGroups should override to route to their children.
10217      * @param changedView The view whose visibility changed. Could be 'this' or
10218      * an ancestor view.
10219      * @param visibility The new visibility of changedView: {@link #VISIBLE},
10220      * {@link #INVISIBLE} or {@link #GONE}.
10221      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)10222     protected void dispatchVisibilityChanged(@NonNull View changedView,
10223             @Visibility int visibility) {
10224         onVisibilityChanged(changedView, visibility);
10225     }
10226 
10227     /**
10228      * Called when the visibility of the view or an ancestor of the view has
10229      * changed.
10230      *
10231      * @param changedView The view whose visibility changed. May be
10232      *                    {@code this} or an ancestor view.
10233      * @param visibility The new visibility, one of {@link #VISIBLE},
10234      *                   {@link #INVISIBLE} or {@link #GONE}.
10235      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)10236     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10237     }
10238 
10239     /**
10240      * Dispatch a hint about whether this view is displayed. For instance, when
10241      * a View moves out of the screen, it might receives a display hint indicating
10242      * the view is not displayed. Applications should not <em>rely</em> on this hint
10243      * as there is no guarantee that they will receive one.
10244      *
10245      * @param hint A hint about whether or not this view is displayed:
10246      * {@link #VISIBLE} or {@link #INVISIBLE}.
10247      */
dispatchDisplayHint(@isibility int hint)10248     public void dispatchDisplayHint(@Visibility int hint) {
10249         onDisplayHint(hint);
10250     }
10251 
10252     /**
10253      * Gives this view a hint about whether is displayed or not. For instance, when
10254      * a View moves out of the screen, it might receives a display hint indicating
10255      * the view is not displayed. Applications should not <em>rely</em> on this hint
10256      * as there is no guarantee that they will receive one.
10257      *
10258      * @param hint A hint about whether or not this view is displayed:
10259      * {@link #VISIBLE} or {@link #INVISIBLE}.
10260      */
onDisplayHint(@isibility int hint)10261     protected void onDisplayHint(@Visibility int hint) {
10262     }
10263 
10264     /**
10265      * Dispatch a window visibility change down the view hierarchy.
10266      * ViewGroups should override to route to their children.
10267      *
10268      * @param visibility The new visibility of the window.
10269      *
10270      * @see #onWindowVisibilityChanged(int)
10271      */
dispatchWindowVisibilityChanged(@isibility int visibility)10272     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10273         onWindowVisibilityChanged(visibility);
10274     }
10275 
10276     /**
10277      * Called when the window containing has change its visibility
10278      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10279      * that this tells you whether or not your window is being made visible
10280      * to the window manager; this does <em>not</em> tell you whether or not
10281      * your window is obscured by other windows on the screen, even if it
10282      * is itself visible.
10283      *
10284      * @param visibility The new visibility of the window.
10285      */
onWindowVisibilityChanged(@isibility int visibility)10286     protected void onWindowVisibilityChanged(@Visibility int visibility) {
10287         if (visibility == VISIBLE) {
10288             initialAwakenScrollBars();
10289         }
10290     }
10291 
10292     /**
10293      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10294      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10295      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10296      *
10297      * @param isVisible true if this view's visibility to the user is uninterrupted by its
10298      *                  ancestors or by window visibility
10299      * @return true if this view is visible to the user, not counting clipping or overlapping
10300      */
dispatchVisibilityAggregated(boolean isVisible)10301     @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
10302         final boolean thisVisible = getVisibility() == VISIBLE;
10303         // If we're not visible but something is telling us we are, ignore it.
10304         if (thisVisible || !isVisible) {
10305             onVisibilityAggregated(isVisible);
10306         }
10307         return thisVisible && isVisible;
10308     }
10309 
10310     /**
10311      * Called when the user-visibility of this View is potentially affected by a change
10312      * to this view itself, an ancestor view or the window this view is attached to.
10313      *
10314      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10315      *                  and this view's window is also visible
10316      */
10317     @CallSuper
onVisibilityAggregated(boolean isVisible)10318     public void onVisibilityAggregated(boolean isVisible) {
10319         if (isVisible && mAttachInfo != null) {
10320             initialAwakenScrollBars();
10321         }
10322 
10323         final Drawable dr = mBackground;
10324         if (dr != null && isVisible != dr.isVisible()) {
10325             dr.setVisible(isVisible, false);
10326         }
10327         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10328         if (fg != null && isVisible != fg.isVisible()) {
10329             fg.setVisible(isVisible, false);
10330         }
10331     }
10332 
10333     /**
10334      * Returns the current visibility of the window this view is attached to
10335      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10336      *
10337      * @return Returns the current visibility of the view's window.
10338      */
10339     @Visibility
getWindowVisibility()10340     public int getWindowVisibility() {
10341         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10342     }
10343 
10344     /**
10345      * Retrieve the overall visible display size in which the window this view is
10346      * attached to has been positioned in.  This takes into account screen
10347      * decorations above the window, for both cases where the window itself
10348      * is being position inside of them or the window is being placed under
10349      * then and covered insets are used for the window to position its content
10350      * inside.  In effect, this tells you the available area where content can
10351      * be placed and remain visible to users.
10352      *
10353      * <p>This function requires an IPC back to the window manager to retrieve
10354      * the requested information, so should not be used in performance critical
10355      * code like drawing.
10356      *
10357      * @param outRect Filled in with the visible display frame.  If the view
10358      * is not attached to a window, this is simply the raw display size.
10359      */
getWindowVisibleDisplayFrame(Rect outRect)10360     public void getWindowVisibleDisplayFrame(Rect outRect) {
10361         if (mAttachInfo != null) {
10362             try {
10363                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10364             } catch (RemoteException e) {
10365                 return;
10366             }
10367             // XXX This is really broken, and probably all needs to be done
10368             // in the window manager, and we need to know more about whether
10369             // we want the area behind or in front of the IME.
10370             final Rect insets = mAttachInfo.mVisibleInsets;
10371             outRect.left += insets.left;
10372             outRect.top += insets.top;
10373             outRect.right -= insets.right;
10374             outRect.bottom -= insets.bottom;
10375             return;
10376         }
10377         // The view is not attached to a display so we don't have a context.
10378         // Make a best guess about the display size.
10379         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10380         d.getRectSize(outRect);
10381     }
10382 
10383     /**
10384      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10385      * is currently in without any insets.
10386      *
10387      * @hide
10388      */
getWindowDisplayFrame(Rect outRect)10389     public void getWindowDisplayFrame(Rect outRect) {
10390         if (mAttachInfo != null) {
10391             try {
10392                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10393             } catch (RemoteException e) {
10394                 return;
10395             }
10396             return;
10397         }
10398         // The view is not attached to a display so we don't have a context.
10399         // Make a best guess about the display size.
10400         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10401         d.getRectSize(outRect);
10402     }
10403 
10404     /**
10405      * Dispatch a notification about a resource configuration change down
10406      * the view hierarchy.
10407      * ViewGroups should override to route to their children.
10408      *
10409      * @param newConfig The new resource configuration.
10410      *
10411      * @see #onConfigurationChanged(android.content.res.Configuration)
10412      */
dispatchConfigurationChanged(Configuration newConfig)10413     public void dispatchConfigurationChanged(Configuration newConfig) {
10414         onConfigurationChanged(newConfig);
10415     }
10416 
10417     /**
10418      * Called when the current configuration of the resources being used
10419      * by the application have changed.  You can use this to decide when
10420      * to reload resources that can changed based on orientation and other
10421      * configuration characteristics.  You only need to use this if you are
10422      * not relying on the normal {@link android.app.Activity} mechanism of
10423      * recreating the activity instance upon a configuration change.
10424      *
10425      * @param newConfig The new resource configuration.
10426      */
onConfigurationChanged(Configuration newConfig)10427     protected void onConfigurationChanged(Configuration newConfig) {
10428     }
10429 
10430     /**
10431      * Private function to aggregate all per-view attributes in to the view
10432      * root.
10433      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)10434     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10435         performCollectViewAttributes(attachInfo, visibility);
10436     }
10437 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)10438     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10439         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10440             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10441                 attachInfo.mKeepScreenOn = true;
10442             }
10443             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10444             ListenerInfo li = mListenerInfo;
10445             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10446                 attachInfo.mHasSystemUiListeners = true;
10447             }
10448         }
10449     }
10450 
needGlobalAttributesUpdate(boolean force)10451     void needGlobalAttributesUpdate(boolean force) {
10452         final AttachInfo ai = mAttachInfo;
10453         if (ai != null && !ai.mRecomputeGlobalAttributes) {
10454             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10455                     || ai.mHasSystemUiListeners) {
10456                 ai.mRecomputeGlobalAttributes = true;
10457             }
10458         }
10459     }
10460 
10461     /**
10462      * Returns whether the device is currently in touch mode.  Touch mode is entered
10463      * once the user begins interacting with the device by touch, and affects various
10464      * things like whether focus is always visible to the user.
10465      *
10466      * @return Whether the device is in touch mode.
10467      */
10468     @ViewDebug.ExportedProperty
isInTouchMode()10469     public boolean isInTouchMode() {
10470         if (mAttachInfo != null) {
10471             return mAttachInfo.mInTouchMode;
10472         } else {
10473             return ViewRootImpl.isInTouchMode();
10474         }
10475     }
10476 
10477     /**
10478      * Returns the context the view is running in, through which it can
10479      * access the current theme, resources, etc.
10480      *
10481      * @return The view's Context.
10482      */
10483     @ViewDebug.CapturedViewProperty
getContext()10484     public final Context getContext() {
10485         return mContext;
10486     }
10487 
10488     /**
10489      * Handle a key event before it is processed by any input method
10490      * associated with the view hierarchy.  This can be used to intercept
10491      * key events in special situations before the IME consumes them; a
10492      * typical example would be handling the BACK key to update the application's
10493      * UI instead of allowing the IME to see it and close itself.
10494      *
10495      * @param keyCode The value in event.getKeyCode().
10496      * @param event Description of the key event.
10497      * @return If you handled the event, return true. If you want to allow the
10498      *         event to be handled by the next receiver, return false.
10499      */
onKeyPreIme(int keyCode, KeyEvent event)10500     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10501         return false;
10502     }
10503 
10504     /**
10505      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10506      * KeyEvent.Callback.onKeyDown()}: perform press of the view
10507      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10508      * is released, if the view is enabled and clickable.
10509      * <p>
10510      * Key presses in software keyboards will generally NOT trigger this
10511      * listener, although some may elect to do so in some situations. Do not
10512      * rely on this to catch software key presses.
10513      *
10514      * @param keyCode a key code that represents the button pressed, from
10515      *                {@link android.view.KeyEvent}
10516      * @param event the KeyEvent object that defines the button action
10517      */
onKeyDown(int keyCode, KeyEvent event)10518     public boolean onKeyDown(int keyCode, KeyEvent event) {
10519         if (KeyEvent.isConfirmKey(keyCode)) {
10520             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10521                 return true;
10522             }
10523 
10524             // Long clickable items don't necessarily have to be clickable.
10525             if (((mViewFlags & CLICKABLE) == CLICKABLE
10526                     || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10527                     && (event.getRepeatCount() == 0)) {
10528                 // For the purposes of menu anchoring and drawable hotspots,
10529                 // key events are considered to be at the center of the view.
10530                 final float x = getWidth() / 2f;
10531                 final float y = getHeight() / 2f;
10532                 setPressed(true, x, y);
10533                 checkForLongClick(0, x, y);
10534                 return true;
10535             }
10536         }
10537 
10538         return false;
10539     }
10540 
10541     /**
10542      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10543      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10544      * the event).
10545      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10546      * although some may elect to do so in some situations. Do not rely on this to
10547      * catch software key presses.
10548      */
onKeyLongPress(int keyCode, KeyEvent event)10549     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10550         return false;
10551     }
10552 
10553     /**
10554      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10555      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10556      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10557      * or {@link KeyEvent#KEYCODE_SPACE} is released.
10558      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10559      * although some may elect to do so in some situations. Do not rely on this to
10560      * catch software key presses.
10561      *
10562      * @param keyCode A key code that represents the button pressed, from
10563      *                {@link android.view.KeyEvent}.
10564      * @param event   The KeyEvent object that defines the button action.
10565      */
onKeyUp(int keyCode, KeyEvent event)10566     public boolean onKeyUp(int keyCode, KeyEvent event) {
10567         if (KeyEvent.isConfirmKey(keyCode)) {
10568             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10569                 return true;
10570             }
10571             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10572                 setPressed(false);
10573 
10574                 if (!mHasPerformedLongPress) {
10575                     // This is a tap, so remove the longpress check
10576                     removeLongPressCallback();
10577                     return performClick();
10578                 }
10579             }
10580         }
10581         return false;
10582     }
10583 
10584     /**
10585      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10586      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10587      * the event).
10588      * <p>Key presses in software keyboards will generally NOT trigger this listener,
10589      * although some may elect to do so in some situations. Do not rely on this to
10590      * catch software key presses.
10591      *
10592      * @param keyCode     A key code that represents the button pressed, from
10593      *                    {@link android.view.KeyEvent}.
10594      * @param repeatCount The number of times the action was made.
10595      * @param event       The KeyEvent object that defines the button action.
10596      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)10597     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10598         return false;
10599     }
10600 
10601     /**
10602      * Called on the focused view when a key shortcut event is not handled.
10603      * Override this method to implement local key shortcuts for the View.
10604      * Key shortcuts can also be implemented by setting the
10605      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10606      *
10607      * @param keyCode The value in event.getKeyCode().
10608      * @param event Description of the key event.
10609      * @return If you handled the event, return true. If you want to allow the
10610      *         event to be handled by the next receiver, return false.
10611      */
onKeyShortcut(int keyCode, KeyEvent event)10612     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10613         return false;
10614     }
10615 
10616     /**
10617      * Check whether the called view is a text editor, in which case it
10618      * would make sense to automatically display a soft input window for
10619      * it.  Subclasses should override this if they implement
10620      * {@link #onCreateInputConnection(EditorInfo)} to return true if
10621      * a call on that method would return a non-null InputConnection, and
10622      * they are really a first-class editor that the user would normally
10623      * start typing on when the go into a window containing your view.
10624      *
10625      * <p>The default implementation always returns false.  This does
10626      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10627      * will not be called or the user can not otherwise perform edits on your
10628      * view; it is just a hint to the system that this is not the primary
10629      * purpose of this view.
10630      *
10631      * @return Returns true if this view is a text editor, else false.
10632      */
onCheckIsTextEditor()10633     public boolean onCheckIsTextEditor() {
10634         return false;
10635     }
10636 
10637     /**
10638      * Create a new InputConnection for an InputMethod to interact
10639      * with the view.  The default implementation returns null, since it doesn't
10640      * support input methods.  You can override this to implement such support.
10641      * This is only needed for views that take focus and text input.
10642      *
10643      * <p>When implementing this, you probably also want to implement
10644      * {@link #onCheckIsTextEditor()} to indicate you will return a
10645      * non-null InputConnection.</p>
10646      *
10647      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10648      * object correctly and in its entirety, so that the connected IME can rely
10649      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10650      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10651      * must be filled in with the correct cursor position for IMEs to work correctly
10652      * with your application.</p>
10653      *
10654      * @param outAttrs Fill in with attribute information about the connection.
10655      */
onCreateInputConnection(EditorInfo outAttrs)10656     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10657         return null;
10658     }
10659 
10660     /**
10661      * Called by the {@link android.view.inputmethod.InputMethodManager}
10662      * when a view who is not the current
10663      * input connection target is trying to make a call on the manager.  The
10664      * default implementation returns false; you can override this to return
10665      * true for certain views if you are performing InputConnection proxying
10666      * to them.
10667      * @param view The View that is making the InputMethodManager call.
10668      * @return Return true to allow the call, false to reject.
10669      */
checkInputConnectionProxy(View view)10670     public boolean checkInputConnectionProxy(View view) {
10671         return false;
10672     }
10673 
10674     /**
10675      * Show the context menu for this view. It is not safe to hold on to the
10676      * menu after returning from this method.
10677      *
10678      * You should normally not overload this method. Overload
10679      * {@link #onCreateContextMenu(ContextMenu)} or define an
10680      * {@link OnCreateContextMenuListener} to add items to the context menu.
10681      *
10682      * @param menu The context menu to populate
10683      */
createContextMenu(ContextMenu menu)10684     public void createContextMenu(ContextMenu menu) {
10685         ContextMenuInfo menuInfo = getContextMenuInfo();
10686 
10687         // Sets the current menu info so all items added to menu will have
10688         // my extra info set.
10689         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10690 
10691         onCreateContextMenu(menu);
10692         ListenerInfo li = mListenerInfo;
10693         if (li != null && li.mOnCreateContextMenuListener != null) {
10694             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10695         }
10696 
10697         // Clear the extra information so subsequent items that aren't mine don't
10698         // have my extra info.
10699         ((MenuBuilder)menu).setCurrentMenuInfo(null);
10700 
10701         if (mParent != null) {
10702             mParent.createContextMenu(menu);
10703         }
10704     }
10705 
10706     /**
10707      * Views should implement this if they have extra information to associate
10708      * with the context menu. The return result is supplied as a parameter to
10709      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10710      * callback.
10711      *
10712      * @return Extra information about the item for which the context menu
10713      *         should be shown. This information will vary across different
10714      *         subclasses of View.
10715      */
getContextMenuInfo()10716     protected ContextMenuInfo getContextMenuInfo() {
10717         return null;
10718     }
10719 
10720     /**
10721      * Views should implement this if the view itself is going to add items to
10722      * the context menu.
10723      *
10724      * @param menu the context menu to populate
10725      */
onCreateContextMenu(ContextMenu menu)10726     protected void onCreateContextMenu(ContextMenu menu) {
10727     }
10728 
10729     /**
10730      * Implement this method to handle trackball motion events.  The
10731      * <em>relative</em> movement of the trackball since the last event
10732      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10733      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10734      * that a movement of 1 corresponds to the user pressing one DPAD key (so
10735      * they will often be fractional values, representing the more fine-grained
10736      * movement information available from a trackball).
10737      *
10738      * @param event The motion event.
10739      * @return True if the event was handled, false otherwise.
10740      */
onTrackballEvent(MotionEvent event)10741     public boolean onTrackballEvent(MotionEvent event) {
10742         return false;
10743     }
10744 
10745     /**
10746      * Implement this method to handle generic motion events.
10747      * <p>
10748      * Generic motion events describe joystick movements, mouse hovers, track pad
10749      * touches, scroll wheel movements and other input events.  The
10750      * {@link MotionEvent#getSource() source} of the motion event specifies
10751      * the class of input that was received.  Implementations of this method
10752      * must examine the bits in the source before processing the event.
10753      * The following code example shows how this is done.
10754      * </p><p>
10755      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10756      * are delivered to the view under the pointer.  All other generic motion events are
10757      * delivered to the focused view.
10758      * </p>
10759      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10760      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10761      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10762      *             // process the joystick movement...
10763      *             return true;
10764      *         }
10765      *     }
10766      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10767      *         switch (event.getAction()) {
10768      *             case MotionEvent.ACTION_HOVER_MOVE:
10769      *                 // process the mouse hover movement...
10770      *                 return true;
10771      *             case MotionEvent.ACTION_SCROLL:
10772      *                 // process the scroll wheel movement...
10773      *                 return true;
10774      *         }
10775      *     }
10776      *     return super.onGenericMotionEvent(event);
10777      * }</pre>
10778      *
10779      * @param event The generic motion event being processed.
10780      * @return True if the event was handled, false otherwise.
10781      */
onGenericMotionEvent(MotionEvent event)10782     public boolean onGenericMotionEvent(MotionEvent event) {
10783         return false;
10784     }
10785 
10786     /**
10787      * Implement this method to handle hover events.
10788      * <p>
10789      * This method is called whenever a pointer is hovering into, over, or out of the
10790      * bounds of a view and the view is not currently being touched.
10791      * Hover events are represented as pointer events with action
10792      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10793      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10794      * </p>
10795      * <ul>
10796      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10797      * when the pointer enters the bounds of the view.</li>
10798      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10799      * when the pointer has already entered the bounds of the view and has moved.</li>
10800      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10801      * when the pointer has exited the bounds of the view or when the pointer is
10802      * about to go down due to a button click, tap, or similar user action that
10803      * causes the view to be touched.</li>
10804      * </ul>
10805      * <p>
10806      * The view should implement this method to return true to indicate that it is
10807      * handling the hover event, such as by changing its drawable state.
10808      * </p><p>
10809      * The default implementation calls {@link #setHovered} to update the hovered state
10810      * of the view when a hover enter or hover exit event is received, if the view
10811      * is enabled and is clickable.  The default implementation also sends hover
10812      * accessibility events.
10813      * </p>
10814      *
10815      * @param event The motion event that describes the hover.
10816      * @return True if the view handled the hover event.
10817      *
10818      * @see #isHovered
10819      * @see #setHovered
10820      * @see #onHoverChanged
10821      */
onHoverEvent(MotionEvent event)10822     public boolean onHoverEvent(MotionEvent event) {
10823         // The root view may receive hover (or touch) events that are outside the bounds of
10824         // the window.  This code ensures that we only send accessibility events for
10825         // hovers that are actually within the bounds of the root view.
10826         final int action = event.getActionMasked();
10827         if (!mSendingHoverAccessibilityEvents) {
10828             if ((action == MotionEvent.ACTION_HOVER_ENTER
10829                     || action == MotionEvent.ACTION_HOVER_MOVE)
10830                     && !hasHoveredChild()
10831                     && pointInView(event.getX(), event.getY())) {
10832                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10833                 mSendingHoverAccessibilityEvents = true;
10834             }
10835         } else {
10836             if (action == MotionEvent.ACTION_HOVER_EXIT
10837                     || (action == MotionEvent.ACTION_MOVE
10838                             && !pointInView(event.getX(), event.getY()))) {
10839                 mSendingHoverAccessibilityEvents = false;
10840                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10841             }
10842         }
10843 
10844         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10845                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
10846                 && isOnScrollbar(event.getX(), event.getY())) {
10847             awakenScrollBars();
10848         }
10849         if (isHoverable()) {
10850             switch (action) {
10851                 case MotionEvent.ACTION_HOVER_ENTER:
10852                     setHovered(true);
10853                     break;
10854                 case MotionEvent.ACTION_HOVER_EXIT:
10855                     setHovered(false);
10856                     break;
10857             }
10858 
10859             // Dispatch the event to onGenericMotionEvent before returning true.
10860             // This is to provide compatibility with existing applications that
10861             // handled HOVER_MOVE events in onGenericMotionEvent and that would
10862             // break because of the new default handling for hoverable views
10863             // in onHoverEvent.
10864             // Note that onGenericMotionEvent will be called by default when
10865             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10866             dispatchGenericMotionEventInternal(event);
10867             // The event was already handled by calling setHovered(), so always
10868             // return true.
10869             return true;
10870         }
10871 
10872         return false;
10873     }
10874 
10875     /**
10876      * Returns true if the view should handle {@link #onHoverEvent}
10877      * by calling {@link #setHovered} to change its hovered state.
10878      *
10879      * @return True if the view is hoverable.
10880      */
isHoverable()10881     private boolean isHoverable() {
10882         final int viewFlags = mViewFlags;
10883         if ((viewFlags & ENABLED_MASK) == DISABLED) {
10884             return false;
10885         }
10886 
10887         return (viewFlags & CLICKABLE) == CLICKABLE
10888                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10889                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10890     }
10891 
10892     /**
10893      * Returns true if the view is currently hovered.
10894      *
10895      * @return True if the view is currently hovered.
10896      *
10897      * @see #setHovered
10898      * @see #onHoverChanged
10899      */
10900     @ViewDebug.ExportedProperty
isHovered()10901     public boolean isHovered() {
10902         return (mPrivateFlags & PFLAG_HOVERED) != 0;
10903     }
10904 
10905     /**
10906      * Sets whether the view is currently hovered.
10907      * <p>
10908      * Calling this method also changes the drawable state of the view.  This
10909      * enables the view to react to hover by using different drawable resources
10910      * to change its appearance.
10911      * </p><p>
10912      * The {@link #onHoverChanged} method is called when the hovered state changes.
10913      * </p>
10914      *
10915      * @param hovered True if the view is hovered.
10916      *
10917      * @see #isHovered
10918      * @see #onHoverChanged
10919      */
setHovered(boolean hovered)10920     public void setHovered(boolean hovered) {
10921         if (hovered) {
10922             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10923                 mPrivateFlags |= PFLAG_HOVERED;
10924                 refreshDrawableState();
10925                 onHoverChanged(true);
10926             }
10927         } else {
10928             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10929                 mPrivateFlags &= ~PFLAG_HOVERED;
10930                 refreshDrawableState();
10931                 onHoverChanged(false);
10932             }
10933         }
10934     }
10935 
10936     /**
10937      * Implement this method to handle hover state changes.
10938      * <p>
10939      * This method is called whenever the hover state changes as a result of a
10940      * call to {@link #setHovered}.
10941      * </p>
10942      *
10943      * @param hovered The current hover state, as returned by {@link #isHovered}.
10944      *
10945      * @see #isHovered
10946      * @see #setHovered
10947      */
onHoverChanged(boolean hovered)10948     public void onHoverChanged(boolean hovered) {
10949     }
10950 
10951     /**
10952      * Handles scroll bar dragging by mouse input.
10953      *
10954      * @hide
10955      * @param event The motion event.
10956      *
10957      * @return true if the event was handled as a scroll bar dragging, false otherwise.
10958      */
handleScrollBarDragging(MotionEvent event)10959     protected boolean handleScrollBarDragging(MotionEvent event) {
10960         if (mScrollCache == null) {
10961             return false;
10962         }
10963         final float x = event.getX();
10964         final float y = event.getY();
10965         final int action = event.getAction();
10966         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
10967                 && action != MotionEvent.ACTION_DOWN)
10968                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
10969                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
10970             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
10971             return false;
10972         }
10973 
10974         switch (action) {
10975             case MotionEvent.ACTION_MOVE:
10976                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
10977                     return false;
10978                 }
10979                 if (mScrollCache.mScrollBarDraggingState
10980                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
10981                     final Rect bounds = mScrollCache.mScrollBarBounds;
10982                     getVerticalScrollBarBounds(bounds);
10983                     final int range = computeVerticalScrollRange();
10984                     final int offset = computeVerticalScrollOffset();
10985                     final int extent = computeVerticalScrollExtent();
10986 
10987                     final int thumbLength = ScrollBarUtils.getThumbLength(
10988                             bounds.height(), bounds.width(), extent, range);
10989                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
10990                             bounds.height(), thumbLength, extent, range, offset);
10991 
10992                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
10993                     final float maxThumbOffset = bounds.height() - thumbLength;
10994                     final float newThumbOffset =
10995                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
10996                     final int height = getHeight();
10997                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
10998                             && height > 0 && extent > 0) {
10999                         final int newY = Math.round((range - extent)
11000                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11001                         if (newY != getScrollY()) {
11002                             mScrollCache.mScrollBarDraggingPos = y;
11003                             setScrollY(newY);
11004                         }
11005                     }
11006                     return true;
11007                 }
11008                 if (mScrollCache.mScrollBarDraggingState
11009                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11010                     final Rect bounds = mScrollCache.mScrollBarBounds;
11011                     getHorizontalScrollBarBounds(bounds);
11012                     final int range = computeHorizontalScrollRange();
11013                     final int offset = computeHorizontalScrollOffset();
11014                     final int extent = computeHorizontalScrollExtent();
11015 
11016                     final int thumbLength = ScrollBarUtils.getThumbLength(
11017                             bounds.width(), bounds.height(), extent, range);
11018                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
11019                             bounds.width(), thumbLength, extent, range, offset);
11020 
11021                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
11022                     final float maxThumbOffset = bounds.width() - thumbLength;
11023                     final float newThumbOffset =
11024                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11025                     final int width = getWidth();
11026                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11027                             && width > 0 && extent > 0) {
11028                         final int newX = Math.round((range - extent)
11029                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11030                         if (newX != getScrollX()) {
11031                             mScrollCache.mScrollBarDraggingPos = x;
11032                             setScrollX(newX);
11033                         }
11034                     }
11035                     return true;
11036                 }
11037             case MotionEvent.ACTION_DOWN:
11038                 if (mScrollCache.state == ScrollabilityCache.OFF) {
11039                     return false;
11040                 }
11041                 if (isOnVerticalScrollbarThumb(x, y)) {
11042                     mScrollCache.mScrollBarDraggingState =
11043                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11044                     mScrollCache.mScrollBarDraggingPos = y;
11045                     return true;
11046                 }
11047                 if (isOnHorizontalScrollbarThumb(x, y)) {
11048                     mScrollCache.mScrollBarDraggingState =
11049                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11050                     mScrollCache.mScrollBarDraggingPos = x;
11051                     return true;
11052                 }
11053         }
11054         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11055         return false;
11056     }
11057 
11058     /**
11059      * Implement this method to handle touch screen motion events.
11060      * <p>
11061      * If this method is used to detect click actions, it is recommended that
11062      * the actions be performed by implementing and calling
11063      * {@link #performClick()}. This will ensure consistent system behavior,
11064      * including:
11065      * <ul>
11066      * <li>obeying click sound preferences
11067      * <li>dispatching OnClickListener calls
11068      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11069      * accessibility features are enabled
11070      * </ul>
11071      *
11072      * @param event The motion event.
11073      * @return True if the event was handled, false otherwise.
11074      */
onTouchEvent(MotionEvent event)11075     public boolean onTouchEvent(MotionEvent event) {
11076         final float x = event.getX();
11077         final float y = event.getY();
11078         final int viewFlags = mViewFlags;
11079         final int action = event.getAction();
11080 
11081         if ((viewFlags & ENABLED_MASK) == DISABLED) {
11082             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11083                 setPressed(false);
11084             }
11085             // A disabled view that is clickable still consumes the touch
11086             // events, it just doesn't respond to them.
11087             return (((viewFlags & CLICKABLE) == CLICKABLE
11088                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11089                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11090         }
11091         if (mTouchDelegate != null) {
11092             if (mTouchDelegate.onTouchEvent(event)) {
11093                 return true;
11094             }
11095         }
11096 
11097         if (((viewFlags & CLICKABLE) == CLICKABLE ||
11098                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11099                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11100             switch (action) {
11101                 case MotionEvent.ACTION_UP:
11102                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11103                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11104                         // take focus if we don't have it already and we should in
11105                         // touch mode.
11106                         boolean focusTaken = false;
11107                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11108                             focusTaken = requestFocus();
11109                         }
11110 
11111                         if (prepressed) {
11112                             // The button is being released before we actually
11113                             // showed it as pressed.  Make it show the pressed
11114                             // state now (before scheduling the click) to ensure
11115                             // the user sees it.
11116                             setPressed(true, x, y);
11117                        }
11118 
11119                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11120                             // This is a tap, so remove the longpress check
11121                             removeLongPressCallback();
11122 
11123                             // Only perform take click actions if we were in the pressed state
11124                             if (!focusTaken) {
11125                                 // Use a Runnable and post this rather than calling
11126                                 // performClick directly. This lets other visual state
11127                                 // of the view update before click actions start.
11128                                 if (mPerformClick == null) {
11129                                     mPerformClick = new PerformClick();
11130                                 }
11131                                 if (!post(mPerformClick)) {
11132                                     performClick();
11133                                 }
11134                             }
11135                         }
11136 
11137                         if (mUnsetPressedState == null) {
11138                             mUnsetPressedState = new UnsetPressedState();
11139                         }
11140 
11141                         if (prepressed) {
11142                             postDelayed(mUnsetPressedState,
11143                                     ViewConfiguration.getPressedStateDuration());
11144                         } else if (!post(mUnsetPressedState)) {
11145                             // If the post failed, unpress right now
11146                             mUnsetPressedState.run();
11147                         }
11148 
11149                         removeTapCallback();
11150                     }
11151                     mIgnoreNextUpEvent = false;
11152                     break;
11153 
11154                 case MotionEvent.ACTION_DOWN:
11155                     mHasPerformedLongPress = false;
11156 
11157                     if (performButtonActionOnTouchDown(event)) {
11158                         break;
11159                     }
11160 
11161                     // Walk up the hierarchy to determine if we're inside a scrolling container.
11162                     boolean isInScrollingContainer = isInScrollingContainer();
11163 
11164                     // For views inside a scrolling container, delay the pressed feedback for
11165                     // a short period in case this is a scroll.
11166                     if (isInScrollingContainer) {
11167                         mPrivateFlags |= PFLAG_PREPRESSED;
11168                         if (mPendingCheckForTap == null) {
11169                             mPendingCheckForTap = new CheckForTap();
11170                         }
11171                         mPendingCheckForTap.x = event.getX();
11172                         mPendingCheckForTap.y = event.getY();
11173                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11174                     } else {
11175                         // Not inside a scrolling container, so show the feedback right away
11176                         setPressed(true, x, y);
11177                         checkForLongClick(0, x, y);
11178                     }
11179                     break;
11180 
11181                 case MotionEvent.ACTION_CANCEL:
11182                     setPressed(false);
11183                     removeTapCallback();
11184                     removeLongPressCallback();
11185                     mInContextButtonPress = false;
11186                     mHasPerformedLongPress = false;
11187                     mIgnoreNextUpEvent = false;
11188                     break;
11189 
11190                 case MotionEvent.ACTION_MOVE:
11191                     drawableHotspotChanged(x, y);
11192 
11193                     // Be lenient about moving outside of buttons
11194                     if (!pointInView(x, y, mTouchSlop)) {
11195                         // Outside button
11196                         removeTapCallback();
11197                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11198                             // Remove any future long press/tap checks
11199                             removeLongPressCallback();
11200 
11201                             setPressed(false);
11202                         }
11203                     }
11204                     break;
11205             }
11206 
11207             return true;
11208         }
11209 
11210         return false;
11211     }
11212 
11213     /**
11214      * @hide
11215      */
isInScrollingContainer()11216     public boolean isInScrollingContainer() {
11217         ViewParent p = getParent();
11218         while (p != null && p instanceof ViewGroup) {
11219             if (((ViewGroup) p).shouldDelayChildPressedState()) {
11220                 return true;
11221             }
11222             p = p.getParent();
11223         }
11224         return false;
11225     }
11226 
11227     /**
11228      * Remove the longpress detection timer.
11229      */
removeLongPressCallback()11230     private void removeLongPressCallback() {
11231         if (mPendingCheckForLongPress != null) {
11232           removeCallbacks(mPendingCheckForLongPress);
11233         }
11234     }
11235 
11236     /**
11237      * Remove the pending click action
11238      */
removePerformClickCallback()11239     private void removePerformClickCallback() {
11240         if (mPerformClick != null) {
11241             removeCallbacks(mPerformClick);
11242         }
11243     }
11244 
11245     /**
11246      * Remove the prepress detection timer.
11247      */
removeUnsetPressCallback()11248     private void removeUnsetPressCallback() {
11249         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11250             setPressed(false);
11251             removeCallbacks(mUnsetPressedState);
11252         }
11253     }
11254 
11255     /**
11256      * Remove the tap detection timer.
11257      */
removeTapCallback()11258     private void removeTapCallback() {
11259         if (mPendingCheckForTap != null) {
11260             mPrivateFlags &= ~PFLAG_PREPRESSED;
11261             removeCallbacks(mPendingCheckForTap);
11262         }
11263     }
11264 
11265     /**
11266      * Cancels a pending long press.  Your subclass can use this if you
11267      * want the context menu to come up if the user presses and holds
11268      * at the same place, but you don't want it to come up if they press
11269      * and then move around enough to cause scrolling.
11270      */
cancelLongPress()11271     public void cancelLongPress() {
11272         removeLongPressCallback();
11273 
11274         /*
11275          * The prepressed state handled by the tap callback is a display
11276          * construct, but the tap callback will post a long press callback
11277          * less its own timeout. Remove it here.
11278          */
11279         removeTapCallback();
11280     }
11281 
11282     /**
11283      * Remove the pending callback for sending a
11284      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11285      */
removeSendViewScrolledAccessibilityEventCallback()11286     private void removeSendViewScrolledAccessibilityEventCallback() {
11287         if (mSendViewScrolledAccessibilityEvent != null) {
11288             removeCallbacks(mSendViewScrolledAccessibilityEvent);
11289             mSendViewScrolledAccessibilityEvent.mIsPending = false;
11290         }
11291     }
11292 
11293     /**
11294      * Sets the TouchDelegate for this View.
11295      */
setTouchDelegate(TouchDelegate delegate)11296     public void setTouchDelegate(TouchDelegate delegate) {
11297         mTouchDelegate = delegate;
11298     }
11299 
11300     /**
11301      * Gets the TouchDelegate for this View.
11302      */
getTouchDelegate()11303     public TouchDelegate getTouchDelegate() {
11304         return mTouchDelegate;
11305     }
11306 
11307     /**
11308      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11309      *
11310      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11311      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11312      * available. This method should only be called for touch events.
11313      *
11314      * <p class="note">This api is not intended for most applications. Buffered dispatch
11315      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11316      * streams will not improve your input latency. Side effects include: increased latency,
11317      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11318      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11319      * you.</p>
11320      */
requestUnbufferedDispatch(MotionEvent event)11321     public final void requestUnbufferedDispatch(MotionEvent event) {
11322         final int action = event.getAction();
11323         if (mAttachInfo == null
11324                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11325                 || !event.isTouchEvent()) {
11326             return;
11327         }
11328         mAttachInfo.mUnbufferedDispatchRequested = true;
11329     }
11330 
11331     /**
11332      * Set flags controlling behavior of this view.
11333      *
11334      * @param flags Constant indicating the value which should be set
11335      * @param mask Constant indicating the bit range that should be changed
11336      */
setFlags(int flags, int mask)11337     void setFlags(int flags, int mask) {
11338         final boolean accessibilityEnabled =
11339                 AccessibilityManager.getInstance(mContext).isEnabled();
11340         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11341 
11342         int old = mViewFlags;
11343         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11344 
11345         int changed = mViewFlags ^ old;
11346         if (changed == 0) {
11347             return;
11348         }
11349         int privateFlags = mPrivateFlags;
11350 
11351         /* Check if the FOCUSABLE bit has changed */
11352         if (((changed & FOCUSABLE_MASK) != 0) &&
11353                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11354             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11355                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11356                 /* Give up focus if we are no longer focusable */
11357                 clearFocus();
11358             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11359                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11360                 /*
11361                  * Tell the view system that we are now available to take focus
11362                  * if no one else already has it.
11363                  */
11364                 if (mParent != null) mParent.focusableViewAvailable(this);
11365             }
11366         }
11367 
11368         final int newVisibility = flags & VISIBILITY_MASK;
11369         if (newVisibility == VISIBLE) {
11370             if ((changed & VISIBILITY_MASK) != 0) {
11371                 /*
11372                  * If this view is becoming visible, invalidate it in case it changed while
11373                  * it was not visible. Marking it drawn ensures that the invalidation will
11374                  * go through.
11375                  */
11376                 mPrivateFlags |= PFLAG_DRAWN;
11377                 invalidate(true);
11378 
11379                 needGlobalAttributesUpdate(true);
11380 
11381                 // a view becoming visible is worth notifying the parent
11382                 // about in case nothing has focus.  even if this specific view
11383                 // isn't focusable, it may contain something that is, so let
11384                 // the root view try to give this focus if nothing else does.
11385                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11386                     mParent.focusableViewAvailable(this);
11387                 }
11388             }
11389         }
11390 
11391         /* Check if the GONE bit has changed */
11392         if ((changed & GONE) != 0) {
11393             needGlobalAttributesUpdate(false);
11394             requestLayout();
11395 
11396             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11397                 if (hasFocus()) clearFocus();
11398                 clearAccessibilityFocus();
11399                 destroyDrawingCache();
11400                 if (mParent instanceof View) {
11401                     // GONE views noop invalidation, so invalidate the parent
11402                     ((View) mParent).invalidate(true);
11403                 }
11404                 // Mark the view drawn to ensure that it gets invalidated properly the next
11405                 // time it is visible and gets invalidated
11406                 mPrivateFlags |= PFLAG_DRAWN;
11407             }
11408             if (mAttachInfo != null) {
11409                 mAttachInfo.mViewVisibilityChanged = true;
11410             }
11411         }
11412 
11413         /* Check if the VISIBLE bit has changed */
11414         if ((changed & INVISIBLE) != 0) {
11415             needGlobalAttributesUpdate(false);
11416             /*
11417              * If this view is becoming invisible, set the DRAWN flag so that
11418              * the next invalidate() will not be skipped.
11419              */
11420             mPrivateFlags |= PFLAG_DRAWN;
11421 
11422             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11423                 // root view becoming invisible shouldn't clear focus and accessibility focus
11424                 if (getRootView() != this) {
11425                     if (hasFocus()) clearFocus();
11426                     clearAccessibilityFocus();
11427                 }
11428             }
11429             if (mAttachInfo != null) {
11430                 mAttachInfo.mViewVisibilityChanged = true;
11431             }
11432         }
11433 
11434         if ((changed & VISIBILITY_MASK) != 0) {
11435             // If the view is invisible, cleanup its display list to free up resources
11436             if (newVisibility != VISIBLE && mAttachInfo != null) {
11437                 cleanupDraw();
11438             }
11439 
11440             if (mParent instanceof ViewGroup) {
11441                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
11442                         (changed & VISIBILITY_MASK), newVisibility);
11443                 ((View) mParent).invalidate(true);
11444             } else if (mParent != null) {
11445                 mParent.invalidateChild(this, null);
11446             }
11447 
11448             if (mAttachInfo != null) {
11449                 dispatchVisibilityChanged(this, newVisibility);
11450 
11451                 // Aggregated visibility changes are dispatched to attached views
11452                 // in visible windows where the parent is currently shown/drawn
11453                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11454                 // discounting clipping or overlapping. This makes it a good place
11455                 // to change animation states.
11456                 if (mParent != null && getWindowVisibility() == VISIBLE &&
11457                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11458                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
11459                 }
11460                 notifySubtreeAccessibilityStateChangedIfNeeded();
11461             }
11462         }
11463 
11464         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11465             destroyDrawingCache();
11466         }
11467 
11468         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11469             destroyDrawingCache();
11470             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11471             invalidateParentCaches();
11472         }
11473 
11474         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11475             destroyDrawingCache();
11476             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11477         }
11478 
11479         if ((changed & DRAW_MASK) != 0) {
11480             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11481                 if (mBackground != null
11482                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11483                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11484                 } else {
11485                     mPrivateFlags |= PFLAG_SKIP_DRAW;
11486                 }
11487             } else {
11488                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11489             }
11490             requestLayout();
11491             invalidate(true);
11492         }
11493 
11494         if ((changed & KEEP_SCREEN_ON) != 0) {
11495             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11496                 mParent.recomputeViewAttributes(this);
11497             }
11498         }
11499 
11500         if (accessibilityEnabled) {
11501             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11502                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11503                     || (changed & CONTEXT_CLICKABLE) != 0) {
11504                 if (oldIncludeForAccessibility != includeForAccessibility()) {
11505                     notifySubtreeAccessibilityStateChangedIfNeeded();
11506                 } else {
11507                     notifyViewAccessibilityStateChangedIfNeeded(
11508                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11509                 }
11510             } else if ((changed & ENABLED_MASK) != 0) {
11511                 notifyViewAccessibilityStateChangedIfNeeded(
11512                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11513             }
11514         }
11515     }
11516 
11517     /**
11518      * Change the view's z order in the tree, so it's on top of other sibling
11519      * views. This ordering change may affect layout, if the parent container
11520      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11521      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11522      * method should be followed by calls to {@link #requestLayout()} and
11523      * {@link View#invalidate()} on the view's parent to force the parent to redraw
11524      * with the new child ordering.
11525      *
11526      * @see ViewGroup#bringChildToFront(View)
11527      */
bringToFront()11528     public void bringToFront() {
11529         if (mParent != null) {
11530             mParent.bringChildToFront(this);
11531         }
11532     }
11533 
11534     /**
11535      * This is called in response to an internal scroll in this view (i.e., the
11536      * view scrolled its own contents). This is typically as a result of
11537      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11538      * called.
11539      *
11540      * @param l Current horizontal scroll origin.
11541      * @param t Current vertical scroll origin.
11542      * @param oldl Previous horizontal scroll origin.
11543      * @param oldt Previous vertical scroll origin.
11544      */
onScrollChanged(int l, int t, int oldl, int oldt)11545     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11546         notifySubtreeAccessibilityStateChangedIfNeeded();
11547 
11548         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11549             postSendViewScrolledAccessibilityEventCallback();
11550         }
11551 
11552         mBackgroundSizeChanged = true;
11553         if (mForegroundInfo != null) {
11554             mForegroundInfo.mBoundsChanged = true;
11555         }
11556 
11557         final AttachInfo ai = mAttachInfo;
11558         if (ai != null) {
11559             ai.mViewScrollChanged = true;
11560         }
11561 
11562         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11563             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11564         }
11565     }
11566 
11567     /**
11568      * Interface definition for a callback to be invoked when the scroll
11569      * X or Y positions of a view change.
11570      * <p>
11571      * <b>Note:</b> Some views handle scrolling independently from View and may
11572      * have their own separate listeners for scroll-type events. For example,
11573      * {@link android.widget.ListView ListView} allows clients to register an
11574      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11575      * to listen for changes in list scroll position.
11576      *
11577      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11578      */
11579     public interface OnScrollChangeListener {
11580         /**
11581          * Called when the scroll position of a view changes.
11582          *
11583          * @param v The view whose scroll position has changed.
11584          * @param scrollX Current horizontal scroll origin.
11585          * @param scrollY Current vertical scroll origin.
11586          * @param oldScrollX Previous horizontal scroll origin.
11587          * @param oldScrollY Previous vertical scroll origin.
11588          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)11589         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11590     }
11591 
11592     /**
11593      * Interface definition for a callback to be invoked when the layout bounds of a view
11594      * changes due to layout processing.
11595      */
11596     public interface OnLayoutChangeListener {
11597         /**
11598          * Called when the layout bounds of a view changes due to layout processing.
11599          *
11600          * @param v The view whose bounds have changed.
11601          * @param left The new value of the view's left property.
11602          * @param top The new value of the view's top property.
11603          * @param right The new value of the view's right property.
11604          * @param bottom The new value of the view's bottom property.
11605          * @param oldLeft The previous value of the view's left property.
11606          * @param oldTop The previous value of the view's top property.
11607          * @param oldRight The previous value of the view's right property.
11608          * @param oldBottom The previous value of the view's bottom property.
11609          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)11610         void onLayoutChange(View v, int left, int top, int right, int bottom,
11611             int oldLeft, int oldTop, int oldRight, int oldBottom);
11612     }
11613 
11614     /**
11615      * This is called during layout when the size of this view has changed. If
11616      * you were just added to the view hierarchy, you're called with the old
11617      * values of 0.
11618      *
11619      * @param w Current width of this view.
11620      * @param h Current height of this view.
11621      * @param oldw Old width of this view.
11622      * @param oldh Old height of this view.
11623      */
onSizeChanged(int w, int h, int oldw, int oldh)11624     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11625     }
11626 
11627     /**
11628      * Called by draw to draw the child views. This may be overridden
11629      * by derived classes to gain control just before its children are drawn
11630      * (but after its own view has been drawn).
11631      * @param canvas the canvas on which to draw the view
11632      */
dispatchDraw(Canvas canvas)11633     protected void dispatchDraw(Canvas canvas) {
11634 
11635     }
11636 
11637     /**
11638      * Gets the parent of this view. Note that the parent is a
11639      * ViewParent and not necessarily a View.
11640      *
11641      * @return Parent of this view.
11642      */
getParent()11643     public final ViewParent getParent() {
11644         return mParent;
11645     }
11646 
11647     /**
11648      * Set the horizontal scrolled position of your view. This will cause a call to
11649      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11650      * invalidated.
11651      * @param value the x position to scroll to
11652      */
setScrollX(int value)11653     public void setScrollX(int value) {
11654         scrollTo(value, mScrollY);
11655     }
11656 
11657     /**
11658      * Set the vertical scrolled position of your view. This will cause a call to
11659      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11660      * invalidated.
11661      * @param value the y position to scroll to
11662      */
setScrollY(int value)11663     public void setScrollY(int value) {
11664         scrollTo(mScrollX, value);
11665     }
11666 
11667     /**
11668      * Return the scrolled left position of this view. This is the left edge of
11669      * the displayed part of your view. You do not need to draw any pixels
11670      * farther left, since those are outside of the frame of your view on
11671      * screen.
11672      *
11673      * @return The left edge of the displayed part of your view, in pixels.
11674      */
getScrollX()11675     public final int getScrollX() {
11676         return mScrollX;
11677     }
11678 
11679     /**
11680      * Return the scrolled top position of this view. This is the top edge of
11681      * the displayed part of your view. You do not need to draw any pixels above
11682      * it, since those are outside of the frame of your view on screen.
11683      *
11684      * @return The top edge of the displayed part of your view, in pixels.
11685      */
getScrollY()11686     public final int getScrollY() {
11687         return mScrollY;
11688     }
11689 
11690     /**
11691      * Return the width of the your view.
11692      *
11693      * @return The width of your view, in pixels.
11694      */
11695     @ViewDebug.ExportedProperty(category = "layout")
getWidth()11696     public final int getWidth() {
11697         return mRight - mLeft;
11698     }
11699 
11700     /**
11701      * Return the height of your view.
11702      *
11703      * @return The height of your view, in pixels.
11704      */
11705     @ViewDebug.ExportedProperty(category = "layout")
getHeight()11706     public final int getHeight() {
11707         return mBottom - mTop;
11708     }
11709 
11710     /**
11711      * Return the visible drawing bounds of your view. Fills in the output
11712      * rectangle with the values from getScrollX(), getScrollY(),
11713      * getWidth(), and getHeight(). These bounds do not account for any
11714      * transformation properties currently set on the view, such as
11715      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11716      *
11717      * @param outRect The (scrolled) drawing bounds of the view.
11718      */
getDrawingRect(Rect outRect)11719     public void getDrawingRect(Rect outRect) {
11720         outRect.left = mScrollX;
11721         outRect.top = mScrollY;
11722         outRect.right = mScrollX + (mRight - mLeft);
11723         outRect.bottom = mScrollY + (mBottom - mTop);
11724     }
11725 
11726     /**
11727      * Like {@link #getMeasuredWidthAndState()}, but only returns the
11728      * raw width component (that is the result is masked by
11729      * {@link #MEASURED_SIZE_MASK}).
11730      *
11731      * @return The raw measured width of this view.
11732      */
getMeasuredWidth()11733     public final int getMeasuredWidth() {
11734         return mMeasuredWidth & MEASURED_SIZE_MASK;
11735     }
11736 
11737     /**
11738      * Return the full width measurement information for this view as computed
11739      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11740      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11741      * This should be used during measurement and layout calculations only. Use
11742      * {@link #getWidth()} to see how wide a view is after layout.
11743      *
11744      * @return The measured width of this view as a bit mask.
11745      */
11746     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11747             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11748                     name = "MEASURED_STATE_TOO_SMALL"),
11749     })
getMeasuredWidthAndState()11750     public final int getMeasuredWidthAndState() {
11751         return mMeasuredWidth;
11752     }
11753 
11754     /**
11755      * Like {@link #getMeasuredHeightAndState()}, but only returns the
11756      * raw width component (that is the result is masked by
11757      * {@link #MEASURED_SIZE_MASK}).
11758      *
11759      * @return The raw measured height of this view.
11760      */
getMeasuredHeight()11761     public final int getMeasuredHeight() {
11762         return mMeasuredHeight & MEASURED_SIZE_MASK;
11763     }
11764 
11765     /**
11766      * Return the full height measurement information for this view as computed
11767      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11768      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11769      * This should be used during measurement and layout calculations only. Use
11770      * {@link #getHeight()} to see how wide a view is after layout.
11771      *
11772      * @return The measured width of this view as a bit mask.
11773      */
11774     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11775             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11776                     name = "MEASURED_STATE_TOO_SMALL"),
11777     })
getMeasuredHeightAndState()11778     public final int getMeasuredHeightAndState() {
11779         return mMeasuredHeight;
11780     }
11781 
11782     /**
11783      * Return only the state bits of {@link #getMeasuredWidthAndState()}
11784      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11785      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11786      * and the height component is at the shifted bits
11787      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11788      */
getMeasuredState()11789     public final int getMeasuredState() {
11790         return (mMeasuredWidth&MEASURED_STATE_MASK)
11791                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11792                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11793     }
11794 
11795     /**
11796      * The transform matrix of this view, which is calculated based on the current
11797      * rotation, scale, and pivot properties.
11798      *
11799      * @see #getRotation()
11800      * @see #getScaleX()
11801      * @see #getScaleY()
11802      * @see #getPivotX()
11803      * @see #getPivotY()
11804      * @return The current transform matrix for the view
11805      */
getMatrix()11806     public Matrix getMatrix() {
11807         ensureTransformationInfo();
11808         final Matrix matrix = mTransformationInfo.mMatrix;
11809         mRenderNode.getMatrix(matrix);
11810         return matrix;
11811     }
11812 
11813     /**
11814      * Returns true if the transform matrix is the identity matrix.
11815      * Recomputes the matrix if necessary.
11816      *
11817      * @return True if the transform matrix is the identity matrix, false otherwise.
11818      */
hasIdentityMatrix()11819     final boolean hasIdentityMatrix() {
11820         return mRenderNode.hasIdentityMatrix();
11821     }
11822 
ensureTransformationInfo()11823     void ensureTransformationInfo() {
11824         if (mTransformationInfo == null) {
11825             mTransformationInfo = new TransformationInfo();
11826         }
11827     }
11828 
11829     /**
11830      * Utility method to retrieve the inverse of the current mMatrix property.
11831      * We cache the matrix to avoid recalculating it when transform properties
11832      * have not changed.
11833      *
11834      * @return The inverse of the current matrix of this view.
11835      * @hide
11836      */
getInverseMatrix()11837     public final Matrix getInverseMatrix() {
11838         ensureTransformationInfo();
11839         if (mTransformationInfo.mInverseMatrix == null) {
11840             mTransformationInfo.mInverseMatrix = new Matrix();
11841         }
11842         final Matrix matrix = mTransformationInfo.mInverseMatrix;
11843         mRenderNode.getInverseMatrix(matrix);
11844         return matrix;
11845     }
11846 
11847     /**
11848      * Gets the distance along the Z axis from the camera to this view.
11849      *
11850      * @see #setCameraDistance(float)
11851      *
11852      * @return The distance along the Z axis.
11853      */
getCameraDistance()11854     public float getCameraDistance() {
11855         final float dpi = mResources.getDisplayMetrics().densityDpi;
11856         return -(mRenderNode.getCameraDistance() * dpi);
11857     }
11858 
11859     /**
11860      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11861      * views are drawn) from the camera to this view. The camera's distance
11862      * affects 3D transformations, for instance rotations around the X and Y
11863      * axis. If the rotationX or rotationY properties are changed and this view is
11864      * large (more than half the size of the screen), it is recommended to always
11865      * use a camera distance that's greater than the height (X axis rotation) or
11866      * the width (Y axis rotation) of this view.</p>
11867      *
11868      * <p>The distance of the camera from the view plane can have an affect on the
11869      * perspective distortion of the view when it is rotated around the x or y axis.
11870      * For example, a large distance will result in a large viewing angle, and there
11871      * will not be much perspective distortion of the view as it rotates. A short
11872      * distance may cause much more perspective distortion upon rotation, and can
11873      * also result in some drawing artifacts if the rotated view ends up partially
11874      * behind the camera (which is why the recommendation is to use a distance at
11875      * least as far as the size of the view, if the view is to be rotated.)</p>
11876      *
11877      * <p>The distance is expressed in "depth pixels." The default distance depends
11878      * on the screen density. For instance, on a medium density display, the
11879      * default distance is 1280. On a high density display, the default distance
11880      * is 1920.</p>
11881      *
11882      * <p>If you want to specify a distance that leads to visually consistent
11883      * results across various densities, use the following formula:</p>
11884      * <pre>
11885      * float scale = context.getResources().getDisplayMetrics().density;
11886      * view.setCameraDistance(distance * scale);
11887      * </pre>
11888      *
11889      * <p>The density scale factor of a high density display is 1.5,
11890      * and 1920 = 1280 * 1.5.</p>
11891      *
11892      * @param distance The distance in "depth pixels", if negative the opposite
11893      *        value is used
11894      *
11895      * @see #setRotationX(float)
11896      * @see #setRotationY(float)
11897      */
setCameraDistance(float distance)11898     public void setCameraDistance(float distance) {
11899         final float dpi = mResources.getDisplayMetrics().densityDpi;
11900 
11901         invalidateViewProperty(true, false);
11902         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11903         invalidateViewProperty(false, false);
11904 
11905         invalidateParentIfNeededAndWasQuickRejected();
11906     }
11907 
11908     /**
11909      * The degrees that the view is rotated around the pivot point.
11910      *
11911      * @see #setRotation(float)
11912      * @see #getPivotX()
11913      * @see #getPivotY()
11914      *
11915      * @return The degrees of rotation.
11916      */
11917     @ViewDebug.ExportedProperty(category = "drawing")
getRotation()11918     public float getRotation() {
11919         return mRenderNode.getRotation();
11920     }
11921 
11922     /**
11923      * Sets the degrees that the view is rotated around the pivot point. Increasing values
11924      * result in clockwise rotation.
11925      *
11926      * @param rotation The degrees of rotation.
11927      *
11928      * @see #getRotation()
11929      * @see #getPivotX()
11930      * @see #getPivotY()
11931      * @see #setRotationX(float)
11932      * @see #setRotationY(float)
11933      *
11934      * @attr ref android.R.styleable#View_rotation
11935      */
setRotation(float rotation)11936     public void setRotation(float rotation) {
11937         if (rotation != getRotation()) {
11938             // Double-invalidation is necessary to capture view's old and new areas
11939             invalidateViewProperty(true, false);
11940             mRenderNode.setRotation(rotation);
11941             invalidateViewProperty(false, true);
11942 
11943             invalidateParentIfNeededAndWasQuickRejected();
11944             notifySubtreeAccessibilityStateChangedIfNeeded();
11945         }
11946     }
11947 
11948     /**
11949      * The degrees that the view is rotated around the vertical axis through the pivot point.
11950      *
11951      * @see #getPivotX()
11952      * @see #getPivotY()
11953      * @see #setRotationY(float)
11954      *
11955      * @return The degrees of Y rotation.
11956      */
11957     @ViewDebug.ExportedProperty(category = "drawing")
getRotationY()11958     public float getRotationY() {
11959         return mRenderNode.getRotationY();
11960     }
11961 
11962     /**
11963      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11964      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11965      * down the y axis.
11966      *
11967      * When rotating large views, it is recommended to adjust the camera distance
11968      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11969      *
11970      * @param rotationY The degrees of Y rotation.
11971      *
11972      * @see #getRotationY()
11973      * @see #getPivotX()
11974      * @see #getPivotY()
11975      * @see #setRotation(float)
11976      * @see #setRotationX(float)
11977      * @see #setCameraDistance(float)
11978      *
11979      * @attr ref android.R.styleable#View_rotationY
11980      */
setRotationY(float rotationY)11981     public void setRotationY(float rotationY) {
11982         if (rotationY != getRotationY()) {
11983             invalidateViewProperty(true, false);
11984             mRenderNode.setRotationY(rotationY);
11985             invalidateViewProperty(false, true);
11986 
11987             invalidateParentIfNeededAndWasQuickRejected();
11988             notifySubtreeAccessibilityStateChangedIfNeeded();
11989         }
11990     }
11991 
11992     /**
11993      * The degrees that the view is rotated around the horizontal axis through the pivot point.
11994      *
11995      * @see #getPivotX()
11996      * @see #getPivotY()
11997      * @see #setRotationX(float)
11998      *
11999      * @return The degrees of X rotation.
12000      */
12001     @ViewDebug.ExportedProperty(category = "drawing")
getRotationX()12002     public float getRotationX() {
12003         return mRenderNode.getRotationX();
12004     }
12005 
12006     /**
12007      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12008      * Increasing values result in clockwise rotation from the viewpoint of looking down the
12009      * x axis.
12010      *
12011      * When rotating large views, it is recommended to adjust the camera distance
12012      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12013      *
12014      * @param rotationX The degrees of X rotation.
12015      *
12016      * @see #getRotationX()
12017      * @see #getPivotX()
12018      * @see #getPivotY()
12019      * @see #setRotation(float)
12020      * @see #setRotationY(float)
12021      * @see #setCameraDistance(float)
12022      *
12023      * @attr ref android.R.styleable#View_rotationX
12024      */
setRotationX(float rotationX)12025     public void setRotationX(float rotationX) {
12026         if (rotationX != getRotationX()) {
12027             invalidateViewProperty(true, false);
12028             mRenderNode.setRotationX(rotationX);
12029             invalidateViewProperty(false, true);
12030 
12031             invalidateParentIfNeededAndWasQuickRejected();
12032             notifySubtreeAccessibilityStateChangedIfNeeded();
12033         }
12034     }
12035 
12036     /**
12037      * The amount that the view is scaled in x around the pivot point, as a proportion of
12038      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12039      *
12040      * <p>By default, this is 1.0f.
12041      *
12042      * @see #getPivotX()
12043      * @see #getPivotY()
12044      * @return The scaling factor.
12045      */
12046     @ViewDebug.ExportedProperty(category = "drawing")
getScaleX()12047     public float getScaleX() {
12048         return mRenderNode.getScaleX();
12049     }
12050 
12051     /**
12052      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12053      * the view's unscaled width. A value of 1 means that no scaling is applied.
12054      *
12055      * @param scaleX The scaling factor.
12056      * @see #getPivotX()
12057      * @see #getPivotY()
12058      *
12059      * @attr ref android.R.styleable#View_scaleX
12060      */
setScaleX(float scaleX)12061     public void setScaleX(float scaleX) {
12062         if (scaleX != getScaleX()) {
12063             invalidateViewProperty(true, false);
12064             mRenderNode.setScaleX(scaleX);
12065             invalidateViewProperty(false, true);
12066 
12067             invalidateParentIfNeededAndWasQuickRejected();
12068             notifySubtreeAccessibilityStateChangedIfNeeded();
12069         }
12070     }
12071 
12072     /**
12073      * The amount that the view is scaled in y around the pivot point, as a proportion of
12074      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12075      *
12076      * <p>By default, this is 1.0f.
12077      *
12078      * @see #getPivotX()
12079      * @see #getPivotY()
12080      * @return The scaling factor.
12081      */
12082     @ViewDebug.ExportedProperty(category = "drawing")
getScaleY()12083     public float getScaleY() {
12084         return mRenderNode.getScaleY();
12085     }
12086 
12087     /**
12088      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12089      * the view's unscaled width. A value of 1 means that no scaling is applied.
12090      *
12091      * @param scaleY The scaling factor.
12092      * @see #getPivotX()
12093      * @see #getPivotY()
12094      *
12095      * @attr ref android.R.styleable#View_scaleY
12096      */
setScaleY(float scaleY)12097     public void setScaleY(float scaleY) {
12098         if (scaleY != getScaleY()) {
12099             invalidateViewProperty(true, false);
12100             mRenderNode.setScaleY(scaleY);
12101             invalidateViewProperty(false, true);
12102 
12103             invalidateParentIfNeededAndWasQuickRejected();
12104             notifySubtreeAccessibilityStateChangedIfNeeded();
12105         }
12106     }
12107 
12108     /**
12109      * The x location of the point around which the view is {@link #setRotation(float) rotated}
12110      * and {@link #setScaleX(float) scaled}.
12111      *
12112      * @see #getRotation()
12113      * @see #getScaleX()
12114      * @see #getScaleY()
12115      * @see #getPivotY()
12116      * @return The x location of the pivot point.
12117      *
12118      * @attr ref android.R.styleable#View_transformPivotX
12119      */
12120     @ViewDebug.ExportedProperty(category = "drawing")
getPivotX()12121     public float getPivotX() {
12122         return mRenderNode.getPivotX();
12123     }
12124 
12125     /**
12126      * Sets the x location of the point around which the view is
12127      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12128      * By default, the pivot point is centered on the object.
12129      * Setting this property disables this behavior and causes the view to use only the
12130      * explicitly set pivotX and pivotY values.
12131      *
12132      * @param pivotX The x location of the pivot point.
12133      * @see #getRotation()
12134      * @see #getScaleX()
12135      * @see #getScaleY()
12136      * @see #getPivotY()
12137      *
12138      * @attr ref android.R.styleable#View_transformPivotX
12139      */
setPivotX(float pivotX)12140     public void setPivotX(float pivotX) {
12141         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12142             invalidateViewProperty(true, false);
12143             mRenderNode.setPivotX(pivotX);
12144             invalidateViewProperty(false, true);
12145 
12146             invalidateParentIfNeededAndWasQuickRejected();
12147         }
12148     }
12149 
12150     /**
12151      * The y location of the point around which the view is {@link #setRotation(float) rotated}
12152      * and {@link #setScaleY(float) scaled}.
12153      *
12154      * @see #getRotation()
12155      * @see #getScaleX()
12156      * @see #getScaleY()
12157      * @see #getPivotY()
12158      * @return The y location of the pivot point.
12159      *
12160      * @attr ref android.R.styleable#View_transformPivotY
12161      */
12162     @ViewDebug.ExportedProperty(category = "drawing")
getPivotY()12163     public float getPivotY() {
12164         return mRenderNode.getPivotY();
12165     }
12166 
12167     /**
12168      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12169      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12170      * Setting this property disables this behavior and causes the view to use only the
12171      * explicitly set pivotX and pivotY values.
12172      *
12173      * @param pivotY The y location of the pivot point.
12174      * @see #getRotation()
12175      * @see #getScaleX()
12176      * @see #getScaleY()
12177      * @see #getPivotY()
12178      *
12179      * @attr ref android.R.styleable#View_transformPivotY
12180      */
setPivotY(float pivotY)12181     public void setPivotY(float pivotY) {
12182         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12183             invalidateViewProperty(true, false);
12184             mRenderNode.setPivotY(pivotY);
12185             invalidateViewProperty(false, true);
12186 
12187             invalidateParentIfNeededAndWasQuickRejected();
12188         }
12189     }
12190 
12191     /**
12192      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12193      * completely transparent and 1 means the view is completely opaque.
12194      *
12195      * <p>By default this is 1.0f.
12196      * @return The opacity of the view.
12197      */
12198     @ViewDebug.ExportedProperty(category = "drawing")
getAlpha()12199     public float getAlpha() {
12200         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12201     }
12202 
12203     /**
12204      * Sets the behavior for overlapping rendering for this view (see {@link
12205      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12206      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12207      * providing the value which is then used internally. That is, when {@link
12208      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12209      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12210      * instead.
12211      *
12212      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12213      * instead of that returned by {@link #hasOverlappingRendering()}.
12214      *
12215      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12216      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)12217     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12218         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12219         if (hasOverlappingRendering) {
12220             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12221         } else {
12222             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12223         }
12224     }
12225 
12226     /**
12227      * Returns the value for overlapping rendering that is used internally. This is either
12228      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12229      * the return value of {@link #hasOverlappingRendering()}, otherwise.
12230      *
12231      * @return The value for overlapping rendering being used internally.
12232      */
getHasOverlappingRendering()12233     public final boolean getHasOverlappingRendering() {
12234         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12235                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12236                 hasOverlappingRendering();
12237     }
12238 
12239     /**
12240      * Returns whether this View has content which overlaps.
12241      *
12242      * <p>This function, intended to be overridden by specific View types, is an optimization when
12243      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12244      * an offscreen buffer and then composited into place, which can be expensive. If the view has
12245      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12246      * directly. An example of overlapping rendering is a TextView with a background image, such as
12247      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12248      * ImageView with only the foreground image. The default implementation returns true; subclasses
12249      * should override if they have cases which can be optimized.</p>
12250      *
12251      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12252      * necessitates that a View return true if it uses the methods internally without passing the
12253      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12254      *
12255      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12256      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12257      *
12258      * @return true if the content in this view might overlap, false otherwise.
12259      */
12260     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()12261     public boolean hasOverlappingRendering() {
12262         return true;
12263     }
12264 
12265     /**
12266      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12267      * completely transparent and 1 means the view is completely opaque.
12268      *
12269      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12270      * can have significant performance implications, especially for large views. It is best to use
12271      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12272      *
12273      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12274      * strongly recommended for performance reasons to either override
12275      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12276      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12277      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12278      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12279      * of rendering cost, even for simple or small views. Starting with
12280      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12281      * applied to the view at the rendering level.</p>
12282      *
12283      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12284      * responsible for applying the opacity itself.</p>
12285      *
12286      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12287      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12288      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12289      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12290      *
12291      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12292      * value will clip a View to its bounds, unless the View returns <code>false</code> from
12293      * {@link #hasOverlappingRendering}.</p>
12294      *
12295      * @param alpha The opacity of the view.
12296      *
12297      * @see #hasOverlappingRendering()
12298      * @see #setLayerType(int, android.graphics.Paint)
12299      *
12300      * @attr ref android.R.styleable#View_alpha
12301      */
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)12302     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12303         ensureTransformationInfo();
12304         if (mTransformationInfo.mAlpha != alpha) {
12305             mTransformationInfo.mAlpha = alpha;
12306             if (onSetAlpha((int) (alpha * 255))) {
12307                 mPrivateFlags |= PFLAG_ALPHA_SET;
12308                 // subclass is handling alpha - don't optimize rendering cache invalidation
12309                 invalidateParentCaches();
12310                 invalidate(true);
12311             } else {
12312                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12313                 invalidateViewProperty(true, false);
12314                 mRenderNode.setAlpha(getFinalAlpha());
12315                 notifyViewAccessibilityStateChangedIfNeeded(
12316                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12317             }
12318         }
12319     }
12320 
12321     /**
12322      * Faster version of setAlpha() which performs the same steps except there are
12323      * no calls to invalidate(). The caller of this function should perform proper invalidation
12324      * on the parent and this object. The return value indicates whether the subclass handles
12325      * alpha (the return value for onSetAlpha()).
12326      *
12327      * @param alpha The new value for the alpha property
12328      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12329      *         the new value for the alpha property is different from the old value
12330      */
setAlphaNoInvalidation(float alpha)12331     boolean setAlphaNoInvalidation(float alpha) {
12332         ensureTransformationInfo();
12333         if (mTransformationInfo.mAlpha != alpha) {
12334             mTransformationInfo.mAlpha = alpha;
12335             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12336             if (subclassHandlesAlpha) {
12337                 mPrivateFlags |= PFLAG_ALPHA_SET;
12338                 return true;
12339             } else {
12340                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12341                 mRenderNode.setAlpha(getFinalAlpha());
12342             }
12343         }
12344         return false;
12345     }
12346 
12347     /**
12348      * This property is hidden and intended only for use by the Fade transition, which
12349      * animates it to produce a visual translucency that does not side-effect (or get
12350      * affected by) the real alpha property. This value is composited with the other
12351      * alpha value (and the AlphaAnimation value, when that is present) to produce
12352      * a final visual translucency result, which is what is passed into the DisplayList.
12353      *
12354      * @hide
12355      */
setTransitionAlpha(float alpha)12356     public void setTransitionAlpha(float alpha) {
12357         ensureTransformationInfo();
12358         if (mTransformationInfo.mTransitionAlpha != alpha) {
12359             mTransformationInfo.mTransitionAlpha = alpha;
12360             mPrivateFlags &= ~PFLAG_ALPHA_SET;
12361             invalidateViewProperty(true, false);
12362             mRenderNode.setAlpha(getFinalAlpha());
12363         }
12364     }
12365 
12366     /**
12367      * Calculates the visual alpha of this view, which is a combination of the actual
12368      * alpha value and the transitionAlpha value (if set).
12369      */
getFinalAlpha()12370     private float getFinalAlpha() {
12371         if (mTransformationInfo != null) {
12372             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12373         }
12374         return 1;
12375     }
12376 
12377     /**
12378      * This property is hidden and intended only for use by the Fade transition, which
12379      * animates it to produce a visual translucency that does not side-effect (or get
12380      * affected by) the real alpha property. This value is composited with the other
12381      * alpha value (and the AlphaAnimation value, when that is present) to produce
12382      * a final visual translucency result, which is what is passed into the DisplayList.
12383      *
12384      * @hide
12385      */
12386     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()12387     public float getTransitionAlpha() {
12388         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12389     }
12390 
12391     /**
12392      * Top position of this view relative to its parent.
12393      *
12394      * @return The top of this view, in pixels.
12395      */
12396     @ViewDebug.CapturedViewProperty
getTop()12397     public final int getTop() {
12398         return mTop;
12399     }
12400 
12401     /**
12402      * Sets the top position of this view relative to its parent. This method is meant to be called
12403      * by the layout system and should not generally be called otherwise, because the property
12404      * may be changed at any time by the layout.
12405      *
12406      * @param top The top of this view, in pixels.
12407      */
setTop(int top)12408     public final void setTop(int top) {
12409         if (top != mTop) {
12410             final boolean matrixIsIdentity = hasIdentityMatrix();
12411             if (matrixIsIdentity) {
12412                 if (mAttachInfo != null) {
12413                     int minTop;
12414                     int yLoc;
12415                     if (top < mTop) {
12416                         minTop = top;
12417                         yLoc = top - mTop;
12418                     } else {
12419                         minTop = mTop;
12420                         yLoc = 0;
12421                     }
12422                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12423                 }
12424             } else {
12425                 // Double-invalidation is necessary to capture view's old and new areas
12426                 invalidate(true);
12427             }
12428 
12429             int width = mRight - mLeft;
12430             int oldHeight = mBottom - mTop;
12431 
12432             mTop = top;
12433             mRenderNode.setTop(mTop);
12434 
12435             sizeChange(width, mBottom - mTop, width, oldHeight);
12436 
12437             if (!matrixIsIdentity) {
12438                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12439                 invalidate(true);
12440             }
12441             mBackgroundSizeChanged = true;
12442             if (mForegroundInfo != null) {
12443                 mForegroundInfo.mBoundsChanged = true;
12444             }
12445             invalidateParentIfNeeded();
12446             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12447                 // View was rejected last time it was drawn by its parent; this may have changed
12448                 invalidateParentIfNeeded();
12449             }
12450         }
12451     }
12452 
12453     /**
12454      * Bottom position of this view relative to its parent.
12455      *
12456      * @return The bottom of this view, in pixels.
12457      */
12458     @ViewDebug.CapturedViewProperty
getBottom()12459     public final int getBottom() {
12460         return mBottom;
12461     }
12462 
12463     /**
12464      * True if this view has changed since the last time being drawn.
12465      *
12466      * @return The dirty state of this view.
12467      */
isDirty()12468     public boolean isDirty() {
12469         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12470     }
12471 
12472     /**
12473      * Sets the bottom position of this view relative to its parent. This method is meant to be
12474      * called by the layout system and should not generally be called otherwise, because the
12475      * property may be changed at any time by the layout.
12476      *
12477      * @param bottom The bottom of this view, in pixels.
12478      */
setBottom(int bottom)12479     public final void setBottom(int bottom) {
12480         if (bottom != mBottom) {
12481             final boolean matrixIsIdentity = hasIdentityMatrix();
12482             if (matrixIsIdentity) {
12483                 if (mAttachInfo != null) {
12484                     int maxBottom;
12485                     if (bottom < mBottom) {
12486                         maxBottom = mBottom;
12487                     } else {
12488                         maxBottom = bottom;
12489                     }
12490                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12491                 }
12492             } else {
12493                 // Double-invalidation is necessary to capture view's old and new areas
12494                 invalidate(true);
12495             }
12496 
12497             int width = mRight - mLeft;
12498             int oldHeight = mBottom - mTop;
12499 
12500             mBottom = bottom;
12501             mRenderNode.setBottom(mBottom);
12502 
12503             sizeChange(width, mBottom - mTop, width, oldHeight);
12504 
12505             if (!matrixIsIdentity) {
12506                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12507                 invalidate(true);
12508             }
12509             mBackgroundSizeChanged = true;
12510             if (mForegroundInfo != null) {
12511                 mForegroundInfo.mBoundsChanged = true;
12512             }
12513             invalidateParentIfNeeded();
12514             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12515                 // View was rejected last time it was drawn by its parent; this may have changed
12516                 invalidateParentIfNeeded();
12517             }
12518         }
12519     }
12520 
12521     /**
12522      * Left position of this view relative to its parent.
12523      *
12524      * @return The left edge of this view, in pixels.
12525      */
12526     @ViewDebug.CapturedViewProperty
getLeft()12527     public final int getLeft() {
12528         return mLeft;
12529     }
12530 
12531     /**
12532      * Sets the left position of this view relative to its parent. This method is meant to be called
12533      * by the layout system and should not generally be called otherwise, because the property
12534      * may be changed at any time by the layout.
12535      *
12536      * @param left The left of this view, in pixels.
12537      */
setLeft(int left)12538     public final void setLeft(int left) {
12539         if (left != mLeft) {
12540             final boolean matrixIsIdentity = hasIdentityMatrix();
12541             if (matrixIsIdentity) {
12542                 if (mAttachInfo != null) {
12543                     int minLeft;
12544                     int xLoc;
12545                     if (left < mLeft) {
12546                         minLeft = left;
12547                         xLoc = left - mLeft;
12548                     } else {
12549                         minLeft = mLeft;
12550                         xLoc = 0;
12551                     }
12552                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12553                 }
12554             } else {
12555                 // Double-invalidation is necessary to capture view's old and new areas
12556                 invalidate(true);
12557             }
12558 
12559             int oldWidth = mRight - mLeft;
12560             int height = mBottom - mTop;
12561 
12562             mLeft = left;
12563             mRenderNode.setLeft(left);
12564 
12565             sizeChange(mRight - mLeft, height, oldWidth, height);
12566 
12567             if (!matrixIsIdentity) {
12568                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12569                 invalidate(true);
12570             }
12571             mBackgroundSizeChanged = true;
12572             if (mForegroundInfo != null) {
12573                 mForegroundInfo.mBoundsChanged = true;
12574             }
12575             invalidateParentIfNeeded();
12576             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12577                 // View was rejected last time it was drawn by its parent; this may have changed
12578                 invalidateParentIfNeeded();
12579             }
12580         }
12581     }
12582 
12583     /**
12584      * Right position of this view relative to its parent.
12585      *
12586      * @return The right edge of this view, in pixels.
12587      */
12588     @ViewDebug.CapturedViewProperty
getRight()12589     public final int getRight() {
12590         return mRight;
12591     }
12592 
12593     /**
12594      * Sets the right position of this view relative to its parent. This method is meant to be called
12595      * by the layout system and should not generally be called otherwise, because the property
12596      * may be changed at any time by the layout.
12597      *
12598      * @param right The right of this view, in pixels.
12599      */
setRight(int right)12600     public final void setRight(int right) {
12601         if (right != mRight) {
12602             final boolean matrixIsIdentity = hasIdentityMatrix();
12603             if (matrixIsIdentity) {
12604                 if (mAttachInfo != null) {
12605                     int maxRight;
12606                     if (right < mRight) {
12607                         maxRight = mRight;
12608                     } else {
12609                         maxRight = right;
12610                     }
12611                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12612                 }
12613             } else {
12614                 // Double-invalidation is necessary to capture view's old and new areas
12615                 invalidate(true);
12616             }
12617 
12618             int oldWidth = mRight - mLeft;
12619             int height = mBottom - mTop;
12620 
12621             mRight = right;
12622             mRenderNode.setRight(mRight);
12623 
12624             sizeChange(mRight - mLeft, height, oldWidth, height);
12625 
12626             if (!matrixIsIdentity) {
12627                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12628                 invalidate(true);
12629             }
12630             mBackgroundSizeChanged = true;
12631             if (mForegroundInfo != null) {
12632                 mForegroundInfo.mBoundsChanged = true;
12633             }
12634             invalidateParentIfNeeded();
12635             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12636                 // View was rejected last time it was drawn by its parent; this may have changed
12637                 invalidateParentIfNeeded();
12638             }
12639         }
12640     }
12641 
12642     /**
12643      * The visual x position of this view, in pixels. This is equivalent to the
12644      * {@link #setTranslationX(float) translationX} property plus the current
12645      * {@link #getLeft() left} property.
12646      *
12647      * @return The visual x position of this view, in pixels.
12648      */
12649     @ViewDebug.ExportedProperty(category = "drawing")
getX()12650     public float getX() {
12651         return mLeft + getTranslationX();
12652     }
12653 
12654     /**
12655      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12656      * {@link #setTranslationX(float) translationX} property to be the difference between
12657      * the x value passed in and the current {@link #getLeft() left} property.
12658      *
12659      * @param x The visual x position of this view, in pixels.
12660      */
setX(float x)12661     public void setX(float x) {
12662         setTranslationX(x - mLeft);
12663     }
12664 
12665     /**
12666      * The visual y position of this view, in pixels. This is equivalent to the
12667      * {@link #setTranslationY(float) translationY} property plus the current
12668      * {@link #getTop() top} property.
12669      *
12670      * @return The visual y position of this view, in pixels.
12671      */
12672     @ViewDebug.ExportedProperty(category = "drawing")
getY()12673     public float getY() {
12674         return mTop + getTranslationY();
12675     }
12676 
12677     /**
12678      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12679      * {@link #setTranslationY(float) translationY} property to be the difference between
12680      * the y value passed in and the current {@link #getTop() top} property.
12681      *
12682      * @param y The visual y position of this view, in pixels.
12683      */
setY(float y)12684     public void setY(float y) {
12685         setTranslationY(y - mTop);
12686     }
12687 
12688     /**
12689      * The visual z position of this view, in pixels. This is equivalent to the
12690      * {@link #setTranslationZ(float) translationZ} property plus the current
12691      * {@link #getElevation() elevation} property.
12692      *
12693      * @return The visual z position of this view, in pixels.
12694      */
12695     @ViewDebug.ExportedProperty(category = "drawing")
getZ()12696     public float getZ() {
12697         return getElevation() + getTranslationZ();
12698     }
12699 
12700     /**
12701      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12702      * {@link #setTranslationZ(float) translationZ} property to be the difference between
12703      * the x value passed in and the current {@link #getElevation() elevation} property.
12704      *
12705      * @param z The visual z position of this view, in pixels.
12706      */
setZ(float z)12707     public void setZ(float z) {
12708         setTranslationZ(z - getElevation());
12709     }
12710 
12711     /**
12712      * The base elevation of this view relative to its parent, in pixels.
12713      *
12714      * @return The base depth position of the view, in pixels.
12715      */
12716     @ViewDebug.ExportedProperty(category = "drawing")
getElevation()12717     public float getElevation() {
12718         return mRenderNode.getElevation();
12719     }
12720 
12721     /**
12722      * Sets the base elevation of this view, in pixels.
12723      *
12724      * @attr ref android.R.styleable#View_elevation
12725      */
setElevation(float elevation)12726     public void setElevation(float elevation) {
12727         if (elevation != getElevation()) {
12728             invalidateViewProperty(true, false);
12729             mRenderNode.setElevation(elevation);
12730             invalidateViewProperty(false, true);
12731 
12732             invalidateParentIfNeededAndWasQuickRejected();
12733         }
12734     }
12735 
12736     /**
12737      * The horizontal location of this view relative to its {@link #getLeft() left} position.
12738      * This position is post-layout, in addition to wherever the object's
12739      * layout placed it.
12740      *
12741      * @return The horizontal position of this view relative to its left position, in pixels.
12742      */
12743     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationX()12744     public float getTranslationX() {
12745         return mRenderNode.getTranslationX();
12746     }
12747 
12748     /**
12749      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12750      * This effectively positions the object post-layout, in addition to wherever the object's
12751      * layout placed it.
12752      *
12753      * @param translationX The horizontal position of this view relative to its left position,
12754      * in pixels.
12755      *
12756      * @attr ref android.R.styleable#View_translationX
12757      */
setTranslationX(float translationX)12758     public void setTranslationX(float translationX) {
12759         if (translationX != getTranslationX()) {
12760             invalidateViewProperty(true, false);
12761             mRenderNode.setTranslationX(translationX);
12762             invalidateViewProperty(false, true);
12763 
12764             invalidateParentIfNeededAndWasQuickRejected();
12765             notifySubtreeAccessibilityStateChangedIfNeeded();
12766         }
12767     }
12768 
12769     /**
12770      * The vertical location of this view relative to its {@link #getTop() top} position.
12771      * This position is post-layout, in addition to wherever the object's
12772      * layout placed it.
12773      *
12774      * @return The vertical position of this view relative to its top position,
12775      * in pixels.
12776      */
12777     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationY()12778     public float getTranslationY() {
12779         return mRenderNode.getTranslationY();
12780     }
12781 
12782     /**
12783      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12784      * This effectively positions the object post-layout, in addition to wherever the object's
12785      * layout placed it.
12786      *
12787      * @param translationY The vertical position of this view relative to its top position,
12788      * in pixels.
12789      *
12790      * @attr ref android.R.styleable#View_translationY
12791      */
setTranslationY(float translationY)12792     public void setTranslationY(float translationY) {
12793         if (translationY != getTranslationY()) {
12794             invalidateViewProperty(true, false);
12795             mRenderNode.setTranslationY(translationY);
12796             invalidateViewProperty(false, true);
12797 
12798             invalidateParentIfNeededAndWasQuickRejected();
12799             notifySubtreeAccessibilityStateChangedIfNeeded();
12800         }
12801     }
12802 
12803     /**
12804      * The depth location of this view relative to its {@link #getElevation() elevation}.
12805      *
12806      * @return The depth of this view relative to its elevation.
12807      */
12808     @ViewDebug.ExportedProperty(category = "drawing")
getTranslationZ()12809     public float getTranslationZ() {
12810         return mRenderNode.getTranslationZ();
12811     }
12812 
12813     /**
12814      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12815      *
12816      * @attr ref android.R.styleable#View_translationZ
12817      */
setTranslationZ(float translationZ)12818     public void setTranslationZ(float translationZ) {
12819         if (translationZ != getTranslationZ()) {
12820             invalidateViewProperty(true, false);
12821             mRenderNode.setTranslationZ(translationZ);
12822             invalidateViewProperty(false, true);
12823 
12824             invalidateParentIfNeededAndWasQuickRejected();
12825         }
12826     }
12827 
12828     /** @hide */
setAnimationMatrix(Matrix matrix)12829     public void setAnimationMatrix(Matrix matrix) {
12830         invalidateViewProperty(true, false);
12831         mRenderNode.setAnimationMatrix(matrix);
12832         invalidateViewProperty(false, true);
12833 
12834         invalidateParentIfNeededAndWasQuickRejected();
12835     }
12836 
12837     /**
12838      * Returns the current StateListAnimator if exists.
12839      *
12840      * @return StateListAnimator or null if it does not exists
12841      * @see    #setStateListAnimator(android.animation.StateListAnimator)
12842      */
getStateListAnimator()12843     public StateListAnimator getStateListAnimator() {
12844         return mStateListAnimator;
12845     }
12846 
12847     /**
12848      * Attaches the provided StateListAnimator to this View.
12849      * <p>
12850      * Any previously attached StateListAnimator will be detached.
12851      *
12852      * @param stateListAnimator The StateListAnimator to update the view
12853      * @see {@link android.animation.StateListAnimator}
12854      */
setStateListAnimator(StateListAnimator stateListAnimator)12855     public void setStateListAnimator(StateListAnimator stateListAnimator) {
12856         if (mStateListAnimator == stateListAnimator) {
12857             return;
12858         }
12859         if (mStateListAnimator != null) {
12860             mStateListAnimator.setTarget(null);
12861         }
12862         mStateListAnimator = stateListAnimator;
12863         if (stateListAnimator != null) {
12864             stateListAnimator.setTarget(this);
12865             if (isAttachedToWindow()) {
12866                 stateListAnimator.setState(getDrawableState());
12867             }
12868         }
12869     }
12870 
12871     /**
12872      * Returns whether the Outline should be used to clip the contents of the View.
12873      * <p>
12874      * Note that this flag will only be respected if the View's Outline returns true from
12875      * {@link Outline#canClip()}.
12876      *
12877      * @see #setOutlineProvider(ViewOutlineProvider)
12878      * @see #setClipToOutline(boolean)
12879      */
getClipToOutline()12880     public final boolean getClipToOutline() {
12881         return mRenderNode.getClipToOutline();
12882     }
12883 
12884     /**
12885      * Sets whether the View's Outline should be used to clip the contents of the View.
12886      * <p>
12887      * Only a single non-rectangular clip can be applied on a View at any time.
12888      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12889      * circular reveal} animation take priority over Outline clipping, and
12890      * child Outline clipping takes priority over Outline clipping done by a
12891      * parent.
12892      * <p>
12893      * Note that this flag will only be respected if the View's Outline returns true from
12894      * {@link Outline#canClip()}.
12895      *
12896      * @see #setOutlineProvider(ViewOutlineProvider)
12897      * @see #getClipToOutline()
12898      */
setClipToOutline(boolean clipToOutline)12899     public void setClipToOutline(boolean clipToOutline) {
12900         damageInParent();
12901         if (getClipToOutline() != clipToOutline) {
12902             mRenderNode.setClipToOutline(clipToOutline);
12903         }
12904     }
12905 
12906     // correspond to the enum values of View_outlineProvider
12907     private static final int PROVIDER_BACKGROUND = 0;
12908     private static final int PROVIDER_NONE = 1;
12909     private static final int PROVIDER_BOUNDS = 2;
12910     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)12911     private void setOutlineProviderFromAttribute(int providerInt) {
12912         switch (providerInt) {
12913             case PROVIDER_BACKGROUND:
12914                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12915                 break;
12916             case PROVIDER_NONE:
12917                 setOutlineProvider(null);
12918                 break;
12919             case PROVIDER_BOUNDS:
12920                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
12921                 break;
12922             case PROVIDER_PADDED_BOUNDS:
12923                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12924                 break;
12925         }
12926     }
12927 
12928     /**
12929      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12930      * the shape of the shadow it casts, and enables outline clipping.
12931      * <p>
12932      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12933      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12934      * outline provider with this method allows this behavior to be overridden.
12935      * <p>
12936      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12937      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12938      * <p>
12939      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12940      *
12941      * @see #setClipToOutline(boolean)
12942      * @see #getClipToOutline()
12943      * @see #getOutlineProvider()
12944      */
setOutlineProvider(ViewOutlineProvider provider)12945     public void setOutlineProvider(ViewOutlineProvider provider) {
12946         mOutlineProvider = provider;
12947         invalidateOutline();
12948     }
12949 
12950     /**
12951      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12952      * that defines the shape of the shadow it casts, and enables outline clipping.
12953      *
12954      * @see #setOutlineProvider(ViewOutlineProvider)
12955      */
getOutlineProvider()12956     public ViewOutlineProvider getOutlineProvider() {
12957         return mOutlineProvider;
12958     }
12959 
12960     /**
12961      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12962      *
12963      * @see #setOutlineProvider(ViewOutlineProvider)
12964      */
invalidateOutline()12965     public void invalidateOutline() {
12966         rebuildOutline();
12967 
12968         notifySubtreeAccessibilityStateChangedIfNeeded();
12969         invalidateViewProperty(false, false);
12970     }
12971 
12972     /**
12973      * Internal version of {@link #invalidateOutline()} which invalidates the
12974      * outline without invalidating the view itself. This is intended to be called from
12975      * within methods in the View class itself which are the result of the view being
12976      * invalidated already. For example, when we are drawing the background of a View,
12977      * we invalidate the outline in case it changed in the meantime, but we do not
12978      * need to invalidate the view because we're already drawing the background as part
12979      * of drawing the view in response to an earlier invalidation of the view.
12980      */
rebuildOutline()12981     private void rebuildOutline() {
12982         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12983         if (mAttachInfo == null) return;
12984 
12985         if (mOutlineProvider == null) {
12986             // no provider, remove outline
12987             mRenderNode.setOutline(null);
12988         } else {
12989             final Outline outline = mAttachInfo.mTmpOutline;
12990             outline.setEmpty();
12991             outline.setAlpha(1.0f);
12992 
12993             mOutlineProvider.getOutline(this, outline);
12994             mRenderNode.setOutline(outline);
12995         }
12996     }
12997 
12998     /**
12999      * HierarchyViewer only
13000      *
13001      * @hide
13002      */
13003     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()13004     public boolean hasShadow() {
13005         return mRenderNode.hasShadow();
13006     }
13007 
13008 
13009     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)13010     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13011         mRenderNode.setRevealClip(shouldClip, x, y, radius);
13012         invalidateViewProperty(false, false);
13013     }
13014 
13015     /**
13016      * Hit rectangle in parent's coordinates
13017      *
13018      * @param outRect The hit rectangle of the view.
13019      */
getHitRect(Rect outRect)13020     public void getHitRect(Rect outRect) {
13021         if (hasIdentityMatrix() || mAttachInfo == null) {
13022             outRect.set(mLeft, mTop, mRight, mBottom);
13023         } else {
13024             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13025             tmpRect.set(0, 0, getWidth(), getHeight());
13026             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13027             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13028                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13029         }
13030     }
13031 
13032     /**
13033      * Determines whether the given point, in local coordinates is inside the view.
13034      */
pointInView(float localX, float localY)13035     /*package*/ final boolean pointInView(float localX, float localY) {
13036         return pointInView(localX, localY, 0);
13037     }
13038 
13039     /**
13040      * Utility method to determine whether the given point, in local coordinates,
13041      * is inside the view, where the area of the view is expanded by the slop factor.
13042      * This method is called while processing touch-move events to determine if the event
13043      * is still within the view.
13044      *
13045      * @hide
13046      */
pointInView(float localX, float localY, float slop)13047     public boolean pointInView(float localX, float localY, float slop) {
13048         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13049                 localY < ((mBottom - mTop) + slop);
13050     }
13051 
13052     /**
13053      * When a view has focus and the user navigates away from it, the next view is searched for
13054      * starting from the rectangle filled in by this method.
13055      *
13056      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13057      * of the view.  However, if your view maintains some idea of internal selection,
13058      * such as a cursor, or a selected row or column, you should override this method and
13059      * fill in a more specific rectangle.
13060      *
13061      * @param r The rectangle to fill in, in this view's coordinates.
13062      */
getFocusedRect(Rect r)13063     public void getFocusedRect(Rect r) {
13064         getDrawingRect(r);
13065     }
13066 
13067     /**
13068      * If some part of this view is not clipped by any of its parents, then
13069      * return that area in r in global (root) coordinates. To convert r to local
13070      * coordinates (without taking possible View rotations into account), offset
13071      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13072      * If the view is completely clipped or translated out, return false.
13073      *
13074      * @param r If true is returned, r holds the global coordinates of the
13075      *        visible portion of this view.
13076      * @param globalOffset If true is returned, globalOffset holds the dx,dy
13077      *        between this view and its root. globalOffet may be null.
13078      * @return true if r is non-empty (i.e. part of the view is visible at the
13079      *         root level.
13080      */
getGlobalVisibleRect(Rect r, Point globalOffset)13081     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13082         int width = mRight - mLeft;
13083         int height = mBottom - mTop;
13084         if (width > 0 && height > 0) {
13085             r.set(0, 0, width, height);
13086             if (globalOffset != null) {
13087                 globalOffset.set(-mScrollX, -mScrollY);
13088             }
13089             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13090         }
13091         return false;
13092     }
13093 
getGlobalVisibleRect(Rect r)13094     public final boolean getGlobalVisibleRect(Rect r) {
13095         return getGlobalVisibleRect(r, null);
13096     }
13097 
getLocalVisibleRect(Rect r)13098     public final boolean getLocalVisibleRect(Rect r) {
13099         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13100         if (getGlobalVisibleRect(r, offset)) {
13101             r.offset(-offset.x, -offset.y); // make r local
13102             return true;
13103         }
13104         return false;
13105     }
13106 
13107     /**
13108      * Offset this view's vertical location by the specified number of pixels.
13109      *
13110      * @param offset the number of pixels to offset the view by
13111      */
offsetTopAndBottom(int offset)13112     public void offsetTopAndBottom(int offset) {
13113         if (offset != 0) {
13114             final boolean matrixIsIdentity = hasIdentityMatrix();
13115             if (matrixIsIdentity) {
13116                 if (isHardwareAccelerated()) {
13117                     invalidateViewProperty(false, false);
13118                 } else {
13119                     final ViewParent p = mParent;
13120                     if (p != null && mAttachInfo != null) {
13121                         final Rect r = mAttachInfo.mTmpInvalRect;
13122                         int minTop;
13123                         int maxBottom;
13124                         int yLoc;
13125                         if (offset < 0) {
13126                             minTop = mTop + offset;
13127                             maxBottom = mBottom;
13128                             yLoc = offset;
13129                         } else {
13130                             minTop = mTop;
13131                             maxBottom = mBottom + offset;
13132                             yLoc = 0;
13133                         }
13134                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13135                         p.invalidateChild(this, r);
13136                     }
13137                 }
13138             } else {
13139                 invalidateViewProperty(false, false);
13140             }
13141 
13142             mTop += offset;
13143             mBottom += offset;
13144             mRenderNode.offsetTopAndBottom(offset);
13145             if (isHardwareAccelerated()) {
13146                 invalidateViewProperty(false, false);
13147                 invalidateParentIfNeededAndWasQuickRejected();
13148             } else {
13149                 if (!matrixIsIdentity) {
13150                     invalidateViewProperty(false, true);
13151                 }
13152                 invalidateParentIfNeeded();
13153             }
13154             notifySubtreeAccessibilityStateChangedIfNeeded();
13155         }
13156     }
13157 
13158     /**
13159      * Offset this view's horizontal location by the specified amount of pixels.
13160      *
13161      * @param offset the number of pixels to offset the view by
13162      */
offsetLeftAndRight(int offset)13163     public void offsetLeftAndRight(int offset) {
13164         if (offset != 0) {
13165             final boolean matrixIsIdentity = hasIdentityMatrix();
13166             if (matrixIsIdentity) {
13167                 if (isHardwareAccelerated()) {
13168                     invalidateViewProperty(false, false);
13169                 } else {
13170                     final ViewParent p = mParent;
13171                     if (p != null && mAttachInfo != null) {
13172                         final Rect r = mAttachInfo.mTmpInvalRect;
13173                         int minLeft;
13174                         int maxRight;
13175                         if (offset < 0) {
13176                             minLeft = mLeft + offset;
13177                             maxRight = mRight;
13178                         } else {
13179                             minLeft = mLeft;
13180                             maxRight = mRight + offset;
13181                         }
13182                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13183                         p.invalidateChild(this, r);
13184                     }
13185                 }
13186             } else {
13187                 invalidateViewProperty(false, false);
13188             }
13189 
13190             mLeft += offset;
13191             mRight += offset;
13192             mRenderNode.offsetLeftAndRight(offset);
13193             if (isHardwareAccelerated()) {
13194                 invalidateViewProperty(false, false);
13195                 invalidateParentIfNeededAndWasQuickRejected();
13196             } else {
13197                 if (!matrixIsIdentity) {
13198                     invalidateViewProperty(false, true);
13199                 }
13200                 invalidateParentIfNeeded();
13201             }
13202             notifySubtreeAccessibilityStateChangedIfNeeded();
13203         }
13204     }
13205 
13206     /**
13207      * Get the LayoutParams associated with this view. All views should have
13208      * layout parameters. These supply parameters to the <i>parent</i> of this
13209      * view specifying how it should be arranged. There are many subclasses of
13210      * ViewGroup.LayoutParams, and these correspond to the different subclasses
13211      * of ViewGroup that are responsible for arranging their children.
13212      *
13213      * This method may return null if this View is not attached to a parent
13214      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13215      * was not invoked successfully. When a View is attached to a parent
13216      * ViewGroup, this method must not return null.
13217      *
13218      * @return The LayoutParams associated with this view, or null if no
13219      *         parameters have been set yet
13220      */
13221     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()13222     public ViewGroup.LayoutParams getLayoutParams() {
13223         return mLayoutParams;
13224     }
13225 
13226     /**
13227      * Set the layout parameters associated with this view. These supply
13228      * parameters to the <i>parent</i> of this view specifying how it should be
13229      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13230      * correspond to the different subclasses of ViewGroup that are responsible
13231      * for arranging their children.
13232      *
13233      * @param params The layout parameters for this view, cannot be null
13234      */
setLayoutParams(ViewGroup.LayoutParams params)13235     public void setLayoutParams(ViewGroup.LayoutParams params) {
13236         if (params == null) {
13237             throw new NullPointerException("Layout parameters cannot be null");
13238         }
13239         mLayoutParams = params;
13240         resolveLayoutParams();
13241         if (mParent instanceof ViewGroup) {
13242             ((ViewGroup) mParent).onSetLayoutParams(this, params);
13243         }
13244         requestLayout();
13245     }
13246 
13247     /**
13248      * Resolve the layout parameters depending on the resolved layout direction
13249      *
13250      * @hide
13251      */
resolveLayoutParams()13252     public void resolveLayoutParams() {
13253         if (mLayoutParams != null) {
13254             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13255         }
13256     }
13257 
13258     /**
13259      * Set the scrolled position of your view. This will cause a call to
13260      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13261      * invalidated.
13262      * @param x the x position to scroll to
13263      * @param y the y position to scroll to
13264      */
scrollTo(int x, int y)13265     public void scrollTo(int x, int y) {
13266         if (mScrollX != x || mScrollY != y) {
13267             int oldX = mScrollX;
13268             int oldY = mScrollY;
13269             mScrollX = x;
13270             mScrollY = y;
13271             invalidateParentCaches();
13272             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13273             if (!awakenScrollBars()) {
13274                 postInvalidateOnAnimation();
13275             }
13276         }
13277     }
13278 
13279     /**
13280      * Move the scrolled position of your view. This will cause a call to
13281      * {@link #onScrollChanged(int, int, int, int)} and the view will be
13282      * invalidated.
13283      * @param x the amount of pixels to scroll by horizontally
13284      * @param y the amount of pixels to scroll by vertically
13285      */
scrollBy(int x, int y)13286     public void scrollBy(int x, int y) {
13287         scrollTo(mScrollX + x, mScrollY + y);
13288     }
13289 
13290     /**
13291      * <p>Trigger the scrollbars to draw. When invoked this method starts an
13292      * animation to fade the scrollbars out after a default delay. If a subclass
13293      * provides animated scrolling, the start delay should equal the duration
13294      * of the scrolling animation.</p>
13295      *
13296      * <p>The animation starts only if at least one of the scrollbars is
13297      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13298      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13299      * this method returns true, and false otherwise. If the animation is
13300      * started, this method calls {@link #invalidate()}; in that case the
13301      * caller should not call {@link #invalidate()}.</p>
13302      *
13303      * <p>This method should be invoked every time a subclass directly updates
13304      * the scroll parameters.</p>
13305      *
13306      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13307      * and {@link #scrollTo(int, int)}.</p>
13308      *
13309      * @return true if the animation is played, false otherwise
13310      *
13311      * @see #awakenScrollBars(int)
13312      * @see #scrollBy(int, int)
13313      * @see #scrollTo(int, int)
13314      * @see #isHorizontalScrollBarEnabled()
13315      * @see #isVerticalScrollBarEnabled()
13316      * @see #setHorizontalScrollBarEnabled(boolean)
13317      * @see #setVerticalScrollBarEnabled(boolean)
13318      */
awakenScrollBars()13319     protected boolean awakenScrollBars() {
13320         return mScrollCache != null &&
13321                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13322     }
13323 
13324     /**
13325      * Trigger the scrollbars to draw.
13326      * This method differs from awakenScrollBars() only in its default duration.
13327      * initialAwakenScrollBars() will show the scroll bars for longer than
13328      * usual to give the user more of a chance to notice them.
13329      *
13330      * @return true if the animation is played, false otherwise.
13331      */
initialAwakenScrollBars()13332     private boolean initialAwakenScrollBars() {
13333         return mScrollCache != null &&
13334                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13335     }
13336 
13337     /**
13338      * <p>
13339      * Trigger the scrollbars to draw. When invoked this method starts an
13340      * animation to fade the scrollbars out after a fixed delay. If a subclass
13341      * provides animated scrolling, the start delay should equal the duration of
13342      * the scrolling animation.
13343      * </p>
13344      *
13345      * <p>
13346      * The animation starts only if at least one of the scrollbars is enabled,
13347      * as specified by {@link #isHorizontalScrollBarEnabled()} and
13348      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13349      * this method returns true, and false otherwise. If the animation is
13350      * started, this method calls {@link #invalidate()}; in that case the caller
13351      * should not call {@link #invalidate()}.
13352      * </p>
13353      *
13354      * <p>
13355      * This method should be invoked every time a subclass directly updates the
13356      * scroll parameters.
13357      * </p>
13358      *
13359      * @param startDelay the delay, in milliseconds, after which the animation
13360      *        should start; when the delay is 0, the animation starts
13361      *        immediately
13362      * @return true if the animation is played, false otherwise
13363      *
13364      * @see #scrollBy(int, int)
13365      * @see #scrollTo(int, int)
13366      * @see #isHorizontalScrollBarEnabled()
13367      * @see #isVerticalScrollBarEnabled()
13368      * @see #setHorizontalScrollBarEnabled(boolean)
13369      * @see #setVerticalScrollBarEnabled(boolean)
13370      */
awakenScrollBars(int startDelay)13371     protected boolean awakenScrollBars(int startDelay) {
13372         return awakenScrollBars(startDelay, true);
13373     }
13374 
13375     /**
13376      * <p>
13377      * Trigger the scrollbars to draw. When invoked this method starts an
13378      * animation to fade the scrollbars out after a fixed delay. If a subclass
13379      * provides animated scrolling, the start delay should equal the duration of
13380      * the scrolling animation.
13381      * </p>
13382      *
13383      * <p>
13384      * The animation starts only if at least one of the scrollbars is enabled,
13385      * 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()} if the invalidate parameter
13389      * is set to true; in that case the caller
13390      * should not call {@link #invalidate()}.
13391      * </p>
13392      *
13393      * <p>
13394      * This method should be invoked every time a subclass directly updates the
13395      * scroll parameters.
13396      * </p>
13397      *
13398      * @param startDelay the delay, in milliseconds, after which the animation
13399      *        should start; when the delay is 0, the animation starts
13400      *        immediately
13401      *
13402      * @param invalidate Whether this method should call invalidate
13403      *
13404      * @return true if the animation is played, false otherwise
13405      *
13406      * @see #scrollBy(int, int)
13407      * @see #scrollTo(int, int)
13408      * @see #isHorizontalScrollBarEnabled()
13409      * @see #isVerticalScrollBarEnabled()
13410      * @see #setHorizontalScrollBarEnabled(boolean)
13411      * @see #setVerticalScrollBarEnabled(boolean)
13412      */
awakenScrollBars(int startDelay, boolean invalidate)13413     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13414         final ScrollabilityCache scrollCache = mScrollCache;
13415 
13416         if (scrollCache == null || !scrollCache.fadeScrollBars) {
13417             return false;
13418         }
13419 
13420         if (scrollCache.scrollBar == null) {
13421             scrollCache.scrollBar = new ScrollBarDrawable();
13422             scrollCache.scrollBar.setState(getDrawableState());
13423             scrollCache.scrollBar.setCallback(this);
13424         }
13425 
13426         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13427 
13428             if (invalidate) {
13429                 // Invalidate to show the scrollbars
13430                 postInvalidateOnAnimation();
13431             }
13432 
13433             if (scrollCache.state == ScrollabilityCache.OFF) {
13434                 // FIXME: this is copied from WindowManagerService.
13435                 // We should get this value from the system when it
13436                 // is possible to do so.
13437                 final int KEY_REPEAT_FIRST_DELAY = 750;
13438                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13439             }
13440 
13441             // Tell mScrollCache when we should start fading. This may
13442             // extend the fade start time if one was already scheduled
13443             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13444             scrollCache.fadeStartTime = fadeStartTime;
13445             scrollCache.state = ScrollabilityCache.ON;
13446 
13447             // Schedule our fader to run, unscheduling any old ones first
13448             if (mAttachInfo != null) {
13449                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
13450                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13451             }
13452 
13453             return true;
13454         }
13455 
13456         return false;
13457     }
13458 
13459     /**
13460      * Do not invalidate views which are not visible and which are not running an animation. They
13461      * will not get drawn and they should not set dirty flags as if they will be drawn
13462      */
skipInvalidate()13463     private boolean skipInvalidate() {
13464         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13465                 (!(mParent instanceof ViewGroup) ||
13466                         !((ViewGroup) mParent).isViewTransitioning(this));
13467     }
13468 
13469     /**
13470      * Mark the area defined by dirty as needing to be drawn. If the view is
13471      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13472      * point in the future.
13473      * <p>
13474      * This must be called from a UI thread. To call from a non-UI thread, call
13475      * {@link #postInvalidate()}.
13476      * <p>
13477      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13478      * {@code dirty}.
13479      *
13480      * @param dirty the rectangle representing the bounds of the dirty region
13481      */
invalidate(Rect dirty)13482     public void invalidate(Rect dirty) {
13483         final int scrollX = mScrollX;
13484         final int scrollY = mScrollY;
13485         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13486                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13487     }
13488 
13489     /**
13490      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13491      * coordinates of the dirty rect are relative to the view. If the view is
13492      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13493      * point in the future.
13494      * <p>
13495      * This must be called from a UI thread. To call from a non-UI thread, call
13496      * {@link #postInvalidate()}.
13497      *
13498      * @param l the left position of the dirty region
13499      * @param t the top position of the dirty region
13500      * @param r the right position of the dirty region
13501      * @param b the bottom position of the dirty region
13502      */
invalidate(int l, int t, int r, int b)13503     public void invalidate(int l, int t, int r, int b) {
13504         final int scrollX = mScrollX;
13505         final int scrollY = mScrollY;
13506         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13507     }
13508 
13509     /**
13510      * Invalidate the whole view. If the view is visible,
13511      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13512      * the future.
13513      * <p>
13514      * This must be called from a UI thread. To call from a non-UI thread, call
13515      * {@link #postInvalidate()}.
13516      */
invalidate()13517     public void invalidate() {
13518         invalidate(true);
13519     }
13520 
13521     /**
13522      * This is where the invalidate() work actually happens. A full invalidate()
13523      * causes the drawing cache to be invalidated, but this function can be
13524      * called with invalidateCache set to false to skip that invalidation step
13525      * for cases that do not need it (for example, a component that remains at
13526      * the same dimensions with the same content).
13527      *
13528      * @param invalidateCache Whether the drawing cache for this view should be
13529      *            invalidated as well. This is usually true for a full
13530      *            invalidate, but may be set to false if the View's contents or
13531      *            dimensions have not changed.
13532      */
invalidate(boolean invalidateCache)13533     void invalidate(boolean invalidateCache) {
13534         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13535     }
13536 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)13537     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13538             boolean fullInvalidate) {
13539         if (mGhostView != null) {
13540             mGhostView.invalidate(true);
13541             return;
13542         }
13543 
13544         if (skipInvalidate()) {
13545             return;
13546         }
13547 
13548         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13549                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13550                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13551                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13552             if (fullInvalidate) {
13553                 mLastIsOpaque = isOpaque();
13554                 mPrivateFlags &= ~PFLAG_DRAWN;
13555             }
13556 
13557             mPrivateFlags |= PFLAG_DIRTY;
13558 
13559             if (invalidateCache) {
13560                 mPrivateFlags |= PFLAG_INVALIDATED;
13561                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13562             }
13563 
13564             // Propagate the damage rectangle to the parent view.
13565             final AttachInfo ai = mAttachInfo;
13566             final ViewParent p = mParent;
13567             if (p != null && ai != null && l < r && t < b) {
13568                 final Rect damage = ai.mTmpInvalRect;
13569                 damage.set(l, t, r, b);
13570                 p.invalidateChild(this, damage);
13571             }
13572 
13573             // Damage the entire projection receiver, if necessary.
13574             if (mBackground != null && mBackground.isProjected()) {
13575                 final View receiver = getProjectionReceiver();
13576                 if (receiver != null) {
13577                     receiver.damageInParent();
13578                 }
13579             }
13580 
13581             // Damage the entire IsolatedZVolume receiving this view's shadow.
13582             if (isHardwareAccelerated() && getZ() != 0) {
13583                 damageShadowReceiver();
13584             }
13585         }
13586     }
13587 
13588     /**
13589      * @return this view's projection receiver, or {@code null} if none exists
13590      */
getProjectionReceiver()13591     private View getProjectionReceiver() {
13592         ViewParent p = getParent();
13593         while (p != null && p instanceof View) {
13594             final View v = (View) p;
13595             if (v.isProjectionReceiver()) {
13596                 return v;
13597             }
13598             p = p.getParent();
13599         }
13600 
13601         return null;
13602     }
13603 
13604     /**
13605      * @return whether the view is a projection receiver
13606      */
isProjectionReceiver()13607     private boolean isProjectionReceiver() {
13608         return mBackground != null;
13609     }
13610 
13611     /**
13612      * Damage area of the screen that can be covered by this View's shadow.
13613      *
13614      * This method will guarantee that any changes to shadows cast by a View
13615      * are damaged on the screen for future redraw.
13616      */
damageShadowReceiver()13617     private void damageShadowReceiver() {
13618         final AttachInfo ai = mAttachInfo;
13619         if (ai != null) {
13620             ViewParent p = getParent();
13621             if (p != null && p instanceof ViewGroup) {
13622                 final ViewGroup vg = (ViewGroup) p;
13623                 vg.damageInParent();
13624             }
13625         }
13626     }
13627 
13628     /**
13629      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13630      * set any flags or handle all of the cases handled by the default invalidation methods.
13631      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13632      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13633      * walk up the hierarchy, transforming the dirty rect as necessary.
13634      *
13635      * The method also handles normal invalidation logic if display list properties are not
13636      * being used in this view. The invalidateParent and forceRedraw flags are used by that
13637      * backup approach, to handle these cases used in the various property-setting methods.
13638      *
13639      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13640      * are not being used in this view
13641      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13642      * list properties are not being used in this view
13643      */
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)13644     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13645         if (!isHardwareAccelerated()
13646                 || !mRenderNode.isValid()
13647                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13648             if (invalidateParent) {
13649                 invalidateParentCaches();
13650             }
13651             if (forceRedraw) {
13652                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13653             }
13654             invalidate(false);
13655         } else {
13656             damageInParent();
13657         }
13658         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13659             damageShadowReceiver();
13660         }
13661     }
13662 
13663     /**
13664      * Tells the parent view to damage this view's bounds.
13665      *
13666      * @hide
13667      */
damageInParent()13668     protected void damageInParent() {
13669         final AttachInfo ai = mAttachInfo;
13670         final ViewParent p = mParent;
13671         if (p != null && ai != null) {
13672             final Rect r = ai.mTmpInvalRect;
13673             r.set(0, 0, mRight - mLeft, mBottom - mTop);
13674             if (mParent instanceof ViewGroup) {
13675                 ((ViewGroup) mParent).damageChild(this, r);
13676             } else {
13677                 mParent.invalidateChild(this, r);
13678             }
13679         }
13680     }
13681 
13682     /**
13683      * Utility method to transform a given Rect by the current matrix of this view.
13684      */
transformRect(final Rect rect)13685     void transformRect(final Rect rect) {
13686         if (!getMatrix().isIdentity()) {
13687             RectF boundingRect = mAttachInfo.mTmpTransformRect;
13688             boundingRect.set(rect);
13689             getMatrix().mapRect(boundingRect);
13690             rect.set((int) Math.floor(boundingRect.left),
13691                     (int) Math.floor(boundingRect.top),
13692                     (int) Math.ceil(boundingRect.right),
13693                     (int) Math.ceil(boundingRect.bottom));
13694         }
13695     }
13696 
13697     /**
13698      * Used to indicate that the parent of this view should clear its caches. This functionality
13699      * is used to force the parent to rebuild its display list (when hardware-accelerated),
13700      * which is necessary when various parent-managed properties of the view change, such as
13701      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13702      * clears the parent caches and does not causes an invalidate event.
13703      *
13704      * @hide
13705      */
invalidateParentCaches()13706     protected void invalidateParentCaches() {
13707         if (mParent instanceof View) {
13708             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13709         }
13710     }
13711 
13712     /**
13713      * Used to indicate that the parent of this view should be invalidated. This functionality
13714      * is used to force the parent to rebuild its display list (when hardware-accelerated),
13715      * which is necessary when various parent-managed properties of the view change, such as
13716      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13717      * an invalidation event to the parent.
13718      *
13719      * @hide
13720      */
invalidateParentIfNeeded()13721     protected void invalidateParentIfNeeded() {
13722         if (isHardwareAccelerated() && mParent instanceof View) {
13723             ((View) mParent).invalidate(true);
13724         }
13725     }
13726 
13727     /**
13728      * @hide
13729      */
invalidateParentIfNeededAndWasQuickRejected()13730     protected void invalidateParentIfNeededAndWasQuickRejected() {
13731         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13732             // View was rejected last time it was drawn by its parent; this may have changed
13733             invalidateParentIfNeeded();
13734         }
13735     }
13736 
13737     /**
13738      * Indicates whether this View is opaque. An opaque View guarantees that it will
13739      * draw all the pixels overlapping its bounds using a fully opaque color.
13740      *
13741      * Subclasses of View should override this method whenever possible to indicate
13742      * whether an instance is opaque. Opaque Views are treated in a special way by
13743      * the View hierarchy, possibly allowing it to perform optimizations during
13744      * invalidate/draw passes.
13745      *
13746      * @return True if this View is guaranteed to be fully opaque, false otherwise.
13747      */
13748     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()13749     public boolean isOpaque() {
13750         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13751                 getFinalAlpha() >= 1.0f;
13752     }
13753 
13754     /**
13755      * @hide
13756      */
computeOpaqueFlags()13757     protected void computeOpaqueFlags() {
13758         // Opaque if:
13759         //   - Has a background
13760         //   - Background is opaque
13761         //   - Doesn't have scrollbars or scrollbars overlay
13762 
13763         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13764             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13765         } else {
13766             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13767         }
13768 
13769         final int flags = mViewFlags;
13770         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13771                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13772                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13773             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13774         } else {
13775             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13776         }
13777     }
13778 
13779     /**
13780      * @hide
13781      */
hasOpaqueScrollbars()13782     protected boolean hasOpaqueScrollbars() {
13783         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13784     }
13785 
13786     /**
13787      * @return A handler associated with the thread running the View. This
13788      * handler can be used to pump events in the UI events queue.
13789      */
getHandler()13790     public Handler getHandler() {
13791         final AttachInfo attachInfo = mAttachInfo;
13792         if (attachInfo != null) {
13793             return attachInfo.mHandler;
13794         }
13795         return null;
13796     }
13797 
13798     /**
13799      * Returns the queue of runnable for this view.
13800      *
13801      * @return the queue of runnables for this view
13802      */
getRunQueue()13803     private HandlerActionQueue getRunQueue() {
13804         if (mRunQueue == null) {
13805             mRunQueue = new HandlerActionQueue();
13806         }
13807         return mRunQueue;
13808     }
13809 
13810     /**
13811      * Gets the view root associated with the View.
13812      * @return The view root, or null if none.
13813      * @hide
13814      */
getViewRootImpl()13815     public ViewRootImpl getViewRootImpl() {
13816         if (mAttachInfo != null) {
13817             return mAttachInfo.mViewRootImpl;
13818         }
13819         return null;
13820     }
13821 
13822     /**
13823      * @hide
13824      */
getHardwareRenderer()13825     public ThreadedRenderer getHardwareRenderer() {
13826         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13827     }
13828 
13829     /**
13830      * <p>Causes the Runnable to be added to the message queue.
13831      * The runnable will be run on the user interface thread.</p>
13832      *
13833      * @param action The Runnable that will be executed.
13834      *
13835      * @return Returns true if the Runnable was successfully placed in to the
13836      *         message queue.  Returns false on failure, usually because the
13837      *         looper processing the message queue is exiting.
13838      *
13839      * @see #postDelayed
13840      * @see #removeCallbacks
13841      */
post(Runnable action)13842     public boolean post(Runnable action) {
13843         final AttachInfo attachInfo = mAttachInfo;
13844         if (attachInfo != null) {
13845             return attachInfo.mHandler.post(action);
13846         }
13847 
13848         // Postpone the runnable until we know on which thread it needs to run.
13849         // Assume that the runnable will be successfully placed after attach.
13850         getRunQueue().post(action);
13851         return true;
13852     }
13853 
13854     /**
13855      * <p>Causes the Runnable to be added to the message queue, to be run
13856      * after the specified amount of time elapses.
13857      * The runnable will be run on the user interface thread.</p>
13858      *
13859      * @param action The Runnable that will be executed.
13860      * @param delayMillis The delay (in milliseconds) until the Runnable
13861      *        will be executed.
13862      *
13863      * @return true if the Runnable was successfully placed in to the
13864      *         message queue.  Returns false on failure, usually because the
13865      *         looper processing the message queue is exiting.  Note that a
13866      *         result of true does not mean the Runnable will be processed --
13867      *         if the looper is quit before the delivery time of the message
13868      *         occurs then the message will be dropped.
13869      *
13870      * @see #post
13871      * @see #removeCallbacks
13872      */
postDelayed(Runnable action, long delayMillis)13873     public boolean postDelayed(Runnable action, long delayMillis) {
13874         final AttachInfo attachInfo = mAttachInfo;
13875         if (attachInfo != null) {
13876             return attachInfo.mHandler.postDelayed(action, delayMillis);
13877         }
13878 
13879         // Postpone the runnable until we know on which thread it needs to run.
13880         // Assume that the runnable will be successfully placed after attach.
13881         getRunQueue().postDelayed(action, delayMillis);
13882         return true;
13883     }
13884 
13885     /**
13886      * <p>Causes the Runnable to execute on the next animation time step.
13887      * The runnable will be run on the user interface thread.</p>
13888      *
13889      * @param action The Runnable that will be executed.
13890      *
13891      * @see #postOnAnimationDelayed
13892      * @see #removeCallbacks
13893      */
postOnAnimation(Runnable action)13894     public void postOnAnimation(Runnable action) {
13895         final AttachInfo attachInfo = mAttachInfo;
13896         if (attachInfo != null) {
13897             attachInfo.mViewRootImpl.mChoreographer.postCallback(
13898                     Choreographer.CALLBACK_ANIMATION, action, null);
13899         } else {
13900             // Postpone the runnable until we know
13901             // on which thread it needs to run.
13902             getRunQueue().post(action);
13903         }
13904     }
13905 
13906     /**
13907      * <p>Causes the Runnable to execute on the next animation time step,
13908      * after the specified amount of time elapses.
13909      * The runnable will be run on the user interface thread.</p>
13910      *
13911      * @param action The Runnable that will be executed.
13912      * @param delayMillis The delay (in milliseconds) until the Runnable
13913      *        will be executed.
13914      *
13915      * @see #postOnAnimation
13916      * @see #removeCallbacks
13917      */
postOnAnimationDelayed(Runnable action, long delayMillis)13918     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13919         final AttachInfo attachInfo = mAttachInfo;
13920         if (attachInfo != null) {
13921             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13922                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13923         } else {
13924             // Postpone the runnable until we know
13925             // on which thread it needs to run.
13926             getRunQueue().postDelayed(action, delayMillis);
13927         }
13928     }
13929 
13930     /**
13931      * <p>Removes the specified Runnable from the message queue.</p>
13932      *
13933      * @param action The Runnable to remove from the message handling queue
13934      *
13935      * @return true if this view could ask the Handler to remove the Runnable,
13936      *         false otherwise. When the returned value is true, the Runnable
13937      *         may or may not have been actually removed from the message queue
13938      *         (for instance, if the Runnable was not in the queue already.)
13939      *
13940      * @see #post
13941      * @see #postDelayed
13942      * @see #postOnAnimation
13943      * @see #postOnAnimationDelayed
13944      */
removeCallbacks(Runnable action)13945     public boolean removeCallbacks(Runnable action) {
13946         if (action != null) {
13947             final AttachInfo attachInfo = mAttachInfo;
13948             if (attachInfo != null) {
13949                 attachInfo.mHandler.removeCallbacks(action);
13950                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13951                         Choreographer.CALLBACK_ANIMATION, action, null);
13952             }
13953             getRunQueue().removeCallbacks(action);
13954         }
13955         return true;
13956     }
13957 
13958     /**
13959      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13960      * Use this to invalidate the View from a non-UI thread.</p>
13961      *
13962      * <p>This method can be invoked from outside of the UI thread
13963      * only when this View is attached to a window.</p>
13964      *
13965      * @see #invalidate()
13966      * @see #postInvalidateDelayed(long)
13967      */
postInvalidate()13968     public void postInvalidate() {
13969         postInvalidateDelayed(0);
13970     }
13971 
13972     /**
13973      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13974      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13975      *
13976      * <p>This method can be invoked from outside of the UI thread
13977      * only when this View is attached to a window.</p>
13978      *
13979      * @param left The left coordinate of the rectangle to invalidate.
13980      * @param top The top coordinate of the rectangle to invalidate.
13981      * @param right The right coordinate of the rectangle to invalidate.
13982      * @param bottom The bottom coordinate of the rectangle to invalidate.
13983      *
13984      * @see #invalidate(int, int, int, int)
13985      * @see #invalidate(Rect)
13986      * @see #postInvalidateDelayed(long, int, int, int, int)
13987      */
postInvalidate(int left, int top, int right, int bottom)13988     public void postInvalidate(int left, int top, int right, int bottom) {
13989         postInvalidateDelayed(0, left, top, right, bottom);
13990     }
13991 
13992     /**
13993      * <p>Cause an invalidate to happen on a subsequent cycle through the event
13994      * loop. Waits for the specified amount of time.</p>
13995      *
13996      * <p>This method can be invoked from outside of the UI thread
13997      * only when this View is attached to a window.</p>
13998      *
13999      * @param delayMilliseconds the duration in milliseconds to delay the
14000      *         invalidation by
14001      *
14002      * @see #invalidate()
14003      * @see #postInvalidate()
14004      */
postInvalidateDelayed(long delayMilliseconds)14005     public void postInvalidateDelayed(long delayMilliseconds) {
14006         // We try only with the AttachInfo because there's no point in invalidating
14007         // if we are not attached to our window
14008         final AttachInfo attachInfo = mAttachInfo;
14009         if (attachInfo != null) {
14010             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14011         }
14012     }
14013 
14014     /**
14015      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14016      * through the event loop. Waits for the specified amount of time.</p>
14017      *
14018      * <p>This method can be invoked from outside of the UI thread
14019      * only when this View is attached to a window.</p>
14020      *
14021      * @param delayMilliseconds the duration in milliseconds to delay the
14022      *         invalidation by
14023      * @param left The left coordinate of the rectangle to invalidate.
14024      * @param top The top coordinate of the rectangle to invalidate.
14025      * @param right The right coordinate of the rectangle to invalidate.
14026      * @param bottom The bottom coordinate of the rectangle to invalidate.
14027      *
14028      * @see #invalidate(int, int, int, int)
14029      * @see #invalidate(Rect)
14030      * @see #postInvalidate(int, int, int, int)
14031      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)14032     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14033             int right, int bottom) {
14034 
14035         // We try only with the AttachInfo because there's no point in invalidating
14036         // if we are not attached to our window
14037         final AttachInfo attachInfo = mAttachInfo;
14038         if (attachInfo != null) {
14039             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14040             info.target = this;
14041             info.left = left;
14042             info.top = top;
14043             info.right = right;
14044             info.bottom = bottom;
14045 
14046             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14047         }
14048     }
14049 
14050     /**
14051      * <p>Cause an invalidate to happen on the next animation time step, typically the
14052      * next display frame.</p>
14053      *
14054      * <p>This method can be invoked from outside of the UI thread
14055      * only when this View is attached to a window.</p>
14056      *
14057      * @see #invalidate()
14058      */
postInvalidateOnAnimation()14059     public void postInvalidateOnAnimation() {
14060         // We try only with the AttachInfo because there's no point in invalidating
14061         // if we are not attached to our window
14062         final AttachInfo attachInfo = mAttachInfo;
14063         if (attachInfo != null) {
14064             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14065         }
14066     }
14067 
14068     /**
14069      * <p>Cause an invalidate of the specified area to happen on the next animation
14070      * time step, typically the next display frame.</p>
14071      *
14072      * <p>This method can be invoked from outside of the UI thread
14073      * only when this View is attached to a window.</p>
14074      *
14075      * @param left The left coordinate of the rectangle to invalidate.
14076      * @param top The top coordinate of the rectangle to invalidate.
14077      * @param right The right coordinate of the rectangle to invalidate.
14078      * @param bottom The bottom coordinate of the rectangle to invalidate.
14079      *
14080      * @see #invalidate(int, int, int, int)
14081      * @see #invalidate(Rect)
14082      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)14083     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14084         // We try only with the AttachInfo because there's no point in invalidating
14085         // if we are not attached to our window
14086         final AttachInfo attachInfo = mAttachInfo;
14087         if (attachInfo != null) {
14088             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14089             info.target = this;
14090             info.left = left;
14091             info.top = top;
14092             info.right = right;
14093             info.bottom = bottom;
14094 
14095             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14096         }
14097     }
14098 
14099     /**
14100      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14101      * This event is sent at most once every
14102      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14103      */
postSendViewScrolledAccessibilityEventCallback()14104     private void postSendViewScrolledAccessibilityEventCallback() {
14105         if (mSendViewScrolledAccessibilityEvent == null) {
14106             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14107         }
14108         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14109             mSendViewScrolledAccessibilityEvent.mIsPending = true;
14110             postDelayed(mSendViewScrolledAccessibilityEvent,
14111                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14112         }
14113     }
14114 
14115     /**
14116      * Called by a parent to request that a child update its values for mScrollX
14117      * and mScrollY if necessary. This will typically be done if the child is
14118      * animating a scroll using a {@link android.widget.Scroller Scroller}
14119      * object.
14120      */
computeScroll()14121     public void computeScroll() {
14122     }
14123 
14124     /**
14125      * <p>Indicate whether the horizontal edges are faded when the view is
14126      * scrolled horizontally.</p>
14127      *
14128      * @return true if the horizontal edges should are faded on scroll, false
14129      *         otherwise
14130      *
14131      * @see #setHorizontalFadingEdgeEnabled(boolean)
14132      *
14133      * @attr ref android.R.styleable#View_requiresFadingEdge
14134      */
isHorizontalFadingEdgeEnabled()14135     public boolean isHorizontalFadingEdgeEnabled() {
14136         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14137     }
14138 
14139     /**
14140      * <p>Define whether the horizontal edges should be faded when this view
14141      * is scrolled horizontally.</p>
14142      *
14143      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14144      *                                    be faded when the view is scrolled
14145      *                                    horizontally
14146      *
14147      * @see #isHorizontalFadingEdgeEnabled()
14148      *
14149      * @attr ref android.R.styleable#View_requiresFadingEdge
14150      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)14151     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14152         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14153             if (horizontalFadingEdgeEnabled) {
14154                 initScrollCache();
14155             }
14156 
14157             mViewFlags ^= FADING_EDGE_HORIZONTAL;
14158         }
14159     }
14160 
14161     /**
14162      * <p>Indicate whether the vertical edges are faded when the view is
14163      * scrolled horizontally.</p>
14164      *
14165      * @return true if the vertical edges should are faded on scroll, false
14166      *         otherwise
14167      *
14168      * @see #setVerticalFadingEdgeEnabled(boolean)
14169      *
14170      * @attr ref android.R.styleable#View_requiresFadingEdge
14171      */
isVerticalFadingEdgeEnabled()14172     public boolean isVerticalFadingEdgeEnabled() {
14173         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14174     }
14175 
14176     /**
14177      * <p>Define whether the vertical edges should be faded when this view
14178      * is scrolled vertically.</p>
14179      *
14180      * @param verticalFadingEdgeEnabled true if the vertical edges should
14181      *                                  be faded when the view is scrolled
14182      *                                  vertically
14183      *
14184      * @see #isVerticalFadingEdgeEnabled()
14185      *
14186      * @attr ref android.R.styleable#View_requiresFadingEdge
14187      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)14188     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14189         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14190             if (verticalFadingEdgeEnabled) {
14191                 initScrollCache();
14192             }
14193 
14194             mViewFlags ^= FADING_EDGE_VERTICAL;
14195         }
14196     }
14197 
14198     /**
14199      * Returns the strength, or intensity, of the top faded edge. The strength is
14200      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14201      * returns 0.0 or 1.0 but no value in between.
14202      *
14203      * Subclasses should override this method to provide a smoother fade transition
14204      * when scrolling occurs.
14205      *
14206      * @return the intensity of the top fade as a float between 0.0f and 1.0f
14207      */
getTopFadingEdgeStrength()14208     protected float getTopFadingEdgeStrength() {
14209         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14210     }
14211 
14212     /**
14213      * Returns the strength, or intensity, of the bottom faded edge. The strength is
14214      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14215      * returns 0.0 or 1.0 but no value in between.
14216      *
14217      * Subclasses should override this method to provide a smoother fade transition
14218      * when scrolling occurs.
14219      *
14220      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14221      */
getBottomFadingEdgeStrength()14222     protected float getBottomFadingEdgeStrength() {
14223         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14224                 computeVerticalScrollRange() ? 1.0f : 0.0f;
14225     }
14226 
14227     /**
14228      * Returns the strength, or intensity, of the left faded edge. The strength is
14229      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14230      * returns 0.0 or 1.0 but no value in between.
14231      *
14232      * Subclasses should override this method to provide a smoother fade transition
14233      * when scrolling occurs.
14234      *
14235      * @return the intensity of the left fade as a float between 0.0f and 1.0f
14236      */
getLeftFadingEdgeStrength()14237     protected float getLeftFadingEdgeStrength() {
14238         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14239     }
14240 
14241     /**
14242      * Returns the strength, or intensity, of the right faded edge. The strength is
14243      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14244      * returns 0.0 or 1.0 but no value in between.
14245      *
14246      * Subclasses should override this method to provide a smoother fade transition
14247      * when scrolling occurs.
14248      *
14249      * @return the intensity of the right fade as a float between 0.0f and 1.0f
14250      */
getRightFadingEdgeStrength()14251     protected float getRightFadingEdgeStrength() {
14252         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14253                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
14254     }
14255 
14256     /**
14257      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14258      * scrollbar is not drawn by default.</p>
14259      *
14260      * @return true if the horizontal scrollbar should be painted, false
14261      *         otherwise
14262      *
14263      * @see #setHorizontalScrollBarEnabled(boolean)
14264      */
isHorizontalScrollBarEnabled()14265     public boolean isHorizontalScrollBarEnabled() {
14266         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14267     }
14268 
14269     /**
14270      * <p>Define whether the horizontal scrollbar should be drawn or not. The
14271      * scrollbar is not drawn by default.</p>
14272      *
14273      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14274      *                                   be painted
14275      *
14276      * @see #isHorizontalScrollBarEnabled()
14277      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)14278     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14279         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14280             mViewFlags ^= SCROLLBARS_HORIZONTAL;
14281             computeOpaqueFlags();
14282             resolvePadding();
14283         }
14284     }
14285 
14286     /**
14287      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14288      * scrollbar is not drawn by default.</p>
14289      *
14290      * @return true if the vertical scrollbar should be painted, false
14291      *         otherwise
14292      *
14293      * @see #setVerticalScrollBarEnabled(boolean)
14294      */
isVerticalScrollBarEnabled()14295     public boolean isVerticalScrollBarEnabled() {
14296         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14297     }
14298 
14299     /**
14300      * <p>Define whether the vertical scrollbar should be drawn or not. The
14301      * scrollbar is not drawn by default.</p>
14302      *
14303      * @param verticalScrollBarEnabled true if the vertical scrollbar should
14304      *                                 be painted
14305      *
14306      * @see #isVerticalScrollBarEnabled()
14307      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)14308     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14309         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14310             mViewFlags ^= SCROLLBARS_VERTICAL;
14311             computeOpaqueFlags();
14312             resolvePadding();
14313         }
14314     }
14315 
14316     /**
14317      * @hide
14318      */
recomputePadding()14319     protected void recomputePadding() {
14320         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14321     }
14322 
14323     /**
14324      * Define whether scrollbars will fade when the view is not scrolling.
14325      *
14326      * @param fadeScrollbars whether to enable fading
14327      *
14328      * @attr ref android.R.styleable#View_fadeScrollbars
14329      */
setScrollbarFadingEnabled(boolean fadeScrollbars)14330     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14331         initScrollCache();
14332         final ScrollabilityCache scrollabilityCache = mScrollCache;
14333         scrollabilityCache.fadeScrollBars = fadeScrollbars;
14334         if (fadeScrollbars) {
14335             scrollabilityCache.state = ScrollabilityCache.OFF;
14336         } else {
14337             scrollabilityCache.state = ScrollabilityCache.ON;
14338         }
14339     }
14340 
14341     /**
14342      *
14343      * Returns true if scrollbars will fade when this view is not scrolling
14344      *
14345      * @return true if scrollbar fading is enabled
14346      *
14347      * @attr ref android.R.styleable#View_fadeScrollbars
14348      */
isScrollbarFadingEnabled()14349     public boolean isScrollbarFadingEnabled() {
14350         return mScrollCache != null && mScrollCache.fadeScrollBars;
14351     }
14352 
14353     /**
14354      *
14355      * Returns the delay before scrollbars fade.
14356      *
14357      * @return the delay before scrollbars fade
14358      *
14359      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14360      */
getScrollBarDefaultDelayBeforeFade()14361     public int getScrollBarDefaultDelayBeforeFade() {
14362         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14363                 mScrollCache.scrollBarDefaultDelayBeforeFade;
14364     }
14365 
14366     /**
14367      * Define the delay before scrollbars fade.
14368      *
14369      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14370      *
14371      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14372      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)14373     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14374         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14375     }
14376 
14377     /**
14378      *
14379      * Returns the scrollbar fade duration.
14380      *
14381      * @return the scrollbar fade duration
14382      *
14383      * @attr ref android.R.styleable#View_scrollbarFadeDuration
14384      */
getScrollBarFadeDuration()14385     public int getScrollBarFadeDuration() {
14386         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14387                 mScrollCache.scrollBarFadeDuration;
14388     }
14389 
14390     /**
14391      * Define the scrollbar fade duration.
14392      *
14393      * @param scrollBarFadeDuration - the scrollbar fade duration
14394      *
14395      * @attr ref android.R.styleable#View_scrollbarFadeDuration
14396      */
setScrollBarFadeDuration(int scrollBarFadeDuration)14397     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14398         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14399     }
14400 
14401     /**
14402      *
14403      * Returns the scrollbar size.
14404      *
14405      * @return the scrollbar size
14406      *
14407      * @attr ref android.R.styleable#View_scrollbarSize
14408      */
getScrollBarSize()14409     public int getScrollBarSize() {
14410         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14411                 mScrollCache.scrollBarSize;
14412     }
14413 
14414     /**
14415      * Define the scrollbar size.
14416      *
14417      * @param scrollBarSize - the scrollbar size
14418      *
14419      * @attr ref android.R.styleable#View_scrollbarSize
14420      */
setScrollBarSize(int scrollBarSize)14421     public void setScrollBarSize(int scrollBarSize) {
14422         getScrollCache().scrollBarSize = scrollBarSize;
14423     }
14424 
14425     /**
14426      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14427      * inset. When inset, they add to the padding of the view. And the scrollbars
14428      * can be drawn inside the padding area or on the edge of the view. For example,
14429      * if a view has a background drawable and you want to draw the scrollbars
14430      * inside the padding specified by the drawable, you can use
14431      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14432      * appear at the edge of the view, ignoring the padding, then you can use
14433      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14434      * @param style the style of the scrollbars. Should be one of
14435      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14436      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14437      * @see #SCROLLBARS_INSIDE_OVERLAY
14438      * @see #SCROLLBARS_INSIDE_INSET
14439      * @see #SCROLLBARS_OUTSIDE_OVERLAY
14440      * @see #SCROLLBARS_OUTSIDE_INSET
14441      *
14442      * @attr ref android.R.styleable#View_scrollbarStyle
14443      */
setScrollBarStyle(@crollBarStyle int style)14444     public void setScrollBarStyle(@ScrollBarStyle int style) {
14445         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14446             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14447             computeOpaqueFlags();
14448             resolvePadding();
14449         }
14450     }
14451 
14452     /**
14453      * <p>Returns the current scrollbar style.</p>
14454      * @return the current scrollbar style
14455      * @see #SCROLLBARS_INSIDE_OVERLAY
14456      * @see #SCROLLBARS_INSIDE_INSET
14457      * @see #SCROLLBARS_OUTSIDE_OVERLAY
14458      * @see #SCROLLBARS_OUTSIDE_INSET
14459      *
14460      * @attr ref android.R.styleable#View_scrollbarStyle
14461      */
14462     @ViewDebug.ExportedProperty(mapping = {
14463             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14464             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14465             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14466             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14467     })
14468     @ScrollBarStyle
getScrollBarStyle()14469     public int getScrollBarStyle() {
14470         return mViewFlags & SCROLLBARS_STYLE_MASK;
14471     }
14472 
14473     /**
14474      * <p>Compute the horizontal range that the horizontal scrollbar
14475      * represents.</p>
14476      *
14477      * <p>The range is expressed in arbitrary units that must be the same as the
14478      * units used by {@link #computeHorizontalScrollExtent()} and
14479      * {@link #computeHorizontalScrollOffset()}.</p>
14480      *
14481      * <p>The default range is the drawing width of this view.</p>
14482      *
14483      * @return the total horizontal range represented by the horizontal
14484      *         scrollbar
14485      *
14486      * @see #computeHorizontalScrollExtent()
14487      * @see #computeHorizontalScrollOffset()
14488      * @see android.widget.ScrollBarDrawable
14489      */
computeHorizontalScrollRange()14490     protected int computeHorizontalScrollRange() {
14491         return getWidth();
14492     }
14493 
14494     /**
14495      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14496      * within the horizontal range. This value is used to compute the position
14497      * of the thumb within the scrollbar's track.</p>
14498      *
14499      * <p>The range is expressed in arbitrary units that must be the same as the
14500      * units used by {@link #computeHorizontalScrollRange()} and
14501      * {@link #computeHorizontalScrollExtent()}.</p>
14502      *
14503      * <p>The default offset is the scroll offset of this view.</p>
14504      *
14505      * @return the horizontal offset of the scrollbar's thumb
14506      *
14507      * @see #computeHorizontalScrollRange()
14508      * @see #computeHorizontalScrollExtent()
14509      * @see android.widget.ScrollBarDrawable
14510      */
computeHorizontalScrollOffset()14511     protected int computeHorizontalScrollOffset() {
14512         return mScrollX;
14513     }
14514 
14515     /**
14516      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14517      * within the horizontal range. This value is used to compute the length
14518      * of the thumb within the scrollbar's track.</p>
14519      *
14520      * <p>The range is expressed in arbitrary units that must be the same as the
14521      * units used by {@link #computeHorizontalScrollRange()} and
14522      * {@link #computeHorizontalScrollOffset()}.</p>
14523      *
14524      * <p>The default extent is the drawing width of this view.</p>
14525      *
14526      * @return the horizontal extent of the scrollbar's thumb
14527      *
14528      * @see #computeHorizontalScrollRange()
14529      * @see #computeHorizontalScrollOffset()
14530      * @see android.widget.ScrollBarDrawable
14531      */
computeHorizontalScrollExtent()14532     protected int computeHorizontalScrollExtent() {
14533         return getWidth();
14534     }
14535 
14536     /**
14537      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14538      *
14539      * <p>The range is expressed in arbitrary units that must be the same as the
14540      * units used by {@link #computeVerticalScrollExtent()} and
14541      * {@link #computeVerticalScrollOffset()}.</p>
14542      *
14543      * @return the total vertical range represented by the vertical scrollbar
14544      *
14545      * <p>The default range is the drawing height of this view.</p>
14546      *
14547      * @see #computeVerticalScrollExtent()
14548      * @see #computeVerticalScrollOffset()
14549      * @see android.widget.ScrollBarDrawable
14550      */
computeVerticalScrollRange()14551     protected int computeVerticalScrollRange() {
14552         return getHeight();
14553     }
14554 
14555     /**
14556      * <p>Compute the vertical offset of the vertical scrollbar's thumb
14557      * within the horizontal range. This value is used to compute the position
14558      * of the thumb within the scrollbar's track.</p>
14559      *
14560      * <p>The range is expressed in arbitrary units that must be the same as the
14561      * units used by {@link #computeVerticalScrollRange()} and
14562      * {@link #computeVerticalScrollExtent()}.</p>
14563      *
14564      * <p>The default offset is the scroll offset of this view.</p>
14565      *
14566      * @return the vertical offset of the scrollbar's thumb
14567      *
14568      * @see #computeVerticalScrollRange()
14569      * @see #computeVerticalScrollExtent()
14570      * @see android.widget.ScrollBarDrawable
14571      */
computeVerticalScrollOffset()14572     protected int computeVerticalScrollOffset() {
14573         return mScrollY;
14574     }
14575 
14576     /**
14577      * <p>Compute the vertical extent of the vertical scrollbar's thumb
14578      * within the vertical range. This value is used to compute the length
14579      * of the thumb within the scrollbar's track.</p>
14580      *
14581      * <p>The range is expressed in arbitrary units that must be the same as the
14582      * units used by {@link #computeVerticalScrollRange()} and
14583      * {@link #computeVerticalScrollOffset()}.</p>
14584      *
14585      * <p>The default extent is the drawing height of this view.</p>
14586      *
14587      * @return the vertical extent of the scrollbar's thumb
14588      *
14589      * @see #computeVerticalScrollRange()
14590      * @see #computeVerticalScrollOffset()
14591      * @see android.widget.ScrollBarDrawable
14592      */
computeVerticalScrollExtent()14593     protected int computeVerticalScrollExtent() {
14594         return getHeight();
14595     }
14596 
14597     /**
14598      * Check if this view can be scrolled horizontally in a certain direction.
14599      *
14600      * @param direction Negative to check scrolling left, positive to check scrolling right.
14601      * @return true if this view can be scrolled in the specified direction, false otherwise.
14602      */
canScrollHorizontally(int direction)14603     public boolean canScrollHorizontally(int direction) {
14604         final int offset = computeHorizontalScrollOffset();
14605         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14606         if (range == 0) return false;
14607         if (direction < 0) {
14608             return offset > 0;
14609         } else {
14610             return offset < range - 1;
14611         }
14612     }
14613 
14614     /**
14615      * Check if this view can be scrolled vertically in a certain direction.
14616      *
14617      * @param direction Negative to check scrolling up, positive to check scrolling down.
14618      * @return true if this view can be scrolled in the specified direction, false otherwise.
14619      */
canScrollVertically(int direction)14620     public boolean canScrollVertically(int direction) {
14621         final int offset = computeVerticalScrollOffset();
14622         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14623         if (range == 0) return false;
14624         if (direction < 0) {
14625             return offset > 0;
14626         } else {
14627             return offset < range - 1;
14628         }
14629     }
14630 
getScrollIndicatorBounds(@onNull Rect out)14631     void getScrollIndicatorBounds(@NonNull Rect out) {
14632         out.left = mScrollX;
14633         out.right = mScrollX + mRight - mLeft;
14634         out.top = mScrollY;
14635         out.bottom = mScrollY + mBottom - mTop;
14636     }
14637 
onDrawScrollIndicators(Canvas c)14638     private void onDrawScrollIndicators(Canvas c) {
14639         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14640             // No scroll indicators enabled.
14641             return;
14642         }
14643 
14644         final Drawable dr = mScrollIndicatorDrawable;
14645         if (dr == null) {
14646             // Scroll indicators aren't supported here.
14647             return;
14648         }
14649 
14650         final int h = dr.getIntrinsicHeight();
14651         final int w = dr.getIntrinsicWidth();
14652         final Rect rect = mAttachInfo.mTmpInvalRect;
14653         getScrollIndicatorBounds(rect);
14654 
14655         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14656             final boolean canScrollUp = canScrollVertically(-1);
14657             if (canScrollUp) {
14658                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14659                 dr.draw(c);
14660             }
14661         }
14662 
14663         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14664             final boolean canScrollDown = canScrollVertically(1);
14665             if (canScrollDown) {
14666                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14667                 dr.draw(c);
14668             }
14669         }
14670 
14671         final int leftRtl;
14672         final int rightRtl;
14673         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14674             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14675             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14676         } else {
14677             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14678             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14679         }
14680 
14681         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14682         if ((mPrivateFlags3 & leftMask) != 0) {
14683             final boolean canScrollLeft = canScrollHorizontally(-1);
14684             if (canScrollLeft) {
14685                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14686                 dr.draw(c);
14687             }
14688         }
14689 
14690         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14691         if ((mPrivateFlags3 & rightMask) != 0) {
14692             final boolean canScrollRight = canScrollHorizontally(1);
14693             if (canScrollRight) {
14694                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14695                 dr.draw(c);
14696             }
14697         }
14698     }
14699 
getHorizontalScrollBarBounds(Rect bounds)14700     private void getHorizontalScrollBarBounds(Rect bounds) {
14701         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14702         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14703                 && !isVerticalScrollBarHidden();
14704         final int size = getHorizontalScrollbarHeight();
14705         final int verticalScrollBarGap = drawVerticalScrollBar ?
14706                 getVerticalScrollbarWidth() : 0;
14707         final int width = mRight - mLeft;
14708         final int height = mBottom - mTop;
14709         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14710         bounds.left = mScrollX + (mPaddingLeft & inside);
14711         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14712         bounds.bottom = bounds.top + size;
14713     }
14714 
getVerticalScrollBarBounds(Rect bounds)14715     private void getVerticalScrollBarBounds(Rect bounds) {
14716         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14717         final int size = getVerticalScrollbarWidth();
14718         int verticalScrollbarPosition = mVerticalScrollbarPosition;
14719         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14720             verticalScrollbarPosition = isLayoutRtl() ?
14721                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14722         }
14723         final int width = mRight - mLeft;
14724         final int height = mBottom - mTop;
14725         switch (verticalScrollbarPosition) {
14726             default:
14727             case SCROLLBAR_POSITION_RIGHT:
14728                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14729                 break;
14730             case SCROLLBAR_POSITION_LEFT:
14731                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
14732                 break;
14733         }
14734         bounds.top = mScrollY + (mPaddingTop & inside);
14735         bounds.right = bounds.left + size;
14736         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14737     }
14738 
14739     /**
14740      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14741      * scrollbars are painted only if they have been awakened first.</p>
14742      *
14743      * @param canvas the canvas on which to draw the scrollbars
14744      *
14745      * @see #awakenScrollBars(int)
14746      */
onDrawScrollBars(Canvas canvas)14747     protected final void onDrawScrollBars(Canvas canvas) {
14748         // scrollbars are drawn only when the animation is running
14749         final ScrollabilityCache cache = mScrollCache;
14750         if (cache != null) {
14751 
14752             int state = cache.state;
14753 
14754             if (state == ScrollabilityCache.OFF) {
14755                 return;
14756             }
14757 
14758             boolean invalidate = false;
14759 
14760             if (state == ScrollabilityCache.FADING) {
14761                 // We're fading -- get our fade interpolation
14762                 if (cache.interpolatorValues == null) {
14763                     cache.interpolatorValues = new float[1];
14764                 }
14765 
14766                 float[] values = cache.interpolatorValues;
14767 
14768                 // Stops the animation if we're done
14769                 if (cache.scrollBarInterpolator.timeToValues(values) ==
14770                         Interpolator.Result.FREEZE_END) {
14771                     cache.state = ScrollabilityCache.OFF;
14772                 } else {
14773                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14774                 }
14775 
14776                 // This will make the scroll bars inval themselves after
14777                 // drawing. We only want this when we're fading so that
14778                 // we prevent excessive redraws
14779                 invalidate = true;
14780             } else {
14781                 // We're just on -- but we may have been fading before so
14782                 // reset alpha
14783                 cache.scrollBar.mutate().setAlpha(255);
14784             }
14785 
14786             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14787             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14788                     && !isVerticalScrollBarHidden();
14789 
14790             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14791                 final ScrollBarDrawable scrollBar = cache.scrollBar;
14792 
14793                 if (drawHorizontalScrollBar) {
14794                     scrollBar.setParameters(computeHorizontalScrollRange(),
14795                                             computeHorizontalScrollOffset(),
14796                                             computeHorizontalScrollExtent(), false);
14797                     final Rect bounds = cache.mScrollBarBounds;
14798                     getHorizontalScrollBarBounds(bounds);
14799                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14800                             bounds.right, bounds.bottom);
14801                     if (invalidate) {
14802                         invalidate(bounds);
14803                     }
14804                 }
14805 
14806                 if (drawVerticalScrollBar) {
14807                     scrollBar.setParameters(computeVerticalScrollRange(),
14808                                             computeVerticalScrollOffset(),
14809                                             computeVerticalScrollExtent(), true);
14810                     final Rect bounds = cache.mScrollBarBounds;
14811                     getVerticalScrollBarBounds(bounds);
14812                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14813                             bounds.right, bounds.bottom);
14814                     if (invalidate) {
14815                         invalidate(bounds);
14816                     }
14817                 }
14818             }
14819         }
14820     }
14821 
14822     /**
14823      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14824      * FastScroller is visible.
14825      * @return whether to temporarily hide the vertical scrollbar
14826      * @hide
14827      */
isVerticalScrollBarHidden()14828     protected boolean isVerticalScrollBarHidden() {
14829         return false;
14830     }
14831 
14832     /**
14833      * <p>Draw the horizontal scrollbar if
14834      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14835      *
14836      * @param canvas the canvas on which to draw the scrollbar
14837      * @param scrollBar the scrollbar's drawable
14838      *
14839      * @see #isHorizontalScrollBarEnabled()
14840      * @see #computeHorizontalScrollRange()
14841      * @see #computeHorizontalScrollExtent()
14842      * @see #computeHorizontalScrollOffset()
14843      * @see android.widget.ScrollBarDrawable
14844      * @hide
14845      */
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14846     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14847             int l, int t, int r, int b) {
14848         scrollBar.setBounds(l, t, r, b);
14849         scrollBar.draw(canvas);
14850     }
14851 
14852     /**
14853      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14854      * returns true.</p>
14855      *
14856      * @param canvas the canvas on which to draw the scrollbar
14857      * @param scrollBar the scrollbar's drawable
14858      *
14859      * @see #isVerticalScrollBarEnabled()
14860      * @see #computeVerticalScrollRange()
14861      * @see #computeVerticalScrollExtent()
14862      * @see #computeVerticalScrollOffset()
14863      * @see android.widget.ScrollBarDrawable
14864      * @hide
14865      */
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14866     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14867             int l, int t, int r, int b) {
14868         scrollBar.setBounds(l, t, r, b);
14869         scrollBar.draw(canvas);
14870     }
14871 
14872     /**
14873      * Implement this to do your drawing.
14874      *
14875      * @param canvas the canvas on which the background will be drawn
14876      */
onDraw(Canvas canvas)14877     protected void onDraw(Canvas canvas) {
14878     }
14879 
14880     /*
14881      * Caller is responsible for calling requestLayout if necessary.
14882      * (This allows addViewInLayout to not request a new layout.)
14883      */
assignParent(ViewParent parent)14884     void assignParent(ViewParent parent) {
14885         if (mParent == null) {
14886             mParent = parent;
14887         } else if (parent == null) {
14888             mParent = null;
14889         } else {
14890             throw new RuntimeException("view " + this + " being added, but"
14891                     + " it already has a parent");
14892         }
14893     }
14894 
14895     /**
14896      * This is called when the view is attached to a window.  At this point it
14897      * has a Surface and will start drawing.  Note that this function is
14898      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14899      * however it may be called any time before the first onDraw -- including
14900      * before or after {@link #onMeasure(int, int)}.
14901      *
14902      * @see #onDetachedFromWindow()
14903      */
14904     @CallSuper
onAttachedToWindow()14905     protected void onAttachedToWindow() {
14906         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14907             mParent.requestTransparentRegion(this);
14908         }
14909 
14910         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14911 
14912         jumpDrawablesToCurrentState();
14913 
14914         resetSubtreeAccessibilityStateChanged();
14915 
14916         // rebuild, since Outline not maintained while View is detached
14917         rebuildOutline();
14918 
14919         if (isFocused()) {
14920             InputMethodManager imm = InputMethodManager.peekInstance();
14921             if (imm != null) {
14922                 imm.focusIn(this);
14923             }
14924         }
14925     }
14926 
14927     /**
14928      * Resolve all RTL related properties.
14929      *
14930      * @return true if resolution of RTL properties has been done
14931      *
14932      * @hide
14933      */
resolveRtlPropertiesIfNeeded()14934     public boolean resolveRtlPropertiesIfNeeded() {
14935         if (!needRtlPropertiesResolution()) return false;
14936 
14937         // Order is important here: LayoutDirection MUST be resolved first
14938         if (!isLayoutDirectionResolved()) {
14939             resolveLayoutDirection();
14940             resolveLayoutParams();
14941         }
14942         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14943         if (!isTextDirectionResolved()) {
14944             resolveTextDirection();
14945         }
14946         if (!isTextAlignmentResolved()) {
14947             resolveTextAlignment();
14948         }
14949         // Should resolve Drawables before Padding because we need the layout direction of the
14950         // Drawable to correctly resolve Padding.
14951         if (!areDrawablesResolved()) {
14952             resolveDrawables();
14953         }
14954         if (!isPaddingResolved()) {
14955             resolvePadding();
14956         }
14957         onRtlPropertiesChanged(getLayoutDirection());
14958         return true;
14959     }
14960 
14961     /**
14962      * Reset resolution of all RTL related properties.
14963      *
14964      * @hide
14965      */
resetRtlProperties()14966     public void resetRtlProperties() {
14967         resetResolvedLayoutDirection();
14968         resetResolvedTextDirection();
14969         resetResolvedTextAlignment();
14970         resetResolvedPadding();
14971         resetResolvedDrawables();
14972     }
14973 
14974     /**
14975      * @see #onScreenStateChanged(int)
14976      */
dispatchScreenStateChanged(int screenState)14977     void dispatchScreenStateChanged(int screenState) {
14978         onScreenStateChanged(screenState);
14979     }
14980 
14981     /**
14982      * This method is called whenever the state of the screen this view is
14983      * attached to changes. A state change will usually occurs when the screen
14984      * turns on or off (whether it happens automatically or the user does it
14985      * manually.)
14986      *
14987      * @param screenState The new state of the screen. Can be either
14988      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14989      */
onScreenStateChanged(int screenState)14990     public void onScreenStateChanged(int screenState) {
14991     }
14992 
14993     /**
14994      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14995      */
hasRtlSupport()14996     private boolean hasRtlSupport() {
14997         return mContext.getApplicationInfo().hasRtlSupport();
14998     }
14999 
15000     /**
15001      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15002      * RTL not supported)
15003      */
isRtlCompatibilityMode()15004     private boolean isRtlCompatibilityMode() {
15005         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15006         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15007     }
15008 
15009     /**
15010      * @return true if RTL properties need resolution.
15011      *
15012      */
needRtlPropertiesResolution()15013     private boolean needRtlPropertiesResolution() {
15014         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15015     }
15016 
15017     /**
15018      * Called when any RTL property (layout direction or text direction or text alignment) has
15019      * been changed.
15020      *
15021      * Subclasses need to override this method to take care of cached information that depends on the
15022      * resolved layout direction, or to inform child views that inherit their layout direction.
15023      *
15024      * The default implementation does nothing.
15025      *
15026      * @param layoutDirection the direction of the layout
15027      *
15028      * @see #LAYOUT_DIRECTION_LTR
15029      * @see #LAYOUT_DIRECTION_RTL
15030      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)15031     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15032     }
15033 
15034     /**
15035      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15036      * that the parent directionality can and will be resolved before its children.
15037      *
15038      * @return true if resolution has been done, false otherwise.
15039      *
15040      * @hide
15041      */
resolveLayoutDirection()15042     public boolean resolveLayoutDirection() {
15043         // Clear any previous layout direction resolution
15044         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15045 
15046         if (hasRtlSupport()) {
15047             // Set resolved depending on layout direction
15048             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15049                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15050                 case LAYOUT_DIRECTION_INHERIT:
15051                     // We cannot resolve yet. LTR is by default and let the resolution happen again
15052                     // later to get the correct resolved value
15053                     if (!canResolveLayoutDirection()) return false;
15054 
15055                     // Parent has not yet resolved, LTR is still the default
15056                     try {
15057                         if (!mParent.isLayoutDirectionResolved()) return false;
15058 
15059                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15060                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15061                         }
15062                     } catch (AbstractMethodError e) {
15063                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15064                                 " does not fully implement ViewParent", e);
15065                     }
15066                     break;
15067                 case LAYOUT_DIRECTION_RTL:
15068                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15069                     break;
15070                 case LAYOUT_DIRECTION_LOCALE:
15071                     if((LAYOUT_DIRECTION_RTL ==
15072                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15073                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15074                     }
15075                     break;
15076                 default:
15077                     // Nothing to do, LTR by default
15078             }
15079         }
15080 
15081         // Set to resolved
15082         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15083         return true;
15084     }
15085 
15086     /**
15087      * Check if layout direction resolution can be done.
15088      *
15089      * @return true if layout direction resolution can be done otherwise return false.
15090      */
canResolveLayoutDirection()15091     public boolean canResolveLayoutDirection() {
15092         switch (getRawLayoutDirection()) {
15093             case LAYOUT_DIRECTION_INHERIT:
15094                 if (mParent != null) {
15095                     try {
15096                         return mParent.canResolveLayoutDirection();
15097                     } catch (AbstractMethodError e) {
15098                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15099                                 " does not fully implement ViewParent", e);
15100                     }
15101                 }
15102                 return false;
15103 
15104             default:
15105                 return true;
15106         }
15107     }
15108 
15109     /**
15110      * Reset the resolved layout direction. Layout direction will be resolved during a call to
15111      * {@link #onMeasure(int, int)}.
15112      *
15113      * @hide
15114      */
resetResolvedLayoutDirection()15115     public void resetResolvedLayoutDirection() {
15116         // Reset the current resolved bits
15117         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15118     }
15119 
15120     /**
15121      * @return true if the layout direction is inherited.
15122      *
15123      * @hide
15124      */
isLayoutDirectionInherited()15125     public boolean isLayoutDirectionInherited() {
15126         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15127     }
15128 
15129     /**
15130      * @return true if layout direction has been resolved.
15131      */
isLayoutDirectionResolved()15132     public boolean isLayoutDirectionResolved() {
15133         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15134     }
15135 
15136     /**
15137      * Return if padding has been resolved
15138      *
15139      * @hide
15140      */
isPaddingResolved()15141     boolean isPaddingResolved() {
15142         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15143     }
15144 
15145     /**
15146      * Resolves padding depending on layout direction, if applicable, and
15147      * recomputes internal padding values to adjust for scroll bars.
15148      *
15149      * @hide
15150      */
resolvePadding()15151     public void resolvePadding() {
15152         final int resolvedLayoutDirection = getLayoutDirection();
15153 
15154         if (!isRtlCompatibilityMode()) {
15155             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15156             // If start / end padding are defined, they will be resolved (hence overriding) to
15157             // left / right or right / left depending on the resolved layout direction.
15158             // If start / end padding are not defined, use the left / right ones.
15159             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15160                 Rect padding = sThreadLocal.get();
15161                 if (padding == null) {
15162                     padding = new Rect();
15163                     sThreadLocal.set(padding);
15164                 }
15165                 mBackground.getPadding(padding);
15166                 if (!mLeftPaddingDefined) {
15167                     mUserPaddingLeftInitial = padding.left;
15168                 }
15169                 if (!mRightPaddingDefined) {
15170                     mUserPaddingRightInitial = padding.right;
15171                 }
15172             }
15173             switch (resolvedLayoutDirection) {
15174                 case LAYOUT_DIRECTION_RTL:
15175                     if (mUserPaddingStart != UNDEFINED_PADDING) {
15176                         mUserPaddingRight = mUserPaddingStart;
15177                     } else {
15178                         mUserPaddingRight = mUserPaddingRightInitial;
15179                     }
15180                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
15181                         mUserPaddingLeft = mUserPaddingEnd;
15182                     } else {
15183                         mUserPaddingLeft = mUserPaddingLeftInitial;
15184                     }
15185                     break;
15186                 case LAYOUT_DIRECTION_LTR:
15187                 default:
15188                     if (mUserPaddingStart != UNDEFINED_PADDING) {
15189                         mUserPaddingLeft = mUserPaddingStart;
15190                     } else {
15191                         mUserPaddingLeft = mUserPaddingLeftInitial;
15192                     }
15193                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
15194                         mUserPaddingRight = mUserPaddingEnd;
15195                     } else {
15196                         mUserPaddingRight = mUserPaddingRightInitial;
15197                     }
15198             }
15199 
15200             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15201         }
15202 
15203         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15204         onRtlPropertiesChanged(resolvedLayoutDirection);
15205 
15206         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15207     }
15208 
15209     /**
15210      * Reset the resolved layout direction.
15211      *
15212      * @hide
15213      */
resetResolvedPadding()15214     public void resetResolvedPadding() {
15215         resetResolvedPaddingInternal();
15216     }
15217 
15218     /**
15219      * Used when we only want to reset *this* view's padding and not trigger overrides
15220      * in ViewGroup that reset children too.
15221      */
resetResolvedPaddingInternal()15222     void resetResolvedPaddingInternal() {
15223         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15224     }
15225 
15226     /**
15227      * This is called when the view is detached from a window.  At this point it
15228      * no longer has a surface for drawing.
15229      *
15230      * @see #onAttachedToWindow()
15231      */
15232     @CallSuper
onDetachedFromWindow()15233     protected void onDetachedFromWindow() {
15234     }
15235 
15236     /**
15237      * This is a framework-internal mirror of onDetachedFromWindow() that's called
15238      * after onDetachedFromWindow().
15239      *
15240      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15241      * The super method should be called at the end of the overridden method to ensure
15242      * subclasses are destroyed first
15243      *
15244      * @hide
15245      */
15246     @CallSuper
onDetachedFromWindowInternal()15247     protected void onDetachedFromWindowInternal() {
15248         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15249         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15250         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15251 
15252         removeUnsetPressCallback();
15253         removeLongPressCallback();
15254         removePerformClickCallback();
15255         removeSendViewScrolledAccessibilityEventCallback();
15256         stopNestedScroll();
15257 
15258         // Anything that started animating right before detach should already
15259         // be in its final state when re-attached.
15260         jumpDrawablesToCurrentState();
15261 
15262         destroyDrawingCache();
15263 
15264         cleanupDraw();
15265         mCurrentAnimation = null;
15266     }
15267 
cleanupDraw()15268     private void cleanupDraw() {
15269         resetDisplayList();
15270         if (mAttachInfo != null) {
15271             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15272         }
15273     }
15274 
invalidateInheritedLayoutMode(int layoutModeOfRoot)15275     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15276     }
15277 
15278     /**
15279      * @return The number of times this view has been attached to a window
15280      */
getWindowAttachCount()15281     protected int getWindowAttachCount() {
15282         return mWindowAttachCount;
15283     }
15284 
15285     /**
15286      * Retrieve a unique token identifying the window this view is attached to.
15287      * @return Return the window's token for use in
15288      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15289      */
getWindowToken()15290     public IBinder getWindowToken() {
15291         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15292     }
15293 
15294     /**
15295      * Retrieve the {@link WindowId} for the window this view is
15296      * currently attached to.
15297      */
getWindowId()15298     public WindowId getWindowId() {
15299         if (mAttachInfo == null) {
15300             return null;
15301         }
15302         if (mAttachInfo.mWindowId == null) {
15303             try {
15304                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15305                         mAttachInfo.mWindowToken);
15306                 mAttachInfo.mWindowId = new WindowId(
15307                         mAttachInfo.mIWindowId);
15308             } catch (RemoteException e) {
15309             }
15310         }
15311         return mAttachInfo.mWindowId;
15312     }
15313 
15314     /**
15315      * Retrieve a unique token identifying the top-level "real" window of
15316      * the window that this view is attached to.  That is, this is like
15317      * {@link #getWindowToken}, except if the window this view in is a panel
15318      * window (attached to another containing window), then the token of
15319      * the containing window is returned instead.
15320      *
15321      * @return Returns the associated window token, either
15322      * {@link #getWindowToken()} or the containing window's token.
15323      */
getApplicationWindowToken()15324     public IBinder getApplicationWindowToken() {
15325         AttachInfo ai = mAttachInfo;
15326         if (ai != null) {
15327             IBinder appWindowToken = ai.mPanelParentWindowToken;
15328             if (appWindowToken == null) {
15329                 appWindowToken = ai.mWindowToken;
15330             }
15331             return appWindowToken;
15332         }
15333         return null;
15334     }
15335 
15336     /**
15337      * Gets the logical display to which the view's window has been attached.
15338      *
15339      * @return The logical display, or null if the view is not currently attached to a window.
15340      */
getDisplay()15341     public Display getDisplay() {
15342         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15343     }
15344 
15345     /**
15346      * Retrieve private session object this view hierarchy is using to
15347      * communicate with the window manager.
15348      * @return the session object to communicate with the window manager
15349      */
getWindowSession()15350     /*package*/ IWindowSession getWindowSession() {
15351         return mAttachInfo != null ? mAttachInfo.mSession : null;
15352     }
15353 
15354     /**
15355      * Return the visibility value of the least visible component passed.
15356      */
combineVisibility(int vis1, int vis2)15357     int combineVisibility(int vis1, int vis2) {
15358         // This works because VISIBLE < INVISIBLE < GONE.
15359         return Math.max(vis1, vis2);
15360     }
15361 
15362     /**
15363      * @param info the {@link android.view.View.AttachInfo} to associated with
15364      *        this view
15365      */
dispatchAttachedToWindow(AttachInfo info, int visibility)15366     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15367         mAttachInfo = info;
15368         if (mOverlay != null) {
15369             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15370         }
15371         mWindowAttachCount++;
15372         // We will need to evaluate the drawable state at least once.
15373         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15374         if (mFloatingTreeObserver != null) {
15375             info.mTreeObserver.merge(mFloatingTreeObserver);
15376             mFloatingTreeObserver = null;
15377         }
15378 
15379         registerPendingFrameMetricsObservers();
15380 
15381         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15382             mAttachInfo.mScrollContainers.add(this);
15383             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15384         }
15385         // Transfer all pending runnables.
15386         if (mRunQueue != null) {
15387             mRunQueue.executeActions(info.mHandler);
15388             mRunQueue = null;
15389         }
15390         performCollectViewAttributes(mAttachInfo, visibility);
15391         onAttachedToWindow();
15392 
15393         ListenerInfo li = mListenerInfo;
15394         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15395                 li != null ? li.mOnAttachStateChangeListeners : null;
15396         if (listeners != null && listeners.size() > 0) {
15397             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15398             // perform the dispatching. The iterator is a safe guard against listeners that
15399             // could mutate the list by calling the various add/remove methods. This prevents
15400             // the array from being modified while we iterate it.
15401             for (OnAttachStateChangeListener listener : listeners) {
15402                 listener.onViewAttachedToWindow(this);
15403             }
15404         }
15405 
15406         int vis = info.mWindowVisibility;
15407         if (vis != GONE) {
15408             onWindowVisibilityChanged(vis);
15409             if (isShown()) {
15410                 // Calling onVisibilityChanged directly here since the subtree will also
15411                 // receive dispatchAttachedToWindow and this same call
15412                 onVisibilityAggregated(vis == VISIBLE);
15413             }
15414         }
15415 
15416         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15417         // As all views in the subtree will already receive dispatchAttachedToWindow
15418         // traversing the subtree again here is not desired.
15419         onVisibilityChanged(this, visibility);
15420 
15421         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15422             // If nobody has evaluated the drawable state yet, then do it now.
15423             refreshDrawableState();
15424         }
15425         needGlobalAttributesUpdate(false);
15426     }
15427 
dispatchDetachedFromWindow()15428     void dispatchDetachedFromWindow() {
15429         AttachInfo info = mAttachInfo;
15430         if (info != null) {
15431             int vis = info.mWindowVisibility;
15432             if (vis != GONE) {
15433                 onWindowVisibilityChanged(GONE);
15434                 if (isShown()) {
15435                     // Invoking onVisibilityAggregated directly here since the subtree
15436                     // will also receive detached from window
15437                     onVisibilityAggregated(false);
15438                 }
15439             }
15440         }
15441 
15442         onDetachedFromWindow();
15443         onDetachedFromWindowInternal();
15444 
15445         InputMethodManager imm = InputMethodManager.peekInstance();
15446         if (imm != null) {
15447             imm.onViewDetachedFromWindow(this);
15448         }
15449 
15450         ListenerInfo li = mListenerInfo;
15451         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15452                 li != null ? li.mOnAttachStateChangeListeners : null;
15453         if (listeners != null && listeners.size() > 0) {
15454             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15455             // perform the dispatching. The iterator is a safe guard against listeners that
15456             // could mutate the list by calling the various add/remove methods. This prevents
15457             // the array from being modified while we iterate it.
15458             for (OnAttachStateChangeListener listener : listeners) {
15459                 listener.onViewDetachedFromWindow(this);
15460             }
15461         }
15462 
15463         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15464             mAttachInfo.mScrollContainers.remove(this);
15465             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15466         }
15467 
15468         mAttachInfo = null;
15469         if (mOverlay != null) {
15470             mOverlay.getOverlayView().dispatchDetachedFromWindow();
15471         }
15472     }
15473 
15474     /**
15475      * Cancel any deferred high-level input events that were previously posted to the event queue.
15476      *
15477      * <p>Many views post high-level events such as click handlers to the event queue
15478      * to run deferred in order to preserve a desired user experience - clearing visible
15479      * pressed states before executing, etc. This method will abort any events of this nature
15480      * that are currently in flight.</p>
15481      *
15482      * <p>Custom views that generate their own high-level deferred input events should override
15483      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15484      *
15485      * <p>This will also cancel pending input events for any child views.</p>
15486      *
15487      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15488      * This will not impact newer events posted after this call that may occur as a result of
15489      * lower-level input events still waiting in the queue. If you are trying to prevent
15490      * double-submitted  events for the duration of some sort of asynchronous transaction
15491      * you should also take other steps to protect against unexpected double inputs e.g. calling
15492      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15493      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15494      */
cancelPendingInputEvents()15495     public final void cancelPendingInputEvents() {
15496         dispatchCancelPendingInputEvents();
15497     }
15498 
15499     /**
15500      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15501      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15502      */
dispatchCancelPendingInputEvents()15503     void dispatchCancelPendingInputEvents() {
15504         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15505         onCancelPendingInputEvents();
15506         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15507             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15508                     " did not call through to super.onCancelPendingInputEvents()");
15509         }
15510     }
15511 
15512     /**
15513      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15514      * a parent view.
15515      *
15516      * <p>This method is responsible for removing any pending high-level input events that were
15517      * posted to the event queue to run later. Custom view classes that post their own deferred
15518      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15519      * {@link android.os.Handler} should override this method, call
15520      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15521      * </p>
15522      */
onCancelPendingInputEvents()15523     public void onCancelPendingInputEvents() {
15524         removePerformClickCallback();
15525         cancelLongPress();
15526         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15527     }
15528 
15529     /**
15530      * Store this view hierarchy's frozen state into the given container.
15531      *
15532      * @param container The SparseArray in which to save the view's state.
15533      *
15534      * @see #restoreHierarchyState(android.util.SparseArray)
15535      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15536      * @see #onSaveInstanceState()
15537      */
saveHierarchyState(SparseArray<Parcelable> container)15538     public void saveHierarchyState(SparseArray<Parcelable> container) {
15539         dispatchSaveInstanceState(container);
15540     }
15541 
15542     /**
15543      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15544      * this view and its children. May be overridden to modify how freezing happens to a
15545      * view's children; for example, some views may want to not store state for their children.
15546      *
15547      * @param container The SparseArray in which to save the view's state.
15548      *
15549      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15550      * @see #saveHierarchyState(android.util.SparseArray)
15551      * @see #onSaveInstanceState()
15552      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)15553     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15554         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15555             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15556             Parcelable state = onSaveInstanceState();
15557             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15558                 throw new IllegalStateException(
15559                         "Derived class did not call super.onSaveInstanceState()");
15560             }
15561             if (state != null) {
15562                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15563                 // + ": " + state);
15564                 container.put(mID, state);
15565             }
15566         }
15567     }
15568 
15569     /**
15570      * Hook allowing a view to generate a representation of its internal state
15571      * that can later be used to create a new instance with that same state.
15572      * This state should only contain information that is not persistent or can
15573      * not be reconstructed later. For example, you will never store your
15574      * current position on screen because that will be computed again when a
15575      * new instance of the view is placed in its view hierarchy.
15576      * <p>
15577      * Some examples of things you may store here: the current cursor position
15578      * in a text view (but usually not the text itself since that is stored in a
15579      * content provider or other persistent storage), the currently selected
15580      * item in a list view.
15581      *
15582      * @return Returns a Parcelable object containing the view's current dynamic
15583      *         state, or null if there is nothing interesting to save. The
15584      *         default implementation returns null.
15585      * @see #onRestoreInstanceState(android.os.Parcelable)
15586      * @see #saveHierarchyState(android.util.SparseArray)
15587      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15588      * @see #setSaveEnabled(boolean)
15589      */
15590     @CallSuper
onSaveInstanceState()15591     protected Parcelable onSaveInstanceState() {
15592         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15593         if (mStartActivityRequestWho != null) {
15594             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15595             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15596             return state;
15597         }
15598         return BaseSavedState.EMPTY_STATE;
15599     }
15600 
15601     /**
15602      * Restore this view hierarchy's frozen state from the given container.
15603      *
15604      * @param container The SparseArray which holds previously frozen states.
15605      *
15606      * @see #saveHierarchyState(android.util.SparseArray)
15607      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15608      * @see #onRestoreInstanceState(android.os.Parcelable)
15609      */
restoreHierarchyState(SparseArray<Parcelable> container)15610     public void restoreHierarchyState(SparseArray<Parcelable> container) {
15611         dispatchRestoreInstanceState(container);
15612     }
15613 
15614     /**
15615      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15616      * state for this view and its children. May be overridden to modify how restoring
15617      * happens to a view's children; for example, some views may want to not store state
15618      * for their children.
15619      *
15620      * @param container The SparseArray which holds previously saved state.
15621      *
15622      * @see #dispatchSaveInstanceState(android.util.SparseArray)
15623      * @see #restoreHierarchyState(android.util.SparseArray)
15624      * @see #onRestoreInstanceState(android.os.Parcelable)
15625      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)15626     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15627         if (mID != NO_ID) {
15628             Parcelable state = container.get(mID);
15629             if (state != null) {
15630                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15631                 // + ": " + state);
15632                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15633                 onRestoreInstanceState(state);
15634                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15635                     throw new IllegalStateException(
15636                             "Derived class did not call super.onRestoreInstanceState()");
15637                 }
15638             }
15639         }
15640     }
15641 
15642     /**
15643      * Hook allowing a view to re-apply a representation of its internal state that had previously
15644      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15645      * null state.
15646      *
15647      * @param state The frozen state that had previously been returned by
15648      *        {@link #onSaveInstanceState}.
15649      *
15650      * @see #onSaveInstanceState()
15651      * @see #restoreHierarchyState(android.util.SparseArray)
15652      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15653      */
15654     @CallSuper
onRestoreInstanceState(Parcelable state)15655     protected void onRestoreInstanceState(Parcelable state) {
15656         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15657         if (state != null && !(state instanceof AbsSavedState)) {
15658             throw new IllegalArgumentException("Wrong state class, expecting View State but "
15659                     + "received " + state.getClass().toString() + " instead. This usually happens "
15660                     + "when two views of different type have the same id in the same hierarchy. "
15661                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15662                     + "other views do not use the same id.");
15663         }
15664         if (state != null && state instanceof BaseSavedState) {
15665             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15666         }
15667     }
15668 
15669     /**
15670      * <p>Return the time at which the drawing of the view hierarchy started.</p>
15671      *
15672      * @return the drawing start time in milliseconds
15673      */
getDrawingTime()15674     public long getDrawingTime() {
15675         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15676     }
15677 
15678     /**
15679      * <p>Enables or disables the duplication of the parent's state into this view. When
15680      * duplication is enabled, this view gets its drawable state from its parent rather
15681      * than from its own internal properties.</p>
15682      *
15683      * <p>Note: in the current implementation, setting this property to true after the
15684      * view was added to a ViewGroup might have no effect at all. This property should
15685      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15686      *
15687      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15688      * property is enabled, an exception will be thrown.</p>
15689      *
15690      * <p>Note: if the child view uses and updates additional states which are unknown to the
15691      * parent, these states should not be affected by this method.</p>
15692      *
15693      * @param enabled True to enable duplication of the parent's drawable state, false
15694      *                to disable it.
15695      *
15696      * @see #getDrawableState()
15697      * @see #isDuplicateParentStateEnabled()
15698      */
setDuplicateParentStateEnabled(boolean enabled)15699     public void setDuplicateParentStateEnabled(boolean enabled) {
15700         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15701     }
15702 
15703     /**
15704      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15705      *
15706      * @return True if this view's drawable state is duplicated from the parent,
15707      *         false otherwise
15708      *
15709      * @see #getDrawableState()
15710      * @see #setDuplicateParentStateEnabled(boolean)
15711      */
isDuplicateParentStateEnabled()15712     public boolean isDuplicateParentStateEnabled() {
15713         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15714     }
15715 
15716     /**
15717      * <p>Specifies the type of layer backing this view. The layer can be
15718      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15719      * {@link #LAYER_TYPE_HARDWARE}.</p>
15720      *
15721      * <p>A layer is associated with an optional {@link android.graphics.Paint}
15722      * instance that controls how the layer is composed on screen. The following
15723      * properties of the paint are taken into account when composing the layer:</p>
15724      * <ul>
15725      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15726      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15727      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15728      * </ul>
15729      *
15730      * <p>If this view has an alpha value set to < 1.0 by calling
15731      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15732      * by this view's alpha value.</p>
15733      *
15734      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15735      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15736      * for more information on when and how to use layers.</p>
15737      *
15738      * @param layerType The type of layer to use with this view, must be one of
15739      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15740      *        {@link #LAYER_TYPE_HARDWARE}
15741      * @param paint The paint used to compose the layer. This argument is optional
15742      *        and can be null. It is ignored when the layer type is
15743      *        {@link #LAYER_TYPE_NONE}
15744      *
15745      * @see #getLayerType()
15746      * @see #LAYER_TYPE_NONE
15747      * @see #LAYER_TYPE_SOFTWARE
15748      * @see #LAYER_TYPE_HARDWARE
15749      * @see #setAlpha(float)
15750      *
15751      * @attr ref android.R.styleable#View_layerType
15752      */
setLayerType(int layerType, @Nullable Paint paint)15753     public void setLayerType(int layerType, @Nullable Paint paint) {
15754         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15755             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15756                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15757         }
15758 
15759         boolean typeChanged = mRenderNode.setLayerType(layerType);
15760 
15761         if (!typeChanged) {
15762             setLayerPaint(paint);
15763             return;
15764         }
15765 
15766         if (layerType != LAYER_TYPE_SOFTWARE) {
15767             // Destroy any previous software drawing cache if present
15768             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15769             // drawing cache created in View#draw when drawing to a SW canvas.
15770             destroyDrawingCache();
15771         }
15772 
15773         mLayerType = layerType;
15774         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15775         mRenderNode.setLayerPaint(mLayerPaint);
15776 
15777         // draw() behaves differently if we are on a layer, so we need to
15778         // invalidate() here
15779         invalidateParentCaches();
15780         invalidate(true);
15781     }
15782 
15783     /**
15784      * Updates the {@link Paint} object used with the current layer (used only if the current
15785      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15786      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15787      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15788      * ensure that the view gets redrawn immediately.
15789      *
15790      * <p>A layer is associated with an optional {@link android.graphics.Paint}
15791      * instance that controls how the layer is composed on screen. The following
15792      * properties of the paint are taken into account when composing the layer:</p>
15793      * <ul>
15794      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15795      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15796      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15797      * </ul>
15798      *
15799      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15800      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15801      *
15802      * @param paint The paint used to compose the layer. This argument is optional
15803      *        and can be null. It is ignored when the layer type is
15804      *        {@link #LAYER_TYPE_NONE}
15805      *
15806      * @see #setLayerType(int, android.graphics.Paint)
15807      */
setLayerPaint(@ullable Paint paint)15808     public void setLayerPaint(@Nullable Paint paint) {
15809         int layerType = getLayerType();
15810         if (layerType != LAYER_TYPE_NONE) {
15811             mLayerPaint = paint;
15812             if (layerType == LAYER_TYPE_HARDWARE) {
15813                 if (mRenderNode.setLayerPaint(paint)) {
15814                     invalidateViewProperty(false, false);
15815                 }
15816             } else {
15817                 invalidate();
15818             }
15819         }
15820     }
15821 
15822     /**
15823      * Indicates what type of layer is currently associated with this view. By default
15824      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15825      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15826      * for more information on the different types of layers.
15827      *
15828      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15829      *         {@link #LAYER_TYPE_HARDWARE}
15830      *
15831      * @see #setLayerType(int, android.graphics.Paint)
15832      * @see #buildLayer()
15833      * @see #LAYER_TYPE_NONE
15834      * @see #LAYER_TYPE_SOFTWARE
15835      * @see #LAYER_TYPE_HARDWARE
15836      */
getLayerType()15837     public int getLayerType() {
15838         return mLayerType;
15839     }
15840 
15841     /**
15842      * Forces this view's layer to be created and this view to be rendered
15843      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15844      * invoking this method will have no effect.
15845      *
15846      * This method can for instance be used to render a view into its layer before
15847      * starting an animation. If this view is complex, rendering into the layer
15848      * before starting the animation will avoid skipping frames.
15849      *
15850      * @throws IllegalStateException If this view is not attached to a window
15851      *
15852      * @see #setLayerType(int, android.graphics.Paint)
15853      */
buildLayer()15854     public void buildLayer() {
15855         if (mLayerType == LAYER_TYPE_NONE) return;
15856 
15857         final AttachInfo attachInfo = mAttachInfo;
15858         if (attachInfo == null) {
15859             throw new IllegalStateException("This view must be attached to a window first");
15860         }
15861 
15862         if (getWidth() == 0 || getHeight() == 0) {
15863             return;
15864         }
15865 
15866         switch (mLayerType) {
15867             case LAYER_TYPE_HARDWARE:
15868                 updateDisplayListIfDirty();
15869                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15870                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15871                 }
15872                 break;
15873             case LAYER_TYPE_SOFTWARE:
15874                 buildDrawingCache(true);
15875                 break;
15876         }
15877     }
15878 
15879     /**
15880      * Destroys all hardware rendering resources. This method is invoked
15881      * when the system needs to reclaim resources. Upon execution of this
15882      * method, you should free any OpenGL resources created by the view.
15883      *
15884      * Note: you <strong>must</strong> call
15885      * <code>super.destroyHardwareResources()</code> when overriding
15886      * this method.
15887      *
15888      * @hide
15889      */
15890     @CallSuper
destroyHardwareResources()15891     protected void destroyHardwareResources() {
15892         // Although the Layer will be destroyed by RenderNode, we want to release
15893         // the staging display list, which is also a signal to RenderNode that it's
15894         // safe to free its copy of the display list as it knows that we will
15895         // push an updated DisplayList if we try to draw again
15896         resetDisplayList();
15897     }
15898 
15899     /**
15900      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15901      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15902      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15903      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15904      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15905      * null.</p>
15906      *
15907      * <p>Enabling the drawing cache is similar to
15908      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15909      * acceleration is turned off. When hardware acceleration is turned on, enabling the
15910      * drawing cache has no effect on rendering because the system uses a different mechanism
15911      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15912      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15913      * for information on how to enable software and hardware layers.</p>
15914      *
15915      * <p>This API can be used to manually generate
15916      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15917      * {@link #getDrawingCache()}.</p>
15918      *
15919      * @param enabled true to enable the drawing cache, false otherwise
15920      *
15921      * @see #isDrawingCacheEnabled()
15922      * @see #getDrawingCache()
15923      * @see #buildDrawingCache()
15924      * @see #setLayerType(int, android.graphics.Paint)
15925      */
setDrawingCacheEnabled(boolean enabled)15926     public void setDrawingCacheEnabled(boolean enabled) {
15927         mCachingFailed = false;
15928         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15929     }
15930 
15931     /**
15932      * <p>Indicates whether the drawing cache is enabled for this view.</p>
15933      *
15934      * @return true if the drawing cache is enabled
15935      *
15936      * @see #setDrawingCacheEnabled(boolean)
15937      * @see #getDrawingCache()
15938      */
15939     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()15940     public boolean isDrawingCacheEnabled() {
15941         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15942     }
15943 
15944     /**
15945      * Debugging utility which recursively outputs the dirty state of a view and its
15946      * descendants.
15947      *
15948      * @hide
15949      */
15950     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)15951     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15952         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15953                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15954                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15955                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15956         if (clear) {
15957             mPrivateFlags &= clearMask;
15958         }
15959         if (this instanceof ViewGroup) {
15960             ViewGroup parent = (ViewGroup) this;
15961             final int count = parent.getChildCount();
15962             for (int i = 0; i < count; i++) {
15963                 final View child = parent.getChildAt(i);
15964                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
15965             }
15966         }
15967     }
15968 
15969     /**
15970      * This method is used by ViewGroup to cause its children to restore or recreate their
15971      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15972      * to recreate its own display list, which would happen if it went through the normal
15973      * draw/dispatchDraw mechanisms.
15974      *
15975      * @hide
15976      */
dispatchGetDisplayList()15977     protected void dispatchGetDisplayList() {}
15978 
15979     /**
15980      * A view that is not attached or hardware accelerated cannot create a display list.
15981      * This method checks these conditions and returns the appropriate result.
15982      *
15983      * @return true if view has the ability to create a display list, false otherwise.
15984      *
15985      * @hide
15986      */
canHaveDisplayList()15987     public boolean canHaveDisplayList() {
15988         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15989     }
15990 
15991     /**
15992      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15993      * @hide
15994      */
15995     @NonNull
updateDisplayListIfDirty()15996     public RenderNode updateDisplayListIfDirty() {
15997         final RenderNode renderNode = mRenderNode;
15998         if (!canHaveDisplayList()) {
15999             // can't populate RenderNode, don't try
16000             return renderNode;
16001         }
16002 
16003         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16004                 || !renderNode.isValid()
16005                 || (mRecreateDisplayList)) {
16006             // Don't need to recreate the display list, just need to tell our
16007             // children to restore/recreate theirs
16008             if (renderNode.isValid()
16009                     && !mRecreateDisplayList) {
16010                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16011                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16012                 dispatchGetDisplayList();
16013 
16014                 return renderNode; // no work needed
16015             }
16016 
16017             // If we got here, we're recreating it. Mark it as such to ensure that
16018             // we copy in child display lists into ours in drawChild()
16019             mRecreateDisplayList = true;
16020 
16021             int width = mRight - mLeft;
16022             int height = mBottom - mTop;
16023             int layerType = getLayerType();
16024 
16025             final DisplayListCanvas canvas = renderNode.start(width, height);
16026             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16027 
16028             try {
16029                 if (layerType == LAYER_TYPE_SOFTWARE) {
16030                     buildDrawingCache(true);
16031                     Bitmap cache = getDrawingCache(true);
16032                     if (cache != null) {
16033                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16034                     }
16035                 } else {
16036                     computeScroll();
16037 
16038                     canvas.translate(-mScrollX, -mScrollY);
16039                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16040                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16041 
16042                     // Fast path for layouts with no backgrounds
16043                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16044                         dispatchDraw(canvas);
16045                         if (mOverlay != null && !mOverlay.isEmpty()) {
16046                             mOverlay.getOverlayView().draw(canvas);
16047                         }
16048                     } else {
16049                         draw(canvas);
16050                     }
16051                 }
16052             } finally {
16053                 renderNode.end(canvas);
16054                 setDisplayListProperties(renderNode);
16055             }
16056         } else {
16057             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16058             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16059         }
16060         return renderNode;
16061     }
16062 
resetDisplayList()16063     private void resetDisplayList() {
16064         if (mRenderNode.isValid()) {
16065             mRenderNode.discardDisplayList();
16066         }
16067 
16068         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16069             mBackgroundRenderNode.discardDisplayList();
16070         }
16071     }
16072 
16073     /**
16074      * Called when the passed RenderNode is removed from the draw tree
16075      * @hide
16076      */
onRenderNodeDetached(RenderNode renderNode)16077     public void onRenderNodeDetached(RenderNode renderNode) {
16078     }
16079 
16080     /**
16081      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16082      *
16083      * @return A non-scaled bitmap representing this view or null if cache is disabled.
16084      *
16085      * @see #getDrawingCache(boolean)
16086      */
getDrawingCache()16087     public Bitmap getDrawingCache() {
16088         return getDrawingCache(false);
16089     }
16090 
16091     /**
16092      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16093      * is null when caching is disabled. If caching is enabled and the cache is not ready,
16094      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16095      * draw from the cache when the cache is enabled. To benefit from the cache, you must
16096      * request the drawing cache by calling this method and draw it on screen if the
16097      * returned bitmap is not null.</p>
16098      *
16099      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16100      * this method will create a bitmap of the same size as this view. Because this bitmap
16101      * will be drawn scaled by the parent ViewGroup, the result on screen might show
16102      * scaling artifacts. To avoid such artifacts, you should call this method by setting
16103      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16104      * size than the view. This implies that your application must be able to handle this
16105      * size.</p>
16106      *
16107      * @param autoScale Indicates whether the generated bitmap should be scaled based on
16108      *        the current density of the screen when the application is in compatibility
16109      *        mode.
16110      *
16111      * @return A bitmap representing this view or null if cache is disabled.
16112      *
16113      * @see #setDrawingCacheEnabled(boolean)
16114      * @see #isDrawingCacheEnabled()
16115      * @see #buildDrawingCache(boolean)
16116      * @see #destroyDrawingCache()
16117      */
getDrawingCache(boolean autoScale)16118     public Bitmap getDrawingCache(boolean autoScale) {
16119         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16120             return null;
16121         }
16122         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16123             buildDrawingCache(autoScale);
16124         }
16125         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16126     }
16127 
16128     /**
16129      * <p>Frees the resources used by the drawing cache. If you call
16130      * {@link #buildDrawingCache()} manually without calling
16131      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16132      * should cleanup the cache with this method afterwards.</p>
16133      *
16134      * @see #setDrawingCacheEnabled(boolean)
16135      * @see #buildDrawingCache()
16136      * @see #getDrawingCache()
16137      */
destroyDrawingCache()16138     public void destroyDrawingCache() {
16139         if (mDrawingCache != null) {
16140             mDrawingCache.recycle();
16141             mDrawingCache = null;
16142         }
16143         if (mUnscaledDrawingCache != null) {
16144             mUnscaledDrawingCache.recycle();
16145             mUnscaledDrawingCache = null;
16146         }
16147     }
16148 
16149     /**
16150      * Setting a solid background color for the drawing cache's bitmaps will improve
16151      * performance and memory usage. Note, though that this should only be used if this
16152      * view will always be drawn on top of a solid color.
16153      *
16154      * @param color The background color to use for the drawing cache's bitmap
16155      *
16156      * @see #setDrawingCacheEnabled(boolean)
16157      * @see #buildDrawingCache()
16158      * @see #getDrawingCache()
16159      */
setDrawingCacheBackgroundColor(@olorInt int color)16160     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16161         if (color != mDrawingCacheBackgroundColor) {
16162             mDrawingCacheBackgroundColor = color;
16163             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16164         }
16165     }
16166 
16167     /**
16168      * @see #setDrawingCacheBackgroundColor(int)
16169      *
16170      * @return The background color to used for the drawing cache's bitmap
16171      */
16172     @ColorInt
getDrawingCacheBackgroundColor()16173     public int getDrawingCacheBackgroundColor() {
16174         return mDrawingCacheBackgroundColor;
16175     }
16176 
16177     /**
16178      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16179      *
16180      * @see #buildDrawingCache(boolean)
16181      */
buildDrawingCache()16182     public void buildDrawingCache() {
16183         buildDrawingCache(false);
16184     }
16185 
16186     /**
16187      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16188      *
16189      * <p>If you call {@link #buildDrawingCache()} manually without calling
16190      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16191      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16192      *
16193      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16194      * this method will create a bitmap of the same size as this view. Because this bitmap
16195      * will be drawn scaled by the parent ViewGroup, the result on screen might show
16196      * scaling artifacts. To avoid such artifacts, you should call this method by setting
16197      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16198      * size than the view. This implies that your application must be able to handle this
16199      * size.</p>
16200      *
16201      * <p>You should avoid calling this method when hardware acceleration is enabled. If
16202      * you do not need the drawing cache bitmap, calling this method will increase memory
16203      * usage and cause the view to be rendered in software once, thus negatively impacting
16204      * performance.</p>
16205      *
16206      * @see #getDrawingCache()
16207      * @see #destroyDrawingCache()
16208      */
buildDrawingCache(boolean autoScale)16209     public void buildDrawingCache(boolean autoScale) {
16210         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16211                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
16212             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16213                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16214                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16215             }
16216             try {
16217                 buildDrawingCacheImpl(autoScale);
16218             } finally {
16219                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16220             }
16221         }
16222     }
16223 
16224     /**
16225      * private, internal implementation of buildDrawingCache, used to enable tracing
16226      */
buildDrawingCacheImpl(boolean autoScale)16227     private void buildDrawingCacheImpl(boolean autoScale) {
16228         mCachingFailed = false;
16229 
16230         int width = mRight - mLeft;
16231         int height = mBottom - mTop;
16232 
16233         final AttachInfo attachInfo = mAttachInfo;
16234         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16235 
16236         if (autoScale && scalingRequired) {
16237             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16238             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16239         }
16240 
16241         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16242         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16243         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16244 
16245         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16246         final long drawingCacheSize =
16247                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16248         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16249             if (width > 0 && height > 0) {
16250                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16251                         + " too large to fit into a software layer (or drawing cache), needs "
16252                         + projectedBitmapSize + " bytes, only "
16253                         + drawingCacheSize + " available");
16254             }
16255             destroyDrawingCache();
16256             mCachingFailed = true;
16257             return;
16258         }
16259 
16260         boolean clear = true;
16261         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16262 
16263         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16264             Bitmap.Config quality;
16265             if (!opaque) {
16266                 // Never pick ARGB_4444 because it looks awful
16267                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16268                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16269                     case DRAWING_CACHE_QUALITY_AUTO:
16270                     case DRAWING_CACHE_QUALITY_LOW:
16271                     case DRAWING_CACHE_QUALITY_HIGH:
16272                     default:
16273                         quality = Bitmap.Config.ARGB_8888;
16274                         break;
16275                 }
16276             } else {
16277                 // Optimization for translucent windows
16278                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16279                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16280             }
16281 
16282             // Try to cleanup memory
16283             if (bitmap != null) bitmap.recycle();
16284 
16285             try {
16286                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16287                         width, height, quality);
16288                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16289                 if (autoScale) {
16290                     mDrawingCache = bitmap;
16291                 } else {
16292                     mUnscaledDrawingCache = bitmap;
16293                 }
16294                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16295             } catch (OutOfMemoryError e) {
16296                 // If there is not enough memory to create the bitmap cache, just
16297                 // ignore the issue as bitmap caches are not required to draw the
16298                 // view hierarchy
16299                 if (autoScale) {
16300                     mDrawingCache = null;
16301                 } else {
16302                     mUnscaledDrawingCache = null;
16303                 }
16304                 mCachingFailed = true;
16305                 return;
16306             }
16307 
16308             clear = drawingCacheBackgroundColor != 0;
16309         }
16310 
16311         Canvas canvas;
16312         if (attachInfo != null) {
16313             canvas = attachInfo.mCanvas;
16314             if (canvas == null) {
16315                 canvas = new Canvas();
16316             }
16317             canvas.setBitmap(bitmap);
16318             // Temporarily clobber the cached Canvas in case one of our children
16319             // is also using a drawing cache. Without this, the children would
16320             // steal the canvas by attaching their own bitmap to it and bad, bad
16321             // thing would happen (invisible views, corrupted drawings, etc.)
16322             attachInfo.mCanvas = null;
16323         } else {
16324             // This case should hopefully never or seldom happen
16325             canvas = new Canvas(bitmap);
16326         }
16327 
16328         if (clear) {
16329             bitmap.eraseColor(drawingCacheBackgroundColor);
16330         }
16331 
16332         computeScroll();
16333         final int restoreCount = canvas.save();
16334 
16335         if (autoScale && scalingRequired) {
16336             final float scale = attachInfo.mApplicationScale;
16337             canvas.scale(scale, scale);
16338         }
16339 
16340         canvas.translate(-mScrollX, -mScrollY);
16341 
16342         mPrivateFlags |= PFLAG_DRAWN;
16343         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16344                 mLayerType != LAYER_TYPE_NONE) {
16345             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16346         }
16347 
16348         // Fast path for layouts with no backgrounds
16349         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16350             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16351             dispatchDraw(canvas);
16352             if (mOverlay != null && !mOverlay.isEmpty()) {
16353                 mOverlay.getOverlayView().draw(canvas);
16354             }
16355         } else {
16356             draw(canvas);
16357         }
16358 
16359         canvas.restoreToCount(restoreCount);
16360         canvas.setBitmap(null);
16361 
16362         if (attachInfo != null) {
16363             // Restore the cached Canvas for our siblings
16364             attachInfo.mCanvas = canvas;
16365         }
16366     }
16367 
16368     /**
16369      * Create a snapshot of the view into a bitmap.  We should probably make
16370      * some form of this public, but should think about the API.
16371      *
16372      * @hide
16373      */
createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren)16374     public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16375         int width = mRight - mLeft;
16376         int height = mBottom - mTop;
16377 
16378         final AttachInfo attachInfo = mAttachInfo;
16379         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16380         width = (int) ((width * scale) + 0.5f);
16381         height = (int) ((height * scale) + 0.5f);
16382 
16383         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16384                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
16385         if (bitmap == null) {
16386             throw new OutOfMemoryError();
16387         }
16388 
16389         Resources resources = getResources();
16390         if (resources != null) {
16391             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16392         }
16393 
16394         Canvas canvas;
16395         if (attachInfo != null) {
16396             canvas = attachInfo.mCanvas;
16397             if (canvas == null) {
16398                 canvas = new Canvas();
16399             }
16400             canvas.setBitmap(bitmap);
16401             // Temporarily clobber the cached Canvas in case one of our children
16402             // is also using a drawing cache. Without this, the children would
16403             // steal the canvas by attaching their own bitmap to it and bad, bad
16404             // things would happen (invisible views, corrupted drawings, etc.)
16405             attachInfo.mCanvas = null;
16406         } else {
16407             // This case should hopefully never or seldom happen
16408             canvas = new Canvas(bitmap);
16409         }
16410 
16411         if ((backgroundColor & 0xff000000) != 0) {
16412             bitmap.eraseColor(backgroundColor);
16413         }
16414 
16415         computeScroll();
16416         final int restoreCount = canvas.save();
16417         canvas.scale(scale, scale);
16418         canvas.translate(-mScrollX, -mScrollY);
16419 
16420         // Temporarily remove the dirty mask
16421         int flags = mPrivateFlags;
16422         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16423 
16424         // Fast path for layouts with no backgrounds
16425         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16426             dispatchDraw(canvas);
16427             if (mOverlay != null && !mOverlay.isEmpty()) {
16428                 mOverlay.getOverlayView().draw(canvas);
16429             }
16430         } else {
16431             draw(canvas);
16432         }
16433 
16434         mPrivateFlags = flags;
16435 
16436         canvas.restoreToCount(restoreCount);
16437         canvas.setBitmap(null);
16438 
16439         if (attachInfo != null) {
16440             // Restore the cached Canvas for our siblings
16441             attachInfo.mCanvas = canvas;
16442         }
16443 
16444         return bitmap;
16445     }
16446 
16447     /**
16448      * Indicates whether this View is currently in edit mode. A View is usually
16449      * in edit mode when displayed within a developer tool. For instance, if
16450      * this View is being drawn by a visual user interface builder, this method
16451      * should return true.
16452      *
16453      * Subclasses should check the return value of this method to provide
16454      * different behaviors if their normal behavior might interfere with the
16455      * host environment. For instance: the class spawns a thread in its
16456      * constructor, the drawing code relies on device-specific features, etc.
16457      *
16458      * This method is usually checked in the drawing code of custom widgets.
16459      *
16460      * @return True if this View is in edit mode, false otherwise.
16461      */
isInEditMode()16462     public boolean isInEditMode() {
16463         return false;
16464     }
16465 
16466     /**
16467      * If the View draws content inside its padding and enables fading edges,
16468      * it needs to support padding offsets. Padding offsets are added to the
16469      * fading edges to extend the length of the fade so that it covers pixels
16470      * drawn inside the padding.
16471      *
16472      * Subclasses of this class should override this method if they need
16473      * to draw content inside the padding.
16474      *
16475      * @return True if padding offset must be applied, false otherwise.
16476      *
16477      * @see #getLeftPaddingOffset()
16478      * @see #getRightPaddingOffset()
16479      * @see #getTopPaddingOffset()
16480      * @see #getBottomPaddingOffset()
16481      *
16482      * @since CURRENT
16483      */
isPaddingOffsetRequired()16484     protected boolean isPaddingOffsetRequired() {
16485         return false;
16486     }
16487 
16488     /**
16489      * Amount by which to extend the left fading region. Called only when
16490      * {@link #isPaddingOffsetRequired()} returns true.
16491      *
16492      * @return The left padding offset in pixels.
16493      *
16494      * @see #isPaddingOffsetRequired()
16495      *
16496      * @since CURRENT
16497      */
getLeftPaddingOffset()16498     protected int getLeftPaddingOffset() {
16499         return 0;
16500     }
16501 
16502     /**
16503      * Amount by which to extend the right fading region. Called only when
16504      * {@link #isPaddingOffsetRequired()} returns true.
16505      *
16506      * @return The right padding offset in pixels.
16507      *
16508      * @see #isPaddingOffsetRequired()
16509      *
16510      * @since CURRENT
16511      */
getRightPaddingOffset()16512     protected int getRightPaddingOffset() {
16513         return 0;
16514     }
16515 
16516     /**
16517      * Amount by which to extend the top fading region. Called only when
16518      * {@link #isPaddingOffsetRequired()} returns true.
16519      *
16520      * @return The top padding offset in pixels.
16521      *
16522      * @see #isPaddingOffsetRequired()
16523      *
16524      * @since CURRENT
16525      */
getTopPaddingOffset()16526     protected int getTopPaddingOffset() {
16527         return 0;
16528     }
16529 
16530     /**
16531      * Amount by which to extend the bottom fading region. Called only when
16532      * {@link #isPaddingOffsetRequired()} returns true.
16533      *
16534      * @return The bottom padding offset in pixels.
16535      *
16536      * @see #isPaddingOffsetRequired()
16537      *
16538      * @since CURRENT
16539      */
getBottomPaddingOffset()16540     protected int getBottomPaddingOffset() {
16541         return 0;
16542     }
16543 
16544     /**
16545      * @hide
16546      * @param offsetRequired
16547      */
getFadeTop(boolean offsetRequired)16548     protected int getFadeTop(boolean offsetRequired) {
16549         int top = mPaddingTop;
16550         if (offsetRequired) top += getTopPaddingOffset();
16551         return top;
16552     }
16553 
16554     /**
16555      * @hide
16556      * @param offsetRequired
16557      */
getFadeHeight(boolean offsetRequired)16558     protected int getFadeHeight(boolean offsetRequired) {
16559         int padding = mPaddingTop;
16560         if (offsetRequired) padding += getTopPaddingOffset();
16561         return mBottom - mTop - mPaddingBottom - padding;
16562     }
16563 
16564     /**
16565      * <p>Indicates whether this view is attached to a hardware accelerated
16566      * window or not.</p>
16567      *
16568      * <p>Even if this method returns true, it does not mean that every call
16569      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16570      * accelerated {@link android.graphics.Canvas}. For instance, if this view
16571      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16572      * window is hardware accelerated,
16573      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16574      * return false, and this method will return true.</p>
16575      *
16576      * @return True if the view is attached to a window and the window is
16577      *         hardware accelerated; false in any other case.
16578      */
16579     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()16580     public boolean isHardwareAccelerated() {
16581         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16582     }
16583 
16584     /**
16585      * Sets a rectangular area on this view to which the view will be clipped
16586      * when it is drawn. Setting the value to null will remove the clip bounds
16587      * and the view will draw normally, using its full bounds.
16588      *
16589      * @param clipBounds The rectangular area, in the local coordinates of
16590      * this view, to which future drawing operations will be clipped.
16591      */
setClipBounds(Rect clipBounds)16592     public void setClipBounds(Rect clipBounds) {
16593         if (clipBounds == mClipBounds
16594                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16595             return;
16596         }
16597         if (clipBounds != null) {
16598             if (mClipBounds == null) {
16599                 mClipBounds = new Rect(clipBounds);
16600             } else {
16601                 mClipBounds.set(clipBounds);
16602             }
16603         } else {
16604             mClipBounds = null;
16605         }
16606         mRenderNode.setClipBounds(mClipBounds);
16607         invalidateViewProperty(false, false);
16608     }
16609 
16610     /**
16611      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16612      *
16613      * @return A copy of the current clip bounds if clip bounds are set,
16614      * otherwise null.
16615      */
getClipBounds()16616     public Rect getClipBounds() {
16617         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16618     }
16619 
16620 
16621     /**
16622      * Populates an output rectangle with the clip bounds of the view,
16623      * returning {@code true} if successful or {@code false} if the view's
16624      * clip bounds are {@code null}.
16625      *
16626      * @param outRect rectangle in which to place the clip bounds of the view
16627      * @return {@code true} if successful or {@code false} if the view's
16628      *         clip bounds are {@code null}
16629      */
getClipBounds(Rect outRect)16630     public boolean getClipBounds(Rect outRect) {
16631         if (mClipBounds != null) {
16632             outRect.set(mClipBounds);
16633             return true;
16634         }
16635         return false;
16636     }
16637 
16638     /**
16639      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16640      * case of an active Animation being run on the view.
16641      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)16642     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16643             Animation a, boolean scalingRequired) {
16644         Transformation invalidationTransform;
16645         final int flags = parent.mGroupFlags;
16646         final boolean initialized = a.isInitialized();
16647         if (!initialized) {
16648             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16649             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16650             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16651             onAnimationStart();
16652         }
16653 
16654         final Transformation t = parent.getChildTransformation();
16655         boolean more = a.getTransformation(drawingTime, t, 1f);
16656         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16657             if (parent.mInvalidationTransformation == null) {
16658                 parent.mInvalidationTransformation = new Transformation();
16659             }
16660             invalidationTransform = parent.mInvalidationTransformation;
16661             a.getTransformation(drawingTime, invalidationTransform, 1f);
16662         } else {
16663             invalidationTransform = t;
16664         }
16665 
16666         if (more) {
16667             if (!a.willChangeBounds()) {
16668                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16669                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16670                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16671                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16672                     // The child need to draw an animation, potentially offscreen, so
16673                     // make sure we do not cancel invalidate requests
16674                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16675                     parent.invalidate(mLeft, mTop, mRight, mBottom);
16676                 }
16677             } else {
16678                 if (parent.mInvalidateRegion == null) {
16679                     parent.mInvalidateRegion = new RectF();
16680                 }
16681                 final RectF region = parent.mInvalidateRegion;
16682                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16683                         invalidationTransform);
16684 
16685                 // The child need to draw an animation, potentially offscreen, so
16686                 // make sure we do not cancel invalidate requests
16687                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16688 
16689                 final int left = mLeft + (int) region.left;
16690                 final int top = mTop + (int) region.top;
16691                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
16692                         top + (int) (region.height() + .5f));
16693             }
16694         }
16695         return more;
16696     }
16697 
16698     /**
16699      * This method is called by getDisplayList() when a display list is recorded for a View.
16700      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16701      */
setDisplayListProperties(RenderNode renderNode)16702     void setDisplayListProperties(RenderNode renderNode) {
16703         if (renderNode != null) {
16704             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16705             renderNode.setClipToBounds(mParent instanceof ViewGroup
16706                     && ((ViewGroup) mParent).getClipChildren());
16707 
16708             float alpha = 1;
16709             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16710                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16711                 ViewGroup parentVG = (ViewGroup) mParent;
16712                 final Transformation t = parentVG.getChildTransformation();
16713                 if (parentVG.getChildStaticTransformation(this, t)) {
16714                     final int transformType = t.getTransformationType();
16715                     if (transformType != Transformation.TYPE_IDENTITY) {
16716                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16717                             alpha = t.getAlpha();
16718                         }
16719                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16720                             renderNode.setStaticMatrix(t.getMatrix());
16721                         }
16722                     }
16723                 }
16724             }
16725             if (mTransformationInfo != null) {
16726                 alpha *= getFinalAlpha();
16727                 if (alpha < 1) {
16728                     final int multipliedAlpha = (int) (255 * alpha);
16729                     if (onSetAlpha(multipliedAlpha)) {
16730                         alpha = 1;
16731                     }
16732                 }
16733                 renderNode.setAlpha(alpha);
16734             } else if (alpha < 1) {
16735                 renderNode.setAlpha(alpha);
16736             }
16737         }
16738     }
16739 
16740     /**
16741      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16742      *
16743      * This is where the View specializes rendering behavior based on layer type,
16744      * and hardware acceleration.
16745      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)16746     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16747         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16748         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16749          *
16750          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16751          * HW accelerated, it can't handle drawing RenderNodes.
16752          */
16753         boolean drawingWithRenderNode = mAttachInfo != null
16754                 && mAttachInfo.mHardwareAccelerated
16755                 && hardwareAcceleratedCanvas;
16756 
16757         boolean more = false;
16758         final boolean childHasIdentityMatrix = hasIdentityMatrix();
16759         final int parentFlags = parent.mGroupFlags;
16760 
16761         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16762             parent.getChildTransformation().clear();
16763             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16764         }
16765 
16766         Transformation transformToApply = null;
16767         boolean concatMatrix = false;
16768         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16769         final Animation a = getAnimation();
16770         if (a != null) {
16771             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16772             concatMatrix = a.willChangeTransformationMatrix();
16773             if (concatMatrix) {
16774                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16775             }
16776             transformToApply = parent.getChildTransformation();
16777         } else {
16778             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16779                 // No longer animating: clear out old animation matrix
16780                 mRenderNode.setAnimationMatrix(null);
16781                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16782             }
16783             if (!drawingWithRenderNode
16784                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16785                 final Transformation t = parent.getChildTransformation();
16786                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16787                 if (hasTransform) {
16788                     final int transformType = t.getTransformationType();
16789                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16790                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16791                 }
16792             }
16793         }
16794 
16795         concatMatrix |= !childHasIdentityMatrix;
16796 
16797         // Sets the flag as early as possible to allow draw() implementations
16798         // to call invalidate() successfully when doing animations
16799         mPrivateFlags |= PFLAG_DRAWN;
16800 
16801         if (!concatMatrix &&
16802                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16803                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16804                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16805                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16806             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16807             return more;
16808         }
16809         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16810 
16811         if (hardwareAcceleratedCanvas) {
16812             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16813             // retain the flag's value temporarily in the mRecreateDisplayList flag
16814             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16815             mPrivateFlags &= ~PFLAG_INVALIDATED;
16816         }
16817 
16818         RenderNode renderNode = null;
16819         Bitmap cache = null;
16820         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16821         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16822              if (layerType != LAYER_TYPE_NONE) {
16823                  // If not drawing with RenderNode, treat HW layers as SW
16824                  layerType = LAYER_TYPE_SOFTWARE;
16825                  buildDrawingCache(true);
16826             }
16827             cache = getDrawingCache(true);
16828         }
16829 
16830         if (drawingWithRenderNode) {
16831             // Delay getting the display list until animation-driven alpha values are
16832             // set up and possibly passed on to the view
16833             renderNode = updateDisplayListIfDirty();
16834             if (!renderNode.isValid()) {
16835                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
16836                 // to getDisplayList(), the display list will be marked invalid and we should not
16837                 // try to use it again.
16838                 renderNode = null;
16839                 drawingWithRenderNode = false;
16840             }
16841         }
16842 
16843         int sx = 0;
16844         int sy = 0;
16845         if (!drawingWithRenderNode) {
16846             computeScroll();
16847             sx = mScrollX;
16848             sy = mScrollY;
16849         }
16850 
16851         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16852         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16853 
16854         int restoreTo = -1;
16855         if (!drawingWithRenderNode || transformToApply != null) {
16856             restoreTo = canvas.save();
16857         }
16858         if (offsetForScroll) {
16859             canvas.translate(mLeft - sx, mTop - sy);
16860         } else {
16861             if (!drawingWithRenderNode) {
16862                 canvas.translate(mLeft, mTop);
16863             }
16864             if (scalingRequired) {
16865                 if (drawingWithRenderNode) {
16866                     // TODO: Might not need this if we put everything inside the DL
16867                     restoreTo = canvas.save();
16868                 }
16869                 // mAttachInfo cannot be null, otherwise scalingRequired == false
16870                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
16871                 canvas.scale(scale, scale);
16872             }
16873         }
16874 
16875         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16876         if (transformToApply != null
16877                 || alpha < 1
16878                 || !hasIdentityMatrix()
16879                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16880             if (transformToApply != null || !childHasIdentityMatrix) {
16881                 int transX = 0;
16882                 int transY = 0;
16883 
16884                 if (offsetForScroll) {
16885                     transX = -sx;
16886                     transY = -sy;
16887                 }
16888 
16889                 if (transformToApply != null) {
16890                     if (concatMatrix) {
16891                         if (drawingWithRenderNode) {
16892                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
16893                         } else {
16894                             // Undo the scroll translation, apply the transformation matrix,
16895                             // then redo the scroll translate to get the correct result.
16896                             canvas.translate(-transX, -transY);
16897                             canvas.concat(transformToApply.getMatrix());
16898                             canvas.translate(transX, transY);
16899                         }
16900                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16901                     }
16902 
16903                     float transformAlpha = transformToApply.getAlpha();
16904                     if (transformAlpha < 1) {
16905                         alpha *= transformAlpha;
16906                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16907                     }
16908                 }
16909 
16910                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16911                     canvas.translate(-transX, -transY);
16912                     canvas.concat(getMatrix());
16913                     canvas.translate(transX, transY);
16914                 }
16915             }
16916 
16917             // Deal with alpha if it is or used to be <1
16918             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16919                 if (alpha < 1) {
16920                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16921                 } else {
16922                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16923                 }
16924                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16925                 if (!drawingWithDrawingCache) {
16926                     final int multipliedAlpha = (int) (255 * alpha);
16927                     if (!onSetAlpha(multipliedAlpha)) {
16928                         if (drawingWithRenderNode) {
16929                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16930                         } else if (layerType == LAYER_TYPE_NONE) {
16931                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16932                                     multipliedAlpha);
16933                         }
16934                     } else {
16935                         // Alpha is handled by the child directly, clobber the layer's alpha
16936                         mPrivateFlags |= PFLAG_ALPHA_SET;
16937                     }
16938                 }
16939             }
16940         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16941             onSetAlpha(255);
16942             mPrivateFlags &= ~PFLAG_ALPHA_SET;
16943         }
16944 
16945         if (!drawingWithRenderNode) {
16946             // apply clips directly, since RenderNode won't do it for this draw
16947             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16948                 if (offsetForScroll) {
16949                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16950                 } else {
16951                     if (!scalingRequired || cache == null) {
16952                         canvas.clipRect(0, 0, getWidth(), getHeight());
16953                     } else {
16954                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16955                     }
16956                 }
16957             }
16958 
16959             if (mClipBounds != null) {
16960                 // clip bounds ignore scroll
16961                 canvas.clipRect(mClipBounds);
16962             }
16963         }
16964 
16965         if (!drawingWithDrawingCache) {
16966             if (drawingWithRenderNode) {
16967                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16968                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16969             } else {
16970                 // Fast path for layouts with no backgrounds
16971                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16972                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16973                     dispatchDraw(canvas);
16974                 } else {
16975                     draw(canvas);
16976                 }
16977             }
16978         } else if (cache != null) {
16979             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16980             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
16981                 // no layer paint, use temporary paint to draw bitmap
16982                 Paint cachePaint = parent.mCachePaint;
16983                 if (cachePaint == null) {
16984                     cachePaint = new Paint();
16985                     cachePaint.setDither(false);
16986                     parent.mCachePaint = cachePaint;
16987                 }
16988                 cachePaint.setAlpha((int) (alpha * 255));
16989                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16990             } else {
16991                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
16992                 int layerPaintAlpha = mLayerPaint.getAlpha();
16993                 if (alpha < 1) {
16994                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16995                 }
16996                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16997                 if (alpha < 1) {
16998                     mLayerPaint.setAlpha(layerPaintAlpha);
16999                 }
17000             }
17001         }
17002 
17003         if (restoreTo >= 0) {
17004             canvas.restoreToCount(restoreTo);
17005         }
17006 
17007         if (a != null && !more) {
17008             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17009                 onSetAlpha(255);
17010             }
17011             parent.finishAnimatingView(this, a);
17012         }
17013 
17014         if (more && hardwareAcceleratedCanvas) {
17015             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17016                 // alpha animations should cause the child to recreate its display list
17017                 invalidate(true);
17018             }
17019         }
17020 
17021         mRecreateDisplayList = false;
17022 
17023         return more;
17024     }
17025 
17026     /**
17027      * Manually render this view (and all of its children) to the given Canvas.
17028      * The view must have already done a full layout before this function is
17029      * called.  When implementing a view, implement
17030      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17031      * If you do need to override this method, call the superclass version.
17032      *
17033      * @param canvas The Canvas to which the View is rendered.
17034      */
17035     @CallSuper
draw(Canvas canvas)17036     public void draw(Canvas canvas) {
17037         final int privateFlags = mPrivateFlags;
17038         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17039                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17040         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17041 
17042         /*
17043          * Draw traversal performs several drawing steps which must be executed
17044          * in the appropriate order:
17045          *
17046          *      1. Draw the background
17047          *      2. If necessary, save the canvas' layers to prepare for fading
17048          *      3. Draw view's content
17049          *      4. Draw children
17050          *      5. If necessary, draw the fading edges and restore layers
17051          *      6. Draw decorations (scrollbars for instance)
17052          */
17053 
17054         // Step 1, draw the background, if needed
17055         int saveCount;
17056 
17057         if (!dirtyOpaque) {
17058             drawBackground(canvas);
17059         }
17060 
17061         // skip step 2 & 5 if possible (common case)
17062         final int viewFlags = mViewFlags;
17063         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17064         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17065         if (!verticalEdges && !horizontalEdges) {
17066             // Step 3, draw the content
17067             if (!dirtyOpaque) onDraw(canvas);
17068 
17069             // Step 4, draw the children
17070             dispatchDraw(canvas);
17071 
17072             // Overlay is part of the content and draws beneath Foreground
17073             if (mOverlay != null && !mOverlay.isEmpty()) {
17074                 mOverlay.getOverlayView().dispatchDraw(canvas);
17075             }
17076 
17077             // Step 6, draw decorations (foreground, scrollbars)
17078             onDrawForeground(canvas);
17079 
17080             // we're done...
17081             return;
17082         }
17083 
17084         /*
17085          * Here we do the full fledged routine...
17086          * (this is an uncommon case where speed matters less,
17087          * this is why we repeat some of the tests that have been
17088          * done above)
17089          */
17090 
17091         boolean drawTop = false;
17092         boolean drawBottom = false;
17093         boolean drawLeft = false;
17094         boolean drawRight = false;
17095 
17096         float topFadeStrength = 0.0f;
17097         float bottomFadeStrength = 0.0f;
17098         float leftFadeStrength = 0.0f;
17099         float rightFadeStrength = 0.0f;
17100 
17101         // Step 2, save the canvas' layers
17102         int paddingLeft = mPaddingLeft;
17103 
17104         final boolean offsetRequired = isPaddingOffsetRequired();
17105         if (offsetRequired) {
17106             paddingLeft += getLeftPaddingOffset();
17107         }
17108 
17109         int left = mScrollX + paddingLeft;
17110         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17111         int top = mScrollY + getFadeTop(offsetRequired);
17112         int bottom = top + getFadeHeight(offsetRequired);
17113 
17114         if (offsetRequired) {
17115             right += getRightPaddingOffset();
17116             bottom += getBottomPaddingOffset();
17117         }
17118 
17119         final ScrollabilityCache scrollabilityCache = mScrollCache;
17120         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17121         int length = (int) fadeHeight;
17122 
17123         // clip the fade length if top and bottom fades overlap
17124         // overlapping fades produce odd-looking artifacts
17125         if (verticalEdges && (top + length > bottom - length)) {
17126             length = (bottom - top) / 2;
17127         }
17128 
17129         // also clip horizontal fades if necessary
17130         if (horizontalEdges && (left + length > right - length)) {
17131             length = (right - left) / 2;
17132         }
17133 
17134         if (verticalEdges) {
17135             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17136             drawTop = topFadeStrength * fadeHeight > 1.0f;
17137             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17138             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17139         }
17140 
17141         if (horizontalEdges) {
17142             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17143             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17144             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17145             drawRight = rightFadeStrength * fadeHeight > 1.0f;
17146         }
17147 
17148         saveCount = canvas.getSaveCount();
17149 
17150         int solidColor = getSolidColor();
17151         if (solidColor == 0) {
17152             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17153 
17154             if (drawTop) {
17155                 canvas.saveLayer(left, top, right, top + length, null, flags);
17156             }
17157 
17158             if (drawBottom) {
17159                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17160             }
17161 
17162             if (drawLeft) {
17163                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
17164             }
17165 
17166             if (drawRight) {
17167                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
17168             }
17169         } else {
17170             scrollabilityCache.setFadeColor(solidColor);
17171         }
17172 
17173         // Step 3, draw the content
17174         if (!dirtyOpaque) onDraw(canvas);
17175 
17176         // Step 4, draw the children
17177         dispatchDraw(canvas);
17178 
17179         // Step 5, draw the fade effect and restore layers
17180         final Paint p = scrollabilityCache.paint;
17181         final Matrix matrix = scrollabilityCache.matrix;
17182         final Shader fade = scrollabilityCache.shader;
17183 
17184         if (drawTop) {
17185             matrix.setScale(1, fadeHeight * topFadeStrength);
17186             matrix.postTranslate(left, top);
17187             fade.setLocalMatrix(matrix);
17188             p.setShader(fade);
17189             canvas.drawRect(left, top, right, top + length, p);
17190         }
17191 
17192         if (drawBottom) {
17193             matrix.setScale(1, fadeHeight * bottomFadeStrength);
17194             matrix.postRotate(180);
17195             matrix.postTranslate(left, bottom);
17196             fade.setLocalMatrix(matrix);
17197             p.setShader(fade);
17198             canvas.drawRect(left, bottom - length, right, bottom, p);
17199         }
17200 
17201         if (drawLeft) {
17202             matrix.setScale(1, fadeHeight * leftFadeStrength);
17203             matrix.postRotate(-90);
17204             matrix.postTranslate(left, top);
17205             fade.setLocalMatrix(matrix);
17206             p.setShader(fade);
17207             canvas.drawRect(left, top, left + length, bottom, p);
17208         }
17209 
17210         if (drawRight) {
17211             matrix.setScale(1, fadeHeight * rightFadeStrength);
17212             matrix.postRotate(90);
17213             matrix.postTranslate(right, top);
17214             fade.setLocalMatrix(matrix);
17215             p.setShader(fade);
17216             canvas.drawRect(right - length, top, right, bottom, p);
17217         }
17218 
17219         canvas.restoreToCount(saveCount);
17220 
17221         // Overlay is part of the content and draws beneath Foreground
17222         if (mOverlay != null && !mOverlay.isEmpty()) {
17223             mOverlay.getOverlayView().dispatchDraw(canvas);
17224         }
17225 
17226         // Step 6, draw decorations (foreground, scrollbars)
17227         onDrawForeground(canvas);
17228     }
17229 
17230     /**
17231      * Draws the background onto the specified canvas.
17232      *
17233      * @param canvas Canvas on which to draw the background
17234      */
drawBackground(Canvas canvas)17235     private void drawBackground(Canvas canvas) {
17236         final Drawable background = mBackground;
17237         if (background == null) {
17238             return;
17239         }
17240 
17241         setBackgroundBounds();
17242 
17243         // Attempt to use a display list if requested.
17244         if (canvas.isHardwareAccelerated() && mAttachInfo != null
17245                 && mAttachInfo.mHardwareRenderer != null) {
17246             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17247 
17248             final RenderNode renderNode = mBackgroundRenderNode;
17249             if (renderNode != null && renderNode.isValid()) {
17250                 setBackgroundRenderNodeProperties(renderNode);
17251                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17252                 return;
17253             }
17254         }
17255 
17256         final int scrollX = mScrollX;
17257         final int scrollY = mScrollY;
17258         if ((scrollX | scrollY) == 0) {
17259             background.draw(canvas);
17260         } else {
17261             canvas.translate(scrollX, scrollY);
17262             background.draw(canvas);
17263             canvas.translate(-scrollX, -scrollY);
17264         }
17265     }
17266 
17267     /**
17268      * Sets the correct background bounds and rebuilds the outline, if needed.
17269      * <p/>
17270      * This is called by LayoutLib.
17271      */
setBackgroundBounds()17272     void setBackgroundBounds() {
17273         if (mBackgroundSizeChanged && mBackground != null) {
17274             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17275             mBackgroundSizeChanged = false;
17276             rebuildOutline();
17277         }
17278     }
17279 
setBackgroundRenderNodeProperties(RenderNode renderNode)17280     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17281         renderNode.setTranslationX(mScrollX);
17282         renderNode.setTranslationY(mScrollY);
17283     }
17284 
17285     /**
17286      * Creates a new display list or updates the existing display list for the
17287      * specified Drawable.
17288      *
17289      * @param drawable Drawable for which to create a display list
17290      * @param renderNode Existing RenderNode, or {@code null}
17291      * @return A valid display list for the specified drawable
17292      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)17293     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17294         if (renderNode == null) {
17295             renderNode = RenderNode.create(drawable.getClass().getName(), this);
17296         }
17297 
17298         final Rect bounds = drawable.getBounds();
17299         final int width = bounds.width();
17300         final int height = bounds.height();
17301         final DisplayListCanvas canvas = renderNode.start(width, height);
17302 
17303         // Reverse left/top translation done by drawable canvas, which will
17304         // instead be applied by rendernode's LTRB bounds below. This way, the
17305         // drawable's bounds match with its rendernode bounds and its content
17306         // will lie within those bounds in the rendernode tree.
17307         canvas.translate(-bounds.left, -bounds.top);
17308 
17309         try {
17310             drawable.draw(canvas);
17311         } finally {
17312             renderNode.end(canvas);
17313         }
17314 
17315         // Set up drawable properties that are view-independent.
17316         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17317         renderNode.setProjectBackwards(drawable.isProjected());
17318         renderNode.setProjectionReceiver(true);
17319         renderNode.setClipToBounds(false);
17320         return renderNode;
17321     }
17322 
17323     /**
17324      * Returns the overlay for this view, creating it if it does not yet exist.
17325      * Adding drawables to the overlay will cause them to be displayed whenever
17326      * the view itself is redrawn. Objects in the overlay should be actively
17327      * managed: remove them when they should not be displayed anymore. The
17328      * overlay will always have the same size as its host view.
17329      *
17330      * <p>Note: Overlays do not currently work correctly with {@link
17331      * SurfaceView} or {@link TextureView}; contents in overlays for these
17332      * types of views may not display correctly.</p>
17333      *
17334      * @return The ViewOverlay object for this view.
17335      * @see ViewOverlay
17336      */
getOverlay()17337     public ViewOverlay getOverlay() {
17338         if (mOverlay == null) {
17339             mOverlay = new ViewOverlay(mContext, this);
17340         }
17341         return mOverlay;
17342     }
17343 
17344     /**
17345      * Override this if your view is known to always be drawn on top of a solid color background,
17346      * and needs to draw fading edges. Returning a non-zero color enables the view system to
17347      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17348      * should be set to 0xFF.
17349      *
17350      * @see #setVerticalFadingEdgeEnabled(boolean)
17351      * @see #setHorizontalFadingEdgeEnabled(boolean)
17352      *
17353      * @return The known solid color background for this view, or 0 if the color may vary
17354      */
17355     @ViewDebug.ExportedProperty(category = "drawing")
17356     @ColorInt
getSolidColor()17357     public int getSolidColor() {
17358         return 0;
17359     }
17360 
17361     /**
17362      * Build a human readable string representation of the specified view flags.
17363      *
17364      * @param flags the view flags to convert to a string
17365      * @return a String representing the supplied flags
17366      */
printFlags(int flags)17367     private static String printFlags(int flags) {
17368         String output = "";
17369         int numFlags = 0;
17370         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17371             output += "TAKES_FOCUS";
17372             numFlags++;
17373         }
17374 
17375         switch (flags & VISIBILITY_MASK) {
17376         case INVISIBLE:
17377             if (numFlags > 0) {
17378                 output += " ";
17379             }
17380             output += "INVISIBLE";
17381             // USELESS HERE numFlags++;
17382             break;
17383         case GONE:
17384             if (numFlags > 0) {
17385                 output += " ";
17386             }
17387             output += "GONE";
17388             // USELESS HERE numFlags++;
17389             break;
17390         default:
17391             break;
17392         }
17393         return output;
17394     }
17395 
17396     /**
17397      * Build a human readable string representation of the specified private
17398      * view flags.
17399      *
17400      * @param privateFlags the private view flags to convert to a string
17401      * @return a String representing the supplied flags
17402      */
printPrivateFlags(int privateFlags)17403     private static String printPrivateFlags(int privateFlags) {
17404         String output = "";
17405         int numFlags = 0;
17406 
17407         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17408             output += "WANTS_FOCUS";
17409             numFlags++;
17410         }
17411 
17412         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17413             if (numFlags > 0) {
17414                 output += " ";
17415             }
17416             output += "FOCUSED";
17417             numFlags++;
17418         }
17419 
17420         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17421             if (numFlags > 0) {
17422                 output += " ";
17423             }
17424             output += "SELECTED";
17425             numFlags++;
17426         }
17427 
17428         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17429             if (numFlags > 0) {
17430                 output += " ";
17431             }
17432             output += "IS_ROOT_NAMESPACE";
17433             numFlags++;
17434         }
17435 
17436         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17437             if (numFlags > 0) {
17438                 output += " ";
17439             }
17440             output += "HAS_BOUNDS";
17441             numFlags++;
17442         }
17443 
17444         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17445             if (numFlags > 0) {
17446                 output += " ";
17447             }
17448             output += "DRAWN";
17449             // USELESS HERE numFlags++;
17450         }
17451         return output;
17452     }
17453 
17454     /**
17455      * <p>Indicates whether or not this view's layout will be requested during
17456      * the next hierarchy layout pass.</p>
17457      *
17458      * @return true if the layout will be forced during next layout pass
17459      */
isLayoutRequested()17460     public boolean isLayoutRequested() {
17461         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17462     }
17463 
17464     /**
17465      * Return true if o is a ViewGroup that is laying out using optical bounds.
17466      * @hide
17467      */
isLayoutModeOptical(Object o)17468     public static boolean isLayoutModeOptical(Object o) {
17469         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17470     }
17471 
setOpticalFrame(int left, int top, int right, int bottom)17472     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17473         Insets parentInsets = mParent instanceof View ?
17474                 ((View) mParent).getOpticalInsets() : Insets.NONE;
17475         Insets childInsets = getOpticalInsets();
17476         return setFrame(
17477                 left   + parentInsets.left - childInsets.left,
17478                 top    + parentInsets.top  - childInsets.top,
17479                 right  + parentInsets.left + childInsets.right,
17480                 bottom + parentInsets.top  + childInsets.bottom);
17481     }
17482 
17483     /**
17484      * Assign a size and position to a view and all of its
17485      * descendants
17486      *
17487      * <p>This is the second phase of the layout mechanism.
17488      * (The first is measuring). In this phase, each parent calls
17489      * layout on all of its children to position them.
17490      * This is typically done using the child measurements
17491      * that were stored in the measure pass().</p>
17492      *
17493      * <p>Derived classes should not override this method.
17494      * Derived classes with children should override
17495      * onLayout. In that method, they should
17496      * call layout on each of their children.</p>
17497      *
17498      * @param l Left position, relative to parent
17499      * @param t Top position, relative to parent
17500      * @param r Right position, relative to parent
17501      * @param b Bottom position, relative to parent
17502      */
17503     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)17504     public void layout(int l, int t, int r, int b) {
17505         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17506             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17507             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17508         }
17509 
17510         int oldL = mLeft;
17511         int oldT = mTop;
17512         int oldB = mBottom;
17513         int oldR = mRight;
17514 
17515         boolean changed = isLayoutModeOptical(mParent) ?
17516                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17517 
17518         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17519             onLayout(changed, l, t, r, b);
17520             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17521 
17522             ListenerInfo li = mListenerInfo;
17523             if (li != null && li.mOnLayoutChangeListeners != null) {
17524                 ArrayList<OnLayoutChangeListener> listenersCopy =
17525                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17526                 int numListeners = listenersCopy.size();
17527                 for (int i = 0; i < numListeners; ++i) {
17528                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17529                 }
17530             }
17531         }
17532 
17533         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17534         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17535     }
17536 
17537     /**
17538      * Called from layout when this view should
17539      * assign a size and position to each of its children.
17540      *
17541      * Derived classes with children should override
17542      * this method and call layout on each of
17543      * their children.
17544      * @param changed This is a new size or position for this view
17545      * @param left Left position, relative to parent
17546      * @param top Top position, relative to parent
17547      * @param right Right position, relative to parent
17548      * @param bottom Bottom position, relative to parent
17549      */
onLayout(boolean changed, int left, int top, int right, int bottom)17550     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17551     }
17552 
17553     /**
17554      * Assign a size and position to this view.
17555      *
17556      * This is called from layout.
17557      *
17558      * @param left Left position, relative to parent
17559      * @param top Top position, relative to parent
17560      * @param right Right position, relative to parent
17561      * @param bottom Bottom position, relative to parent
17562      * @return true if the new size and position are different than the
17563      *         previous ones
17564      * {@hide}
17565      */
setFrame(int left, int top, int right, int bottom)17566     protected boolean setFrame(int left, int top, int right, int bottom) {
17567         boolean changed = false;
17568 
17569         if (DBG) {
17570             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17571                     + right + "," + bottom + ")");
17572         }
17573 
17574         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17575             changed = true;
17576 
17577             // Remember our drawn bit
17578             int drawn = mPrivateFlags & PFLAG_DRAWN;
17579 
17580             int oldWidth = mRight - mLeft;
17581             int oldHeight = mBottom - mTop;
17582             int newWidth = right - left;
17583             int newHeight = bottom - top;
17584             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17585 
17586             // Invalidate our old position
17587             invalidate(sizeChanged);
17588 
17589             mLeft = left;
17590             mTop = top;
17591             mRight = right;
17592             mBottom = bottom;
17593             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17594 
17595             mPrivateFlags |= PFLAG_HAS_BOUNDS;
17596 
17597 
17598             if (sizeChanged) {
17599                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17600             }
17601 
17602             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17603                 // If we are visible, force the DRAWN bit to on so that
17604                 // this invalidate will go through (at least to our parent).
17605                 // This is because someone may have invalidated this view
17606                 // before this call to setFrame came in, thereby clearing
17607                 // the DRAWN bit.
17608                 mPrivateFlags |= PFLAG_DRAWN;
17609                 invalidate(sizeChanged);
17610                 // parent display list may need to be recreated based on a change in the bounds
17611                 // of any child
17612                 invalidateParentCaches();
17613             }
17614 
17615             // Reset drawn bit to original value (invalidate turns it off)
17616             mPrivateFlags |= drawn;
17617 
17618             mBackgroundSizeChanged = true;
17619             if (mForegroundInfo != null) {
17620                 mForegroundInfo.mBoundsChanged = true;
17621             }
17622 
17623             notifySubtreeAccessibilityStateChangedIfNeeded();
17624         }
17625         return changed;
17626     }
17627 
17628     /**
17629      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17630      * @hide
17631      */
setLeftTopRightBottom(int left, int top, int right, int bottom)17632     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17633         setFrame(left, top, right, bottom);
17634     }
17635 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)17636     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17637         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17638         if (mOverlay != null) {
17639             mOverlay.getOverlayView().setRight(newWidth);
17640             mOverlay.getOverlayView().setBottom(newHeight);
17641         }
17642         rebuildOutline();
17643     }
17644 
17645     /**
17646      * Finalize inflating a view from XML.  This is called as the last phase
17647      * of inflation, after all child views have been added.
17648      *
17649      * <p>Even if the subclass overrides onFinishInflate, they should always be
17650      * sure to call the super method, so that we get called.
17651      */
17652     @CallSuper
onFinishInflate()17653     protected void onFinishInflate() {
17654     }
17655 
17656     /**
17657      * Returns the resources associated with this view.
17658      *
17659      * @return Resources object.
17660      */
getResources()17661     public Resources getResources() {
17662         return mResources;
17663     }
17664 
17665     /**
17666      * Invalidates the specified Drawable.
17667      *
17668      * @param drawable the drawable to invalidate
17669      */
17670     @Override
invalidateDrawable(@onNull Drawable drawable)17671     public void invalidateDrawable(@NonNull Drawable drawable) {
17672         if (verifyDrawable(drawable)) {
17673             final Rect dirty = drawable.getDirtyBounds();
17674             final int scrollX = mScrollX;
17675             final int scrollY = mScrollY;
17676 
17677             invalidate(dirty.left + scrollX, dirty.top + scrollY,
17678                     dirty.right + scrollX, dirty.bottom + scrollY);
17679             rebuildOutline();
17680         }
17681     }
17682 
17683     /**
17684      * Schedules an action on a drawable to occur at a specified time.
17685      *
17686      * @param who the recipient of the action
17687      * @param what the action to run on the drawable
17688      * @param when the time at which the action must occur. Uses the
17689      *        {@link SystemClock#uptimeMillis} timebase.
17690      */
17691     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)17692     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17693         if (verifyDrawable(who) && what != null) {
17694             final long delay = when - SystemClock.uptimeMillis();
17695             if (mAttachInfo != null) {
17696                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17697                         Choreographer.CALLBACK_ANIMATION, what, who,
17698                         Choreographer.subtractFrameDelay(delay));
17699             } else {
17700                 // Postpone the runnable until we know
17701                 // on which thread it needs to run.
17702                 getRunQueue().postDelayed(what, delay);
17703             }
17704         }
17705     }
17706 
17707     /**
17708      * Cancels a scheduled action on a drawable.
17709      *
17710      * @param who the recipient of the action
17711      * @param what the action to cancel
17712      */
17713     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)17714     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17715         if (verifyDrawable(who) && what != null) {
17716             if (mAttachInfo != null) {
17717                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17718                         Choreographer.CALLBACK_ANIMATION, what, who);
17719             }
17720             getRunQueue().removeCallbacks(what);
17721         }
17722     }
17723 
17724     /**
17725      * Unschedule any events associated with the given Drawable.  This can be
17726      * used when selecting a new Drawable into a view, so that the previous
17727      * one is completely unscheduled.
17728      *
17729      * @param who The Drawable to unschedule.
17730      *
17731      * @see #drawableStateChanged
17732      */
unscheduleDrawable(Drawable who)17733     public void unscheduleDrawable(Drawable who) {
17734         if (mAttachInfo != null && who != null) {
17735             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17736                     Choreographer.CALLBACK_ANIMATION, null, who);
17737         }
17738     }
17739 
17740     /**
17741      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17742      * that the View directionality can and will be resolved before its Drawables.
17743      *
17744      * Will call {@link View#onResolveDrawables} when resolution is done.
17745      *
17746      * @hide
17747      */
resolveDrawables()17748     protected void resolveDrawables() {
17749         // Drawables resolution may need to happen before resolving the layout direction (which is
17750         // done only during the measure() call).
17751         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17752         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17753         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17754         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17755         // direction to be resolved as its resolved value will be the same as its raw value.
17756         if (!isLayoutDirectionResolved() &&
17757                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17758             return;
17759         }
17760 
17761         final int layoutDirection = isLayoutDirectionResolved() ?
17762                 getLayoutDirection() : getRawLayoutDirection();
17763 
17764         if (mBackground != null) {
17765             mBackground.setLayoutDirection(layoutDirection);
17766         }
17767         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17768             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17769         }
17770         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17771         onResolveDrawables(layoutDirection);
17772     }
17773 
areDrawablesResolved()17774     boolean areDrawablesResolved() {
17775         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17776     }
17777 
17778     /**
17779      * Called when layout direction has been resolved.
17780      *
17781      * The default implementation does nothing.
17782      *
17783      * @param layoutDirection The resolved layout direction.
17784      *
17785      * @see #LAYOUT_DIRECTION_LTR
17786      * @see #LAYOUT_DIRECTION_RTL
17787      *
17788      * @hide
17789      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)17790     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17791     }
17792 
17793     /**
17794      * @hide
17795      */
resetResolvedDrawables()17796     protected void resetResolvedDrawables() {
17797         resetResolvedDrawablesInternal();
17798     }
17799 
resetResolvedDrawablesInternal()17800     void resetResolvedDrawablesInternal() {
17801         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17802     }
17803 
17804     /**
17805      * If your view subclass is displaying its own Drawable objects, it should
17806      * override this function and return true for any Drawable it is
17807      * displaying.  This allows animations for those drawables to be
17808      * scheduled.
17809      *
17810      * <p>Be sure to call through to the super class when overriding this
17811      * function.
17812      *
17813      * @param who The Drawable to verify.  Return true if it is one you are
17814      *            displaying, else return the result of calling through to the
17815      *            super class.
17816      *
17817      * @return boolean If true than the Drawable is being displayed in the
17818      *         view; else false and it is not allowed to animate.
17819      *
17820      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17821      * @see #drawableStateChanged()
17822      */
17823     @CallSuper
verifyDrawable(@onNull Drawable who)17824     protected boolean verifyDrawable(@NonNull Drawable who) {
17825         // Avoid verifying the scroll bar drawable so that we don't end up in
17826         // an invalidation loop. This effectively prevents the scroll bar
17827         // drawable from triggering invalidations and scheduling runnables.
17828         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17829     }
17830 
17831     /**
17832      * This function is called whenever the state of the view changes in such
17833      * a way that it impacts the state of drawables being shown.
17834      * <p>
17835      * If the View has a StateListAnimator, it will also be called to run necessary state
17836      * change animations.
17837      * <p>
17838      * Be sure to call through to the superclass when overriding this function.
17839      *
17840      * @see Drawable#setState(int[])
17841      */
17842     @CallSuper
drawableStateChanged()17843     protected void drawableStateChanged() {
17844         final int[] state = getDrawableState();
17845         boolean changed = false;
17846 
17847         final Drawable bg = mBackground;
17848         if (bg != null && bg.isStateful()) {
17849             changed |= bg.setState(state);
17850         }
17851 
17852         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17853         if (fg != null && fg.isStateful()) {
17854             changed |= fg.setState(state);
17855         }
17856 
17857         if (mScrollCache != null) {
17858             final Drawable scrollBar = mScrollCache.scrollBar;
17859             if (scrollBar != null && scrollBar.isStateful()) {
17860                 changed |= scrollBar.setState(state)
17861                         && mScrollCache.state != ScrollabilityCache.OFF;
17862             }
17863         }
17864 
17865         if (mStateListAnimator != null) {
17866             mStateListAnimator.setState(state);
17867         }
17868 
17869         if (changed) {
17870             invalidate();
17871         }
17872     }
17873 
17874     /**
17875      * This function is called whenever the view hotspot changes and needs to
17876      * be propagated to drawables or child views managed by the view.
17877      * <p>
17878      * Dispatching to child views is handled by
17879      * {@link #dispatchDrawableHotspotChanged(float, float)}.
17880      * <p>
17881      * Be sure to call through to the superclass when overriding this function.
17882      *
17883      * @param x hotspot x coordinate
17884      * @param y hotspot y coordinate
17885      */
17886     @CallSuper
drawableHotspotChanged(float x, float y)17887     public void drawableHotspotChanged(float x, float y) {
17888         if (mBackground != null) {
17889             mBackground.setHotspot(x, y);
17890         }
17891         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17892             mForegroundInfo.mDrawable.setHotspot(x, y);
17893         }
17894 
17895         dispatchDrawableHotspotChanged(x, y);
17896     }
17897 
17898     /**
17899      * Dispatches drawableHotspotChanged to all of this View's children.
17900      *
17901      * @param x hotspot x coordinate
17902      * @param y hotspot y coordinate
17903      * @see #drawableHotspotChanged(float, float)
17904      */
dispatchDrawableHotspotChanged(float x, float y)17905     public void dispatchDrawableHotspotChanged(float x, float y) {
17906     }
17907 
17908     /**
17909      * Call this to force a view to update its drawable state. This will cause
17910      * drawableStateChanged to be called on this view. Views that are interested
17911      * in the new state should call getDrawableState.
17912      *
17913      * @see #drawableStateChanged
17914      * @see #getDrawableState
17915      */
refreshDrawableState()17916     public void refreshDrawableState() {
17917         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17918         drawableStateChanged();
17919 
17920         ViewParent parent = mParent;
17921         if (parent != null) {
17922             parent.childDrawableStateChanged(this);
17923         }
17924     }
17925 
17926     /**
17927      * Return an array of resource IDs of the drawable states representing the
17928      * current state of the view.
17929      *
17930      * @return The current drawable state
17931      *
17932      * @see Drawable#setState(int[])
17933      * @see #drawableStateChanged()
17934      * @see #onCreateDrawableState(int)
17935      */
getDrawableState()17936     public final int[] getDrawableState() {
17937         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17938             return mDrawableState;
17939         } else {
17940             mDrawableState = onCreateDrawableState(0);
17941             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17942             return mDrawableState;
17943         }
17944     }
17945 
17946     /**
17947      * Generate the new {@link android.graphics.drawable.Drawable} state for
17948      * this view. This is called by the view
17949      * system when the cached Drawable state is determined to be invalid.  To
17950      * retrieve the current state, you should use {@link #getDrawableState}.
17951      *
17952      * @param extraSpace if non-zero, this is the number of extra entries you
17953      * would like in the returned array in which you can place your own
17954      * states.
17955      *
17956      * @return Returns an array holding the current {@link Drawable} state of
17957      * the view.
17958      *
17959      * @see #mergeDrawableStates(int[], int[])
17960      */
onCreateDrawableState(int extraSpace)17961     protected int[] onCreateDrawableState(int extraSpace) {
17962         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17963                 mParent instanceof View) {
17964             return ((View) mParent).onCreateDrawableState(extraSpace);
17965         }
17966 
17967         int[] drawableState;
17968 
17969         int privateFlags = mPrivateFlags;
17970 
17971         int viewStateIndex = 0;
17972         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17973         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17974         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17975         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17976         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17977         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17978         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17979                 ThreadedRenderer.isAvailable()) {
17980             // This is set if HW acceleration is requested, even if the current
17981             // process doesn't allow it.  This is just to allow app preview
17982             // windows to better match their app.
17983             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17984         }
17985         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17986 
17987         final int privateFlags2 = mPrivateFlags2;
17988         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17989             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17990         }
17991         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17992             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17993         }
17994 
17995         drawableState = StateSet.get(viewStateIndex);
17996 
17997         //noinspection ConstantIfStatement
17998         if (false) {
17999             Log.i("View", "drawableStateIndex=" + viewStateIndex);
18000             Log.i("View", toString()
18001                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18002                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18003                     + " fo=" + hasFocus()
18004                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18005                     + " wf=" + hasWindowFocus()
18006                     + ": " + Arrays.toString(drawableState));
18007         }
18008 
18009         if (extraSpace == 0) {
18010             return drawableState;
18011         }
18012 
18013         final int[] fullState;
18014         if (drawableState != null) {
18015             fullState = new int[drawableState.length + extraSpace];
18016             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18017         } else {
18018             fullState = new int[extraSpace];
18019         }
18020 
18021         return fullState;
18022     }
18023 
18024     /**
18025      * Merge your own state values in <var>additionalState</var> into the base
18026      * state values <var>baseState</var> that were returned by
18027      * {@link #onCreateDrawableState(int)}.
18028      *
18029      * @param baseState The base state values returned by
18030      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18031      * own additional state values.
18032      *
18033      * @param additionalState The additional state values you would like
18034      * added to <var>baseState</var>; this array is not modified.
18035      *
18036      * @return As a convenience, the <var>baseState</var> array you originally
18037      * passed into the function is returned.
18038      *
18039      * @see #onCreateDrawableState(int)
18040      */
mergeDrawableStates(int[] baseState, int[] additionalState)18041     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18042         final int N = baseState.length;
18043         int i = N - 1;
18044         while (i >= 0 && baseState[i] == 0) {
18045             i--;
18046         }
18047         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18048         return baseState;
18049     }
18050 
18051     /**
18052      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18053      * on all Drawable objects associated with this view.
18054      * <p>
18055      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18056      * attached to this view.
18057      */
18058     @CallSuper
jumpDrawablesToCurrentState()18059     public void jumpDrawablesToCurrentState() {
18060         if (mBackground != null) {
18061             mBackground.jumpToCurrentState();
18062         }
18063         if (mStateListAnimator != null) {
18064             mStateListAnimator.jumpToCurrentState();
18065         }
18066         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18067             mForegroundInfo.mDrawable.jumpToCurrentState();
18068         }
18069     }
18070 
18071     /**
18072      * Sets the background color for this view.
18073      * @param color the color of the background
18074      */
18075     @RemotableViewMethod
setBackgroundColor(@olorInt int color)18076     public void setBackgroundColor(@ColorInt int color) {
18077         if (mBackground instanceof ColorDrawable) {
18078             ((ColorDrawable) mBackground.mutate()).setColor(color);
18079             computeOpaqueFlags();
18080             mBackgroundResource = 0;
18081         } else {
18082             setBackground(new ColorDrawable(color));
18083         }
18084     }
18085 
18086     /**
18087      * Set the background to a given resource. The resource should refer to
18088      * a Drawable object or 0 to remove the background.
18089      * @param resid The identifier of the resource.
18090      *
18091      * @attr ref android.R.styleable#View_background
18092      */
18093     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)18094     public void setBackgroundResource(@DrawableRes int resid) {
18095         if (resid != 0 && resid == mBackgroundResource) {
18096             return;
18097         }
18098 
18099         Drawable d = null;
18100         if (resid != 0) {
18101             d = mContext.getDrawable(resid);
18102         }
18103         setBackground(d);
18104 
18105         mBackgroundResource = resid;
18106     }
18107 
18108     /**
18109      * Set the background to a given Drawable, or remove the background. If the
18110      * background has padding, this View's padding is set to the background's
18111      * padding. However, when a background is removed, this View's padding isn't
18112      * touched. If setting the padding is desired, please use
18113      * {@link #setPadding(int, int, int, int)}.
18114      *
18115      * @param background The Drawable to use as the background, or null to remove the
18116      *        background
18117      */
setBackground(Drawable background)18118     public void setBackground(Drawable background) {
18119         //noinspection deprecation
18120         setBackgroundDrawable(background);
18121     }
18122 
18123     /**
18124      * @deprecated use {@link #setBackground(Drawable)} instead
18125      */
18126     @Deprecated
setBackgroundDrawable(Drawable background)18127     public void setBackgroundDrawable(Drawable background) {
18128         computeOpaqueFlags();
18129 
18130         if (background == mBackground) {
18131             return;
18132         }
18133 
18134         boolean requestLayout = false;
18135 
18136         mBackgroundResource = 0;
18137 
18138         /*
18139          * Regardless of whether we're setting a new background or not, we want
18140          * to clear the previous drawable. setVisible first while we still have the callback set.
18141          */
18142         if (mBackground != null) {
18143             if (isAttachedToWindow()) {
18144                 mBackground.setVisible(false, false);
18145             }
18146             mBackground.setCallback(null);
18147             unscheduleDrawable(mBackground);
18148         }
18149 
18150         if (background != null) {
18151             Rect padding = sThreadLocal.get();
18152             if (padding == null) {
18153                 padding = new Rect();
18154                 sThreadLocal.set(padding);
18155             }
18156             resetResolvedDrawablesInternal();
18157             background.setLayoutDirection(getLayoutDirection());
18158             if (background.getPadding(padding)) {
18159                 resetResolvedPaddingInternal();
18160                 switch (background.getLayoutDirection()) {
18161                     case LAYOUT_DIRECTION_RTL:
18162                         mUserPaddingLeftInitial = padding.right;
18163                         mUserPaddingRightInitial = padding.left;
18164                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18165                         break;
18166                     case LAYOUT_DIRECTION_LTR:
18167                     default:
18168                         mUserPaddingLeftInitial = padding.left;
18169                         mUserPaddingRightInitial = padding.right;
18170                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18171                 }
18172                 mLeftPaddingDefined = false;
18173                 mRightPaddingDefined = false;
18174             }
18175 
18176             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18177             // if it has a different minimum size, we should layout again
18178             if (mBackground == null
18179                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
18180                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18181                 requestLayout = true;
18182             }
18183 
18184             // Set mBackground before we set this as the callback and start making other
18185             // background drawable state change calls. In particular, the setVisible call below
18186             // can result in drawables attempting to start animations or otherwise invalidate,
18187             // which requires the view set as the callback (us) to recognize the drawable as
18188             // belonging to it as per verifyDrawable.
18189             mBackground = background;
18190             if (background.isStateful()) {
18191                 background.setState(getDrawableState());
18192             }
18193             if (isAttachedToWindow()) {
18194                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18195             }
18196 
18197             applyBackgroundTint();
18198 
18199             // Set callback last, since the view may still be initializing.
18200             background.setCallback(this);
18201 
18202             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18203                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18204                 requestLayout = true;
18205             }
18206         } else {
18207             /* Remove the background */
18208             mBackground = null;
18209             if ((mViewFlags & WILL_NOT_DRAW) != 0
18210                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18211                 mPrivateFlags |= PFLAG_SKIP_DRAW;
18212             }
18213 
18214             /*
18215              * When the background is set, we try to apply its padding to this
18216              * View. When the background is removed, we don't touch this View's
18217              * padding. This is noted in the Javadocs. Hence, we don't need to
18218              * requestLayout(), the invalidate() below is sufficient.
18219              */
18220 
18221             // The old background's minimum size could have affected this
18222             // View's layout, so let's requestLayout
18223             requestLayout = true;
18224         }
18225 
18226         computeOpaqueFlags();
18227 
18228         if (requestLayout) {
18229             requestLayout();
18230         }
18231 
18232         mBackgroundSizeChanged = true;
18233         invalidate(true);
18234         invalidateOutline();
18235     }
18236 
18237     /**
18238      * Gets the background drawable
18239      *
18240      * @return The drawable used as the background for this view, if any.
18241      *
18242      * @see #setBackground(Drawable)
18243      *
18244      * @attr ref android.R.styleable#View_background
18245      */
getBackground()18246     public Drawable getBackground() {
18247         return mBackground;
18248     }
18249 
18250     /**
18251      * Applies a tint to the background drawable. Does not modify the current tint
18252      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18253      * <p>
18254      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18255      * mutate the drawable and apply the specified tint and tint mode using
18256      * {@link Drawable#setTintList(ColorStateList)}.
18257      *
18258      * @param tint the tint to apply, may be {@code null} to clear tint
18259      *
18260      * @attr ref android.R.styleable#View_backgroundTint
18261      * @see #getBackgroundTintList()
18262      * @see Drawable#setTintList(ColorStateList)
18263      */
setBackgroundTintList(@ullable ColorStateList tint)18264     public void setBackgroundTintList(@Nullable ColorStateList tint) {
18265         if (mBackgroundTint == null) {
18266             mBackgroundTint = new TintInfo();
18267         }
18268         mBackgroundTint.mTintList = tint;
18269         mBackgroundTint.mHasTintList = true;
18270 
18271         applyBackgroundTint();
18272     }
18273 
18274     /**
18275      * Return the tint applied to the background drawable, if specified.
18276      *
18277      * @return the tint applied to the background drawable
18278      * @attr ref android.R.styleable#View_backgroundTint
18279      * @see #setBackgroundTintList(ColorStateList)
18280      */
18281     @Nullable
getBackgroundTintList()18282     public ColorStateList getBackgroundTintList() {
18283         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18284     }
18285 
18286     /**
18287      * Specifies the blending mode used to apply the tint specified by
18288      * {@link #setBackgroundTintList(ColorStateList)}} to the background
18289      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18290      *
18291      * @param tintMode the blending mode used to apply the tint, may be
18292      *                 {@code null} to clear tint
18293      * @attr ref android.R.styleable#View_backgroundTintMode
18294      * @see #getBackgroundTintMode()
18295      * @see Drawable#setTintMode(PorterDuff.Mode)
18296      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)18297     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18298         if (mBackgroundTint == null) {
18299             mBackgroundTint = new TintInfo();
18300         }
18301         mBackgroundTint.mTintMode = tintMode;
18302         mBackgroundTint.mHasTintMode = true;
18303 
18304         applyBackgroundTint();
18305     }
18306 
18307     /**
18308      * Return the blending mode used to apply the tint to the background
18309      * drawable, if specified.
18310      *
18311      * @return the blending mode used to apply the tint to the background
18312      *         drawable
18313      * @attr ref android.R.styleable#View_backgroundTintMode
18314      * @see #setBackgroundTintMode(PorterDuff.Mode)
18315      */
18316     @Nullable
getBackgroundTintMode()18317     public PorterDuff.Mode getBackgroundTintMode() {
18318         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18319     }
18320 
applyBackgroundTint()18321     private void applyBackgroundTint() {
18322         if (mBackground != null && mBackgroundTint != null) {
18323             final TintInfo tintInfo = mBackgroundTint;
18324             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18325                 mBackground = mBackground.mutate();
18326 
18327                 if (tintInfo.mHasTintList) {
18328                     mBackground.setTintList(tintInfo.mTintList);
18329                 }
18330 
18331                 if (tintInfo.mHasTintMode) {
18332                     mBackground.setTintMode(tintInfo.mTintMode);
18333                 }
18334 
18335                 // The drawable (or one of its children) may not have been
18336                 // stateful before applying the tint, so let's try again.
18337                 if (mBackground.isStateful()) {
18338                     mBackground.setState(getDrawableState());
18339                 }
18340             }
18341         }
18342     }
18343 
18344     /**
18345      * Returns the drawable used as the foreground of this View. The
18346      * foreground drawable, if non-null, is always drawn on top of the view's content.
18347      *
18348      * @return a Drawable or null if no foreground was set
18349      *
18350      * @see #onDrawForeground(Canvas)
18351      */
getForeground()18352     public Drawable getForeground() {
18353         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18354     }
18355 
18356     /**
18357      * Supply a Drawable that is to be rendered on top of all of the content in the view.
18358      *
18359      * @param foreground the Drawable to be drawn on top of the children
18360      *
18361      * @attr ref android.R.styleable#View_foreground
18362      */
setForeground(Drawable foreground)18363     public void setForeground(Drawable foreground) {
18364         if (mForegroundInfo == null) {
18365             if (foreground == null) {
18366                 // Nothing to do.
18367                 return;
18368             }
18369             mForegroundInfo = new ForegroundInfo();
18370         }
18371 
18372         if (foreground == mForegroundInfo.mDrawable) {
18373             // Nothing to do
18374             return;
18375         }
18376 
18377         if (mForegroundInfo.mDrawable != null) {
18378             if (isAttachedToWindow()) {
18379                 mForegroundInfo.mDrawable.setVisible(false, false);
18380             }
18381             mForegroundInfo.mDrawable.setCallback(null);
18382             unscheduleDrawable(mForegroundInfo.mDrawable);
18383         }
18384 
18385         mForegroundInfo.mDrawable = foreground;
18386         mForegroundInfo.mBoundsChanged = true;
18387         if (foreground != null) {
18388             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18389                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18390             }
18391             foreground.setLayoutDirection(getLayoutDirection());
18392             if (foreground.isStateful()) {
18393                 foreground.setState(getDrawableState());
18394             }
18395             applyForegroundTint();
18396             if (isAttachedToWindow()) {
18397                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18398             }
18399             // Set callback last, since the view may still be initializing.
18400             foreground.setCallback(this);
18401         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18402             mPrivateFlags |= PFLAG_SKIP_DRAW;
18403         }
18404         requestLayout();
18405         invalidate();
18406     }
18407 
18408     /**
18409      * Magic bit used to support features of framework-internal window decor implementation details.
18410      * This used to live exclusively in FrameLayout.
18411      *
18412      * @return true if the foreground should draw inside the padding region or false
18413      *         if it should draw inset by the view's padding
18414      * @hide internal use only; only used by FrameLayout and internal screen layouts.
18415      */
isForegroundInsidePadding()18416     public boolean isForegroundInsidePadding() {
18417         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18418     }
18419 
18420     /**
18421      * Describes how the foreground is positioned.
18422      *
18423      * @return foreground gravity.
18424      *
18425      * @see #setForegroundGravity(int)
18426      *
18427      * @attr ref android.R.styleable#View_foregroundGravity
18428      */
getForegroundGravity()18429     public int getForegroundGravity() {
18430         return mForegroundInfo != null ? mForegroundInfo.mGravity
18431                 : Gravity.START | Gravity.TOP;
18432     }
18433 
18434     /**
18435      * Describes how the foreground is positioned. Defaults to START and TOP.
18436      *
18437      * @param gravity see {@link android.view.Gravity}
18438      *
18439      * @see #getForegroundGravity()
18440      *
18441      * @attr ref android.R.styleable#View_foregroundGravity
18442      */
setForegroundGravity(int gravity)18443     public void setForegroundGravity(int gravity) {
18444         if (mForegroundInfo == null) {
18445             mForegroundInfo = new ForegroundInfo();
18446         }
18447 
18448         if (mForegroundInfo.mGravity != gravity) {
18449             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18450                 gravity |= Gravity.START;
18451             }
18452 
18453             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18454                 gravity |= Gravity.TOP;
18455             }
18456 
18457             mForegroundInfo.mGravity = gravity;
18458             requestLayout();
18459         }
18460     }
18461 
18462     /**
18463      * Applies a tint to the foreground drawable. Does not modify the current tint
18464      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18465      * <p>
18466      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18467      * mutate the drawable and apply the specified tint and tint mode using
18468      * {@link Drawable#setTintList(ColorStateList)}.
18469      *
18470      * @param tint the tint to apply, may be {@code null} to clear tint
18471      *
18472      * @attr ref android.R.styleable#View_foregroundTint
18473      * @see #getForegroundTintList()
18474      * @see Drawable#setTintList(ColorStateList)
18475      */
setForegroundTintList(@ullable ColorStateList tint)18476     public void setForegroundTintList(@Nullable ColorStateList tint) {
18477         if (mForegroundInfo == null) {
18478             mForegroundInfo = new ForegroundInfo();
18479         }
18480         if (mForegroundInfo.mTintInfo == null) {
18481             mForegroundInfo.mTintInfo = new TintInfo();
18482         }
18483         mForegroundInfo.mTintInfo.mTintList = tint;
18484         mForegroundInfo.mTintInfo.mHasTintList = true;
18485 
18486         applyForegroundTint();
18487     }
18488 
18489     /**
18490      * Return the tint applied to the foreground drawable, if specified.
18491      *
18492      * @return the tint applied to the foreground drawable
18493      * @attr ref android.R.styleable#View_foregroundTint
18494      * @see #setForegroundTintList(ColorStateList)
18495      */
18496     @Nullable
getForegroundTintList()18497     public ColorStateList getForegroundTintList() {
18498         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18499                 ? mForegroundInfo.mTintInfo.mTintList : null;
18500     }
18501 
18502     /**
18503      * Specifies the blending mode used to apply the tint specified by
18504      * {@link #setForegroundTintList(ColorStateList)}} to the background
18505      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18506      *
18507      * @param tintMode the blending mode used to apply the tint, may be
18508      *                 {@code null} to clear tint
18509      * @attr ref android.R.styleable#View_foregroundTintMode
18510      * @see #getForegroundTintMode()
18511      * @see Drawable#setTintMode(PorterDuff.Mode)
18512      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)18513     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18514         if (mForegroundInfo == null) {
18515             mForegroundInfo = new ForegroundInfo();
18516         }
18517         if (mForegroundInfo.mTintInfo == null) {
18518             mForegroundInfo.mTintInfo = new TintInfo();
18519         }
18520         mForegroundInfo.mTintInfo.mTintMode = tintMode;
18521         mForegroundInfo.mTintInfo.mHasTintMode = true;
18522 
18523         applyForegroundTint();
18524     }
18525 
18526     /**
18527      * Return the blending mode used to apply the tint to the foreground
18528      * drawable, if specified.
18529      *
18530      * @return the blending mode used to apply the tint to the foreground
18531      *         drawable
18532      * @attr ref android.R.styleable#View_foregroundTintMode
18533      * @see #setForegroundTintMode(PorterDuff.Mode)
18534      */
18535     @Nullable
getForegroundTintMode()18536     public PorterDuff.Mode getForegroundTintMode() {
18537         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18538                 ? mForegroundInfo.mTintInfo.mTintMode : null;
18539     }
18540 
applyForegroundTint()18541     private void applyForegroundTint() {
18542         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18543                 && mForegroundInfo.mTintInfo != null) {
18544             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18545             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18546                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18547 
18548                 if (tintInfo.mHasTintList) {
18549                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18550                 }
18551 
18552                 if (tintInfo.mHasTintMode) {
18553                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18554                 }
18555 
18556                 // The drawable (or one of its children) may not have been
18557                 // stateful before applying the tint, so let's try again.
18558                 if (mForegroundInfo.mDrawable.isStateful()) {
18559                     mForegroundInfo.mDrawable.setState(getDrawableState());
18560                 }
18561             }
18562         }
18563     }
18564 
18565     /**
18566      * Draw any foreground content for this view.
18567      *
18568      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18569      * drawable or other view-specific decorations. The foreground is drawn on top of the
18570      * primary view content.</p>
18571      *
18572      * @param canvas canvas to draw into
18573      */
onDrawForeground(Canvas canvas)18574     public void onDrawForeground(Canvas canvas) {
18575         onDrawScrollIndicators(canvas);
18576         onDrawScrollBars(canvas);
18577 
18578         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18579         if (foreground != null) {
18580             if (mForegroundInfo.mBoundsChanged) {
18581                 mForegroundInfo.mBoundsChanged = false;
18582                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
18583                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18584 
18585                 if (mForegroundInfo.mInsidePadding) {
18586                     selfBounds.set(0, 0, getWidth(), getHeight());
18587                 } else {
18588                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
18589                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18590                 }
18591 
18592                 final int ld = getLayoutDirection();
18593                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18594                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18595                 foreground.setBounds(overlayBounds);
18596             }
18597 
18598             foreground.draw(canvas);
18599         }
18600     }
18601 
18602     /**
18603      * Sets the padding. The view may add on the space required to display
18604      * the scrollbars, depending on the style and visibility of the scrollbars.
18605      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18606      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18607      * from the values set in this call.
18608      *
18609      * @attr ref android.R.styleable#View_padding
18610      * @attr ref android.R.styleable#View_paddingBottom
18611      * @attr ref android.R.styleable#View_paddingLeft
18612      * @attr ref android.R.styleable#View_paddingRight
18613      * @attr ref android.R.styleable#View_paddingTop
18614      * @param left the left padding in pixels
18615      * @param top the top padding in pixels
18616      * @param right the right padding in pixels
18617      * @param bottom the bottom padding in pixels
18618      */
setPadding(int left, int top, int right, int bottom)18619     public void setPadding(int left, int top, int right, int bottom) {
18620         resetResolvedPaddingInternal();
18621 
18622         mUserPaddingStart = UNDEFINED_PADDING;
18623         mUserPaddingEnd = UNDEFINED_PADDING;
18624 
18625         mUserPaddingLeftInitial = left;
18626         mUserPaddingRightInitial = right;
18627 
18628         mLeftPaddingDefined = true;
18629         mRightPaddingDefined = true;
18630 
18631         internalSetPadding(left, top, right, bottom);
18632     }
18633 
18634     /**
18635      * @hide
18636      */
internalSetPadding(int left, int top, int right, int bottom)18637     protected void internalSetPadding(int left, int top, int right, int bottom) {
18638         mUserPaddingLeft = left;
18639         mUserPaddingRight = right;
18640         mUserPaddingBottom = bottom;
18641 
18642         final int viewFlags = mViewFlags;
18643         boolean changed = false;
18644 
18645         // Common case is there are no scroll bars.
18646         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18647             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18648                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18649                         ? 0 : getVerticalScrollbarWidth();
18650                 switch (mVerticalScrollbarPosition) {
18651                     case SCROLLBAR_POSITION_DEFAULT:
18652                         if (isLayoutRtl()) {
18653                             left += offset;
18654                         } else {
18655                             right += offset;
18656                         }
18657                         break;
18658                     case SCROLLBAR_POSITION_RIGHT:
18659                         right += offset;
18660                         break;
18661                     case SCROLLBAR_POSITION_LEFT:
18662                         left += offset;
18663                         break;
18664                 }
18665             }
18666             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18667                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18668                         ? 0 : getHorizontalScrollbarHeight();
18669             }
18670         }
18671 
18672         if (mPaddingLeft != left) {
18673             changed = true;
18674             mPaddingLeft = left;
18675         }
18676         if (mPaddingTop != top) {
18677             changed = true;
18678             mPaddingTop = top;
18679         }
18680         if (mPaddingRight != right) {
18681             changed = true;
18682             mPaddingRight = right;
18683         }
18684         if (mPaddingBottom != bottom) {
18685             changed = true;
18686             mPaddingBottom = bottom;
18687         }
18688 
18689         if (changed) {
18690             requestLayout();
18691             invalidateOutline();
18692         }
18693     }
18694 
18695     /**
18696      * Sets the relative padding. The view may add on the space required to display
18697      * the scrollbars, depending on the style and visibility of the scrollbars.
18698      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18699      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18700      * from the values set in this call.
18701      *
18702      * @attr ref android.R.styleable#View_padding
18703      * @attr ref android.R.styleable#View_paddingBottom
18704      * @attr ref android.R.styleable#View_paddingStart
18705      * @attr ref android.R.styleable#View_paddingEnd
18706      * @attr ref android.R.styleable#View_paddingTop
18707      * @param start the start padding in pixels
18708      * @param top the top padding in pixels
18709      * @param end the end padding in pixels
18710      * @param bottom the bottom padding in pixels
18711      */
setPaddingRelative(int start, int top, int end, int bottom)18712     public void setPaddingRelative(int start, int top, int end, int bottom) {
18713         resetResolvedPaddingInternal();
18714 
18715         mUserPaddingStart = start;
18716         mUserPaddingEnd = end;
18717         mLeftPaddingDefined = true;
18718         mRightPaddingDefined = true;
18719 
18720         switch(getLayoutDirection()) {
18721             case LAYOUT_DIRECTION_RTL:
18722                 mUserPaddingLeftInitial = end;
18723                 mUserPaddingRightInitial = start;
18724                 internalSetPadding(end, top, start, bottom);
18725                 break;
18726             case LAYOUT_DIRECTION_LTR:
18727             default:
18728                 mUserPaddingLeftInitial = start;
18729                 mUserPaddingRightInitial = end;
18730                 internalSetPadding(start, top, end, bottom);
18731         }
18732     }
18733 
18734     /**
18735      * Returns the top padding of this view.
18736      *
18737      * @return the top padding in pixels
18738      */
getPaddingTop()18739     public int getPaddingTop() {
18740         return mPaddingTop;
18741     }
18742 
18743     /**
18744      * Returns the bottom padding of this view. If there are inset and enabled
18745      * scrollbars, this value may include the space required to display the
18746      * scrollbars as well.
18747      *
18748      * @return the bottom padding in pixels
18749      */
getPaddingBottom()18750     public int getPaddingBottom() {
18751         return mPaddingBottom;
18752     }
18753 
18754     /**
18755      * Returns the left padding of this view. If there are inset and enabled
18756      * scrollbars, this value may include the space required to display the
18757      * scrollbars as well.
18758      *
18759      * @return the left padding in pixels
18760      */
getPaddingLeft()18761     public int getPaddingLeft() {
18762         if (!isPaddingResolved()) {
18763             resolvePadding();
18764         }
18765         return mPaddingLeft;
18766     }
18767 
18768     /**
18769      * Returns the start padding of this view depending on its resolved layout direction.
18770      * If there are inset and enabled scrollbars, this value may include the space
18771      * required to display the scrollbars as well.
18772      *
18773      * @return the start padding in pixels
18774      */
getPaddingStart()18775     public int getPaddingStart() {
18776         if (!isPaddingResolved()) {
18777             resolvePadding();
18778         }
18779         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18780                 mPaddingRight : mPaddingLeft;
18781     }
18782 
18783     /**
18784      * Returns the right padding of this view. If there are inset and enabled
18785      * scrollbars, this value may include the space required to display the
18786      * scrollbars as well.
18787      *
18788      * @return the right padding in pixels
18789      */
getPaddingRight()18790     public int getPaddingRight() {
18791         if (!isPaddingResolved()) {
18792             resolvePadding();
18793         }
18794         return mPaddingRight;
18795     }
18796 
18797     /**
18798      * Returns the end padding of this view depending on its resolved layout direction.
18799      * If there are inset and enabled scrollbars, this value may include the space
18800      * required to display the scrollbars as well.
18801      *
18802      * @return the end padding in pixels
18803      */
getPaddingEnd()18804     public int getPaddingEnd() {
18805         if (!isPaddingResolved()) {
18806             resolvePadding();
18807         }
18808         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18809                 mPaddingLeft : mPaddingRight;
18810     }
18811 
18812     /**
18813      * Return if the padding has been set through relative values
18814      * {@link #setPaddingRelative(int, int, int, int)} or through
18815      * @attr ref android.R.styleable#View_paddingStart or
18816      * @attr ref android.R.styleable#View_paddingEnd
18817      *
18818      * @return true if the padding is relative or false if it is not.
18819      */
isPaddingRelative()18820     public boolean isPaddingRelative() {
18821         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18822     }
18823 
computeOpticalInsets()18824     Insets computeOpticalInsets() {
18825         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18826     }
18827 
18828     /**
18829      * @hide
18830      */
resetPaddingToInitialValues()18831     public void resetPaddingToInitialValues() {
18832         if (isRtlCompatibilityMode()) {
18833             mPaddingLeft = mUserPaddingLeftInitial;
18834             mPaddingRight = mUserPaddingRightInitial;
18835             return;
18836         }
18837         if (isLayoutRtl()) {
18838             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18839             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18840         } else {
18841             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18842             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18843         }
18844     }
18845 
18846     /**
18847      * @hide
18848      */
getOpticalInsets()18849     public Insets getOpticalInsets() {
18850         if (mLayoutInsets == null) {
18851             mLayoutInsets = computeOpticalInsets();
18852         }
18853         return mLayoutInsets;
18854     }
18855 
18856     /**
18857      * Set this view's optical insets.
18858      *
18859      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18860      * property. Views that compute their own optical insets should call it as part of measurement.
18861      * This method does not request layout. If you are setting optical insets outside of
18862      * measure/layout itself you will want to call requestLayout() yourself.
18863      * </p>
18864      * @hide
18865      */
setOpticalInsets(Insets insets)18866     public void setOpticalInsets(Insets insets) {
18867         mLayoutInsets = insets;
18868     }
18869 
18870     /**
18871      * Changes the selection state of this view. A view can be selected or not.
18872      * Note that selection is not the same as focus. Views are typically
18873      * selected in the context of an AdapterView like ListView or GridView;
18874      * the selected view is the view that is highlighted.
18875      *
18876      * @param selected true if the view must be selected, false otherwise
18877      */
setSelected(boolean selected)18878     public void setSelected(boolean selected) {
18879         //noinspection DoubleNegation
18880         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18881             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18882             if (!selected) resetPressedState();
18883             invalidate(true);
18884             refreshDrawableState();
18885             dispatchSetSelected(selected);
18886             if (selected) {
18887                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18888             } else {
18889                 notifyViewAccessibilityStateChangedIfNeeded(
18890                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18891             }
18892         }
18893     }
18894 
18895     /**
18896      * Dispatch setSelected to all of this View's children.
18897      *
18898      * @see #setSelected(boolean)
18899      *
18900      * @param selected The new selected state
18901      */
dispatchSetSelected(boolean selected)18902     protected void dispatchSetSelected(boolean selected) {
18903     }
18904 
18905     /**
18906      * Indicates the selection state of this view.
18907      *
18908      * @return true if the view is selected, false otherwise
18909      */
18910     @ViewDebug.ExportedProperty
isSelected()18911     public boolean isSelected() {
18912         return (mPrivateFlags & PFLAG_SELECTED) != 0;
18913     }
18914 
18915     /**
18916      * Changes the activated state of this view. A view can be activated or not.
18917      * Note that activation is not the same as selection.  Selection is
18918      * a transient property, representing the view (hierarchy) the user is
18919      * currently interacting with.  Activation is a longer-term state that the
18920      * user can move views in and out of.  For example, in a list view with
18921      * single or multiple selection enabled, the views in the current selection
18922      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18923      * here.)  The activated state is propagated down to children of the view it
18924      * is set on.
18925      *
18926      * @param activated true if the view must be activated, false otherwise
18927      */
setActivated(boolean activated)18928     public void setActivated(boolean activated) {
18929         //noinspection DoubleNegation
18930         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18931             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18932             invalidate(true);
18933             refreshDrawableState();
18934             dispatchSetActivated(activated);
18935         }
18936     }
18937 
18938     /**
18939      * Dispatch setActivated to all of this View's children.
18940      *
18941      * @see #setActivated(boolean)
18942      *
18943      * @param activated The new activated state
18944      */
dispatchSetActivated(boolean activated)18945     protected void dispatchSetActivated(boolean activated) {
18946     }
18947 
18948     /**
18949      * Indicates the activation state of this view.
18950      *
18951      * @return true if the view is activated, false otherwise
18952      */
18953     @ViewDebug.ExportedProperty
isActivated()18954     public boolean isActivated() {
18955         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18956     }
18957 
18958     /**
18959      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18960      * observer can be used to get notifications when global events, like
18961      * layout, happen.
18962      *
18963      * The returned ViewTreeObserver observer is not guaranteed to remain
18964      * valid for the lifetime of this View. If the caller of this method keeps
18965      * a long-lived reference to ViewTreeObserver, it should always check for
18966      * the return value of {@link ViewTreeObserver#isAlive()}.
18967      *
18968      * @return The ViewTreeObserver for this view's hierarchy.
18969      */
getViewTreeObserver()18970     public ViewTreeObserver getViewTreeObserver() {
18971         if (mAttachInfo != null) {
18972             return mAttachInfo.mTreeObserver;
18973         }
18974         if (mFloatingTreeObserver == null) {
18975             mFloatingTreeObserver = new ViewTreeObserver();
18976         }
18977         return mFloatingTreeObserver;
18978     }
18979 
18980     /**
18981      * <p>Finds the topmost view in the current view hierarchy.</p>
18982      *
18983      * @return the topmost view containing this view
18984      */
getRootView()18985     public View getRootView() {
18986         if (mAttachInfo != null) {
18987             final View v = mAttachInfo.mRootView;
18988             if (v != null) {
18989                 return v;
18990             }
18991         }
18992 
18993         View parent = this;
18994 
18995         while (parent.mParent != null && parent.mParent instanceof View) {
18996             parent = (View) parent.mParent;
18997         }
18998 
18999         return parent;
19000     }
19001 
19002     /**
19003      * Transforms a motion event from view-local coordinates to on-screen
19004      * coordinates.
19005      *
19006      * @param ev the view-local motion event
19007      * @return false if the transformation could not be applied
19008      * @hide
19009      */
toGlobalMotionEvent(MotionEvent ev)19010     public boolean toGlobalMotionEvent(MotionEvent ev) {
19011         final AttachInfo info = mAttachInfo;
19012         if (info == null) {
19013             return false;
19014         }
19015 
19016         final Matrix m = info.mTmpMatrix;
19017         m.set(Matrix.IDENTITY_MATRIX);
19018         transformMatrixToGlobal(m);
19019         ev.transform(m);
19020         return true;
19021     }
19022 
19023     /**
19024      * Transforms a motion event from on-screen coordinates to view-local
19025      * coordinates.
19026      *
19027      * @param ev the on-screen motion event
19028      * @return false if the transformation could not be applied
19029      * @hide
19030      */
toLocalMotionEvent(MotionEvent ev)19031     public boolean toLocalMotionEvent(MotionEvent ev) {
19032         final AttachInfo info = mAttachInfo;
19033         if (info == null) {
19034             return false;
19035         }
19036 
19037         final Matrix m = info.mTmpMatrix;
19038         m.set(Matrix.IDENTITY_MATRIX);
19039         transformMatrixToLocal(m);
19040         ev.transform(m);
19041         return true;
19042     }
19043 
19044     /**
19045      * Modifies the input matrix such that it maps view-local coordinates to
19046      * on-screen coordinates.
19047      *
19048      * @param m input matrix to modify
19049      * @hide
19050      */
transformMatrixToGlobal(Matrix m)19051     public void transformMatrixToGlobal(Matrix m) {
19052         final ViewParent parent = mParent;
19053         if (parent instanceof View) {
19054             final View vp = (View) parent;
19055             vp.transformMatrixToGlobal(m);
19056             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19057         } else if (parent instanceof ViewRootImpl) {
19058             final ViewRootImpl vr = (ViewRootImpl) parent;
19059             vr.transformMatrixToGlobal(m);
19060             m.preTranslate(0, -vr.mCurScrollY);
19061         }
19062 
19063         m.preTranslate(mLeft, mTop);
19064 
19065         if (!hasIdentityMatrix()) {
19066             m.preConcat(getMatrix());
19067         }
19068     }
19069 
19070     /**
19071      * Modifies the input matrix such that it maps on-screen coordinates to
19072      * view-local coordinates.
19073      *
19074      * @param m input matrix to modify
19075      * @hide
19076      */
transformMatrixToLocal(Matrix m)19077     public void transformMatrixToLocal(Matrix m) {
19078         final ViewParent parent = mParent;
19079         if (parent instanceof View) {
19080             final View vp = (View) parent;
19081             vp.transformMatrixToLocal(m);
19082             m.postTranslate(vp.mScrollX, vp.mScrollY);
19083         } else if (parent instanceof ViewRootImpl) {
19084             final ViewRootImpl vr = (ViewRootImpl) parent;
19085             vr.transformMatrixToLocal(m);
19086             m.postTranslate(0, vr.mCurScrollY);
19087         }
19088 
19089         m.postTranslate(-mLeft, -mTop);
19090 
19091         if (!hasIdentityMatrix()) {
19092             m.postConcat(getInverseMatrix());
19093         }
19094     }
19095 
19096     /**
19097      * @hide
19098      */
19099     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19100             @ViewDebug.IntToString(from = 0, to = "x"),
19101             @ViewDebug.IntToString(from = 1, to = "y")
19102     })
getLocationOnScreen()19103     public int[] getLocationOnScreen() {
19104         int[] location = new int[2];
19105         getLocationOnScreen(location);
19106         return location;
19107     }
19108 
19109     /**
19110      * <p>Computes the coordinates of this view on the screen. The argument
19111      * must be an array of two integers. After the method returns, the array
19112      * contains the x and y location in that order.</p>
19113      *
19114      * @param outLocation an array of two integers in which to hold the coordinates
19115      */
getLocationOnScreen(@ize2) int[] outLocation)19116     public void getLocationOnScreen(@Size(2) int[] outLocation) {
19117         getLocationInWindow(outLocation);
19118 
19119         final AttachInfo info = mAttachInfo;
19120         if (info != null) {
19121             outLocation[0] += info.mWindowLeft;
19122             outLocation[1] += info.mWindowTop;
19123         }
19124     }
19125 
19126     /**
19127      * <p>Computes the coordinates of this view in its window. The argument
19128      * must be an array of two integers. After the method returns, the array
19129      * contains the x and y location in that order.</p>
19130      *
19131      * @param outLocation an array of two integers in which to hold the coordinates
19132      */
getLocationInWindow(@ize2) int[] outLocation)19133     public void getLocationInWindow(@Size(2) int[] outLocation) {
19134         if (outLocation == null || outLocation.length < 2) {
19135             throw new IllegalArgumentException("outLocation must be an array of two integers");
19136         }
19137 
19138         outLocation[0] = 0;
19139         outLocation[1] = 0;
19140 
19141         transformFromViewToWindowSpace(outLocation);
19142     }
19143 
19144     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)19145     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19146         if (inOutLocation == null || inOutLocation.length < 2) {
19147             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19148         }
19149 
19150         if (mAttachInfo == null) {
19151             // When the view is not attached to a window, this method does not make sense
19152             inOutLocation[0] = inOutLocation[1] = 0;
19153             return;
19154         }
19155 
19156         float position[] = mAttachInfo.mTmpTransformLocation;
19157         position[0] = inOutLocation[0];
19158         position[1] = inOutLocation[1];
19159 
19160         if (!hasIdentityMatrix()) {
19161             getMatrix().mapPoints(position);
19162         }
19163 
19164         position[0] += mLeft;
19165         position[1] += mTop;
19166 
19167         ViewParent viewParent = mParent;
19168         while (viewParent instanceof View) {
19169             final View view = (View) viewParent;
19170 
19171             position[0] -= view.mScrollX;
19172             position[1] -= view.mScrollY;
19173 
19174             if (!view.hasIdentityMatrix()) {
19175                 view.getMatrix().mapPoints(position);
19176             }
19177 
19178             position[0] += view.mLeft;
19179             position[1] += view.mTop;
19180 
19181             viewParent = view.mParent;
19182          }
19183 
19184         if (viewParent instanceof ViewRootImpl) {
19185             // *cough*
19186             final ViewRootImpl vr = (ViewRootImpl) viewParent;
19187             position[1] -= vr.mCurScrollY;
19188         }
19189 
19190         inOutLocation[0] = Math.round(position[0]);
19191         inOutLocation[1] = Math.round(position[1]);
19192     }
19193 
19194     /**
19195      * {@hide}
19196      * @param id the id of the view to be found
19197      * @return the view of the specified id, null if cannot be found
19198      */
findViewTraversal(@dRes int id)19199     protected View findViewTraversal(@IdRes int id) {
19200         if (id == mID) {
19201             return this;
19202         }
19203         return null;
19204     }
19205 
19206     /**
19207      * {@hide}
19208      * @param tag the tag of the view to be found
19209      * @return the view of specified tag, null if cannot be found
19210      */
findViewWithTagTraversal(Object tag)19211     protected View findViewWithTagTraversal(Object tag) {
19212         if (tag != null && tag.equals(mTag)) {
19213             return this;
19214         }
19215         return null;
19216     }
19217 
19218     /**
19219      * {@hide}
19220      * @param predicate The predicate to evaluate.
19221      * @param childToSkip If not null, ignores this child during the recursive traversal.
19222      * @return The first view that matches the predicate or null.
19223      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)19224     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19225         if (predicate.apply(this)) {
19226             return this;
19227         }
19228         return null;
19229     }
19230 
19231     /**
19232      * Look for a child view with the given id.  If this view has the given
19233      * id, return this view.
19234      *
19235      * @param id The id to search for.
19236      * @return The view that has the given id in the hierarchy or null
19237      */
19238     @Nullable
findViewById(@dRes int id)19239     public final View findViewById(@IdRes int id) {
19240         if (id < 0) {
19241             return null;
19242         }
19243         return findViewTraversal(id);
19244     }
19245 
19246     /**
19247      * Finds a view by its unuque and stable accessibility id.
19248      *
19249      * @param accessibilityId The searched accessibility id.
19250      * @return The found view.
19251      */
findViewByAccessibilityId(int accessibilityId)19252     final View findViewByAccessibilityId(int accessibilityId) {
19253         if (accessibilityId < 0) {
19254             return null;
19255         }
19256         View view = findViewByAccessibilityIdTraversal(accessibilityId);
19257         if (view != null) {
19258             return view.includeForAccessibility() ? view : null;
19259         }
19260         return null;
19261     }
19262 
19263     /**
19264      * Performs the traversal to find a view by its unuque and stable accessibility id.
19265      *
19266      * <strong>Note:</strong>This method does not stop at the root namespace
19267      * boundary since the user can touch the screen at an arbitrary location
19268      * potentially crossing the root namespace bounday which will send an
19269      * accessibility event to accessibility services and they should be able
19270      * to obtain the event source. Also accessibility ids are guaranteed to be
19271      * unique in the window.
19272      *
19273      * @param accessibilityId The accessibility id.
19274      * @return The found view.
19275      *
19276      * @hide
19277      */
findViewByAccessibilityIdTraversal(int accessibilityId)19278     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19279         if (getAccessibilityViewId() == accessibilityId) {
19280             return this;
19281         }
19282         return null;
19283     }
19284 
19285     /**
19286      * Look for a child view with the given tag.  If this view has the given
19287      * tag, return this view.
19288      *
19289      * @param tag The tag to search for, using "tag.equals(getTag())".
19290      * @return The View that has the given tag in the hierarchy or null
19291      */
findViewWithTag(Object tag)19292     public final View findViewWithTag(Object tag) {
19293         if (tag == null) {
19294             return null;
19295         }
19296         return findViewWithTagTraversal(tag);
19297     }
19298 
19299     /**
19300      * {@hide}
19301      * Look for a child view that matches the specified predicate.
19302      * If this view matches the predicate, return this view.
19303      *
19304      * @param predicate The predicate to evaluate.
19305      * @return The first view that matches the predicate or null.
19306      */
findViewByPredicate(Predicate<View> predicate)19307     public final View findViewByPredicate(Predicate<View> predicate) {
19308         return findViewByPredicateTraversal(predicate, null);
19309     }
19310 
19311     /**
19312      * {@hide}
19313      * Look for a child view that matches the specified predicate,
19314      * starting with the specified view and its descendents and then
19315      * recusively searching the ancestors and siblings of that view
19316      * until this view is reached.
19317      *
19318      * This method is useful in cases where the predicate does not match
19319      * a single unique view (perhaps multiple views use the same id)
19320      * and we are trying to find the view that is "closest" in scope to the
19321      * starting view.
19322      *
19323      * @param start The view to start from.
19324      * @param predicate The predicate to evaluate.
19325      * @return The first view that matches the predicate or null.
19326      */
findViewByPredicateInsideOut(View start, Predicate<View> predicate)19327     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19328         View childToSkip = null;
19329         for (;;) {
19330             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19331             if (view != null || start == this) {
19332                 return view;
19333             }
19334 
19335             ViewParent parent = start.getParent();
19336             if (parent == null || !(parent instanceof View)) {
19337                 return null;
19338             }
19339 
19340             childToSkip = start;
19341             start = (View) parent;
19342         }
19343     }
19344 
19345     /**
19346      * Sets the identifier for this view. The identifier does not have to be
19347      * unique in this view's hierarchy. The identifier should be a positive
19348      * number.
19349      *
19350      * @see #NO_ID
19351      * @see #getId()
19352      * @see #findViewById(int)
19353      *
19354      * @param id a number used to identify the view
19355      *
19356      * @attr ref android.R.styleable#View_id
19357      */
setId(@dRes int id)19358     public void setId(@IdRes int id) {
19359         mID = id;
19360         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19361             mID = generateViewId();
19362         }
19363     }
19364 
19365     /**
19366      * {@hide}
19367      *
19368      * @param isRoot true if the view belongs to the root namespace, false
19369      *        otherwise
19370      */
setIsRootNamespace(boolean isRoot)19371     public void setIsRootNamespace(boolean isRoot) {
19372         if (isRoot) {
19373             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19374         } else {
19375             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19376         }
19377     }
19378 
19379     /**
19380      * {@hide}
19381      *
19382      * @return true if the view belongs to the root namespace, false otherwise
19383      */
isRootNamespace()19384     public boolean isRootNamespace() {
19385         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19386     }
19387 
19388     /**
19389      * Returns this view's identifier.
19390      *
19391      * @return a positive integer used to identify the view or {@link #NO_ID}
19392      *         if the view has no ID
19393      *
19394      * @see #setId(int)
19395      * @see #findViewById(int)
19396      * @attr ref android.R.styleable#View_id
19397      */
19398     @IdRes
19399     @ViewDebug.CapturedViewProperty
getId()19400     public int getId() {
19401         return mID;
19402     }
19403 
19404     /**
19405      * Returns this view's tag.
19406      *
19407      * @return the Object stored in this view as a tag, or {@code null} if not
19408      *         set
19409      *
19410      * @see #setTag(Object)
19411      * @see #getTag(int)
19412      */
19413     @ViewDebug.ExportedProperty
getTag()19414     public Object getTag() {
19415         return mTag;
19416     }
19417 
19418     /**
19419      * Sets the tag associated with this view. A tag can be used to mark
19420      * a view in its hierarchy and does not have to be unique within the
19421      * hierarchy. Tags can also be used to store data within a view without
19422      * resorting to another data structure.
19423      *
19424      * @param tag an Object to tag the view with
19425      *
19426      * @see #getTag()
19427      * @see #setTag(int, Object)
19428      */
setTag(final Object tag)19429     public void setTag(final Object tag) {
19430         mTag = tag;
19431     }
19432 
19433     /**
19434      * Returns the tag associated with this view and the specified key.
19435      *
19436      * @param key The key identifying the tag
19437      *
19438      * @return the Object stored in this view as a tag, or {@code null} if not
19439      *         set
19440      *
19441      * @see #setTag(int, Object)
19442      * @see #getTag()
19443      */
getTag(int key)19444     public Object getTag(int key) {
19445         if (mKeyedTags != null) return mKeyedTags.get(key);
19446         return null;
19447     }
19448 
19449     /**
19450      * Sets a tag associated with this view and a key. A tag can be used
19451      * to mark a view in its hierarchy and does not have to be unique within
19452      * the hierarchy. Tags can also be used to store data within a view
19453      * without resorting to another data structure.
19454      *
19455      * The specified key should be an id declared in the resources of the
19456      * application to ensure it is unique (see the <a
19457      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19458      * Keys identified as belonging to
19459      * the Android framework or not associated with any package will cause
19460      * an {@link IllegalArgumentException} to be thrown.
19461      *
19462      * @param key The key identifying the tag
19463      * @param tag An Object to tag the view with
19464      *
19465      * @throws IllegalArgumentException If they specified key is not valid
19466      *
19467      * @see #setTag(Object)
19468      * @see #getTag(int)
19469      */
setTag(int key, final Object tag)19470     public void setTag(int key, final Object tag) {
19471         // If the package id is 0x00 or 0x01, it's either an undefined package
19472         // or a framework id
19473         if ((key >>> 24) < 2) {
19474             throw new IllegalArgumentException("The key must be an application-specific "
19475                     + "resource id.");
19476         }
19477 
19478         setKeyedTag(key, tag);
19479     }
19480 
19481     /**
19482      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19483      * framework id.
19484      *
19485      * @hide
19486      */
setTagInternal(int key, Object tag)19487     public void setTagInternal(int key, Object tag) {
19488         if ((key >>> 24) != 0x1) {
19489             throw new IllegalArgumentException("The key must be a framework-specific "
19490                     + "resource id.");
19491         }
19492 
19493         setKeyedTag(key, tag);
19494     }
19495 
setKeyedTag(int key, Object tag)19496     private void setKeyedTag(int key, Object tag) {
19497         if (mKeyedTags == null) {
19498             mKeyedTags = new SparseArray<Object>(2);
19499         }
19500 
19501         mKeyedTags.put(key, tag);
19502     }
19503 
19504     /**
19505      * Prints information about this view in the log output, with the tag
19506      * {@link #VIEW_LOG_TAG}.
19507      *
19508      * @hide
19509      */
debug()19510     public void debug() {
19511         debug(0);
19512     }
19513 
19514     /**
19515      * Prints information about this view in the log output, with the tag
19516      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19517      * indentation defined by the <code>depth</code>.
19518      *
19519      * @param depth the indentation level
19520      *
19521      * @hide
19522      */
debug(int depth)19523     protected void debug(int depth) {
19524         String output = debugIndent(depth - 1);
19525 
19526         output += "+ " + this;
19527         int id = getId();
19528         if (id != -1) {
19529             output += " (id=" + id + ")";
19530         }
19531         Object tag = getTag();
19532         if (tag != null) {
19533             output += " (tag=" + tag + ")";
19534         }
19535         Log.d(VIEW_LOG_TAG, output);
19536 
19537         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19538             output = debugIndent(depth) + " FOCUSED";
19539             Log.d(VIEW_LOG_TAG, output);
19540         }
19541 
19542         output = debugIndent(depth);
19543         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19544                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19545                 + "} ";
19546         Log.d(VIEW_LOG_TAG, output);
19547 
19548         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19549                 || mPaddingBottom != 0) {
19550             output = debugIndent(depth);
19551             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19552                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19553             Log.d(VIEW_LOG_TAG, output);
19554         }
19555 
19556         output = debugIndent(depth);
19557         output += "mMeasureWidth=" + mMeasuredWidth +
19558                 " mMeasureHeight=" + mMeasuredHeight;
19559         Log.d(VIEW_LOG_TAG, output);
19560 
19561         output = debugIndent(depth);
19562         if (mLayoutParams == null) {
19563             output += "BAD! no layout params";
19564         } else {
19565             output = mLayoutParams.debug(output);
19566         }
19567         Log.d(VIEW_LOG_TAG, output);
19568 
19569         output = debugIndent(depth);
19570         output += "flags={";
19571         output += View.printFlags(mViewFlags);
19572         output += "}";
19573         Log.d(VIEW_LOG_TAG, output);
19574 
19575         output = debugIndent(depth);
19576         output += "privateFlags={";
19577         output += View.printPrivateFlags(mPrivateFlags);
19578         output += "}";
19579         Log.d(VIEW_LOG_TAG, output);
19580     }
19581 
19582     /**
19583      * Creates a string of whitespaces used for indentation.
19584      *
19585      * @param depth the indentation level
19586      * @return a String containing (depth * 2 + 3) * 2 white spaces
19587      *
19588      * @hide
19589      */
debugIndent(int depth)19590     protected static String debugIndent(int depth) {
19591         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19592         for (int i = 0; i < (depth * 2) + 3; i++) {
19593             spaces.append(' ').append(' ');
19594         }
19595         return spaces.toString();
19596     }
19597 
19598     /**
19599      * <p>Return the offset of the widget's text baseline from the widget's top
19600      * boundary. If this widget does not support baseline alignment, this
19601      * method returns -1. </p>
19602      *
19603      * @return the offset of the baseline within the widget's bounds or -1
19604      *         if baseline alignment is not supported
19605      */
19606     @ViewDebug.ExportedProperty(category = "layout")
getBaseline()19607     public int getBaseline() {
19608         return -1;
19609     }
19610 
19611     /**
19612      * Returns whether the view hierarchy is currently undergoing a layout pass. This
19613      * information is useful to avoid situations such as calling {@link #requestLayout()} during
19614      * a layout pass.
19615      *
19616      * @return whether the view hierarchy is currently undergoing a layout pass
19617      */
isInLayout()19618     public boolean isInLayout() {
19619         ViewRootImpl viewRoot = getViewRootImpl();
19620         return (viewRoot != null && viewRoot.isInLayout());
19621     }
19622 
19623     /**
19624      * Call this when something has changed which has invalidated the
19625      * layout of this view. This will schedule a layout pass of the view
19626      * tree. This should not be called while the view hierarchy is currently in a layout
19627      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19628      * end of the current layout pass (and then layout will run again) or after the current
19629      * frame is drawn and the next layout occurs.
19630      *
19631      * <p>Subclasses which override this method should call the superclass method to
19632      * handle possible request-during-layout errors correctly.</p>
19633      */
19634     @CallSuper
requestLayout()19635     public void requestLayout() {
19636         if (mMeasureCache != null) mMeasureCache.clear();
19637 
19638         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19639             // Only trigger request-during-layout logic if this is the view requesting it,
19640             // not the views in its parent hierarchy
19641             ViewRootImpl viewRoot = getViewRootImpl();
19642             if (viewRoot != null && viewRoot.isInLayout()) {
19643                 if (!viewRoot.requestLayoutDuringLayout(this)) {
19644                     return;
19645                 }
19646             }
19647             mAttachInfo.mViewRequestingLayout = this;
19648         }
19649 
19650         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19651         mPrivateFlags |= PFLAG_INVALIDATED;
19652 
19653         if (mParent != null && !mParent.isLayoutRequested()) {
19654             mParent.requestLayout();
19655         }
19656         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19657             mAttachInfo.mViewRequestingLayout = null;
19658         }
19659     }
19660 
19661     /**
19662      * Forces this view to be laid out during the next layout pass.
19663      * This method does not call requestLayout() or forceLayout()
19664      * on the parent.
19665      */
forceLayout()19666     public void forceLayout() {
19667         if (mMeasureCache != null) mMeasureCache.clear();
19668 
19669         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19670         mPrivateFlags |= PFLAG_INVALIDATED;
19671     }
19672 
19673     /**
19674      * <p>
19675      * This is called to find out how big a view should be. The parent
19676      * supplies constraint information in the width and height parameters.
19677      * </p>
19678      *
19679      * <p>
19680      * The actual measurement work of a view is performed in
19681      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19682      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19683      * </p>
19684      *
19685      *
19686      * @param widthMeasureSpec Horizontal space requirements as imposed by the
19687      *        parent
19688      * @param heightMeasureSpec Vertical space requirements as imposed by the
19689      *        parent
19690      *
19691      * @see #onMeasure(int, int)
19692      */
measure(int widthMeasureSpec, int heightMeasureSpec)19693     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19694         boolean optical = isLayoutModeOptical(this);
19695         if (optical != isLayoutModeOptical(mParent)) {
19696             Insets insets = getOpticalInsets();
19697             int oWidth  = insets.left + insets.right;
19698             int oHeight = insets.top  + insets.bottom;
19699             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19700             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19701         }
19702 
19703         // Suppress sign extension for the low bytes
19704         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19705         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19706 
19707         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19708 
19709         // Optimize layout by avoiding an extra EXACTLY pass when the view is
19710         // already measured as the correct size. In API 23 and below, this
19711         // extra pass is required to make LinearLayout re-distribute weight.
19712         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19713                 || heightMeasureSpec != mOldHeightMeasureSpec;
19714         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19715                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19716         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19717                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19718         final boolean needsLayout = specChanged
19719                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19720 
19721         if (forceLayout || needsLayout) {
19722             // first clears the measured dimension flag
19723             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19724 
19725             resolveRtlPropertiesIfNeeded();
19726 
19727             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19728             if (cacheIndex < 0 || sIgnoreMeasureCache) {
19729                 // measure ourselves, this should set the measured dimension flag back
19730                 onMeasure(widthMeasureSpec, heightMeasureSpec);
19731                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19732             } else {
19733                 long value = mMeasureCache.valueAt(cacheIndex);
19734                 // Casting a long to int drops the high 32 bits, no mask needed
19735                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19736                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19737             }
19738 
19739             // flag not set, setMeasuredDimension() was not invoked, we raise
19740             // an exception to warn the developer
19741             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19742                 throw new IllegalStateException("View with id " + getId() + ": "
19743                         + getClass().getName() + "#onMeasure() did not set the"
19744                         + " measured dimension by calling"
19745                         + " setMeasuredDimension()");
19746             }
19747 
19748             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19749         }
19750 
19751         mOldWidthMeasureSpec = widthMeasureSpec;
19752         mOldHeightMeasureSpec = heightMeasureSpec;
19753 
19754         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19755                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19756     }
19757 
19758     /**
19759      * <p>
19760      * Measure the view and its content to determine the measured width and the
19761      * measured height. This method is invoked by {@link #measure(int, int)} and
19762      * should be overridden by subclasses to provide accurate and efficient
19763      * measurement of their contents.
19764      * </p>
19765      *
19766      * <p>
19767      * <strong>CONTRACT:</strong> When overriding this method, you
19768      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19769      * measured width and height of this view. Failure to do so will trigger an
19770      * <code>IllegalStateException</code>, thrown by
19771      * {@link #measure(int, int)}. Calling the superclass'
19772      * {@link #onMeasure(int, int)} is a valid use.
19773      * </p>
19774      *
19775      * <p>
19776      * The base class implementation of measure defaults to the background size,
19777      * unless a larger size is allowed by the MeasureSpec. Subclasses should
19778      * override {@link #onMeasure(int, int)} to provide better measurements of
19779      * their content.
19780      * </p>
19781      *
19782      * <p>
19783      * If this method is overridden, it is the subclass's responsibility to make
19784      * sure the measured height and width are at least the view's minimum height
19785      * and width ({@link #getSuggestedMinimumHeight()} and
19786      * {@link #getSuggestedMinimumWidth()}).
19787      * </p>
19788      *
19789      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19790      *                         The requirements are encoded with
19791      *                         {@link android.view.View.MeasureSpec}.
19792      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19793      *                         The requirements are encoded with
19794      *                         {@link android.view.View.MeasureSpec}.
19795      *
19796      * @see #getMeasuredWidth()
19797      * @see #getMeasuredHeight()
19798      * @see #setMeasuredDimension(int, int)
19799      * @see #getSuggestedMinimumHeight()
19800      * @see #getSuggestedMinimumWidth()
19801      * @see android.view.View.MeasureSpec#getMode(int)
19802      * @see android.view.View.MeasureSpec#getSize(int)
19803      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)19804     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19805         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19806                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19807     }
19808 
19809     /**
19810      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19811      * measured width and measured height. Failing to do so will trigger an
19812      * exception at measurement time.</p>
19813      *
19814      * @param measuredWidth The measured width of this view.  May be a complex
19815      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19816      * {@link #MEASURED_STATE_TOO_SMALL}.
19817      * @param measuredHeight The measured height of this view.  May be a complex
19818      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19819      * {@link #MEASURED_STATE_TOO_SMALL}.
19820      */
setMeasuredDimension(int measuredWidth, int measuredHeight)19821     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19822         boolean optical = isLayoutModeOptical(this);
19823         if (optical != isLayoutModeOptical(mParent)) {
19824             Insets insets = getOpticalInsets();
19825             int opticalWidth  = insets.left + insets.right;
19826             int opticalHeight = insets.top  + insets.bottom;
19827 
19828             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19829             measuredHeight += optical ? opticalHeight : -opticalHeight;
19830         }
19831         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19832     }
19833 
19834     /**
19835      * Sets the measured dimension without extra processing for things like optical bounds.
19836      * Useful for reapplying consistent values that have already been cooked with adjustments
19837      * for optical bounds, etc. such as those from the measurement cache.
19838      *
19839      * @param measuredWidth The measured width of this view.  May be a complex
19840      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19841      * {@link #MEASURED_STATE_TOO_SMALL}.
19842      * @param measuredHeight The measured height of this view.  May be a complex
19843      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19844      * {@link #MEASURED_STATE_TOO_SMALL}.
19845      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)19846     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19847         mMeasuredWidth = measuredWidth;
19848         mMeasuredHeight = measuredHeight;
19849 
19850         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19851     }
19852 
19853     /**
19854      * Merge two states as returned by {@link #getMeasuredState()}.
19855      * @param curState The current state as returned from a view or the result
19856      * of combining multiple views.
19857      * @param newState The new view state to combine.
19858      * @return Returns a new integer reflecting the combination of the two
19859      * states.
19860      */
combineMeasuredStates(int curState, int newState)19861     public static int combineMeasuredStates(int curState, int newState) {
19862         return curState | newState;
19863     }
19864 
19865     /**
19866      * Version of {@link #resolveSizeAndState(int, int, int)}
19867      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19868      */
resolveSize(int size, int measureSpec)19869     public static int resolveSize(int size, int measureSpec) {
19870         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19871     }
19872 
19873     /**
19874      * Utility to reconcile a desired size and state, with constraints imposed
19875      * by a MeasureSpec. Will take the desired size, unless a different size
19876      * is imposed by the constraints. The returned value is a compound integer,
19877      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19878      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19879      * resulting size is smaller than the size the view wants to be.
19880      *
19881      * @param size How big the view wants to be.
19882      * @param measureSpec Constraints imposed by the parent.
19883      * @param childMeasuredState Size information bit mask for the view's
19884      *                           children.
19885      * @return Size information bit mask as defined by
19886      *         {@link #MEASURED_SIZE_MASK} and
19887      *         {@link #MEASURED_STATE_TOO_SMALL}.
19888      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)19889     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19890         final int specMode = MeasureSpec.getMode(measureSpec);
19891         final int specSize = MeasureSpec.getSize(measureSpec);
19892         final int result;
19893         switch (specMode) {
19894             case MeasureSpec.AT_MOST:
19895                 if (specSize < size) {
19896                     result = specSize | MEASURED_STATE_TOO_SMALL;
19897                 } else {
19898                     result = size;
19899                 }
19900                 break;
19901             case MeasureSpec.EXACTLY:
19902                 result = specSize;
19903                 break;
19904             case MeasureSpec.UNSPECIFIED:
19905             default:
19906                 result = size;
19907         }
19908         return result | (childMeasuredState & MEASURED_STATE_MASK);
19909     }
19910 
19911     /**
19912      * Utility to return a default size. Uses the supplied size if the
19913      * MeasureSpec imposed no constraints. Will get larger if allowed
19914      * by the MeasureSpec.
19915      *
19916      * @param size Default size for this view
19917      * @param measureSpec Constraints imposed by the parent
19918      * @return The size this view should be.
19919      */
getDefaultSize(int size, int measureSpec)19920     public static int getDefaultSize(int size, int measureSpec) {
19921         int result = size;
19922         int specMode = MeasureSpec.getMode(measureSpec);
19923         int specSize = MeasureSpec.getSize(measureSpec);
19924 
19925         switch (specMode) {
19926         case MeasureSpec.UNSPECIFIED:
19927             result = size;
19928             break;
19929         case MeasureSpec.AT_MOST:
19930         case MeasureSpec.EXACTLY:
19931             result = specSize;
19932             break;
19933         }
19934         return result;
19935     }
19936 
19937     /**
19938      * Returns the suggested minimum height that the view should use. This
19939      * returns the maximum of the view's minimum height
19940      * and the background's minimum height
19941      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19942      * <p>
19943      * When being used in {@link #onMeasure(int, int)}, the caller should still
19944      * ensure the returned height is within the requirements of the parent.
19945      *
19946      * @return The suggested minimum height of the view.
19947      */
getSuggestedMinimumHeight()19948     protected int getSuggestedMinimumHeight() {
19949         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19950 
19951     }
19952 
19953     /**
19954      * Returns the suggested minimum width that the view should use. This
19955      * returns the maximum of the view's minimum width
19956      * and the background's minimum width
19957      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19958      * <p>
19959      * When being used in {@link #onMeasure(int, int)}, the caller should still
19960      * ensure the returned width is within the requirements of the parent.
19961      *
19962      * @return The suggested minimum width of the view.
19963      */
getSuggestedMinimumWidth()19964     protected int getSuggestedMinimumWidth() {
19965         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19966     }
19967 
19968     /**
19969      * Returns the minimum height of the view.
19970      *
19971      * @return the minimum height the view will try to be.
19972      *
19973      * @see #setMinimumHeight(int)
19974      *
19975      * @attr ref android.R.styleable#View_minHeight
19976      */
getMinimumHeight()19977     public int getMinimumHeight() {
19978         return mMinHeight;
19979     }
19980 
19981     /**
19982      * Sets the minimum height of the view. It is not guaranteed the view will
19983      * be able to achieve this minimum height (for example, if its parent layout
19984      * constrains it with less available height).
19985      *
19986      * @param minHeight The minimum height the view will try to be.
19987      *
19988      * @see #getMinimumHeight()
19989      *
19990      * @attr ref android.R.styleable#View_minHeight
19991      */
19992     @RemotableViewMethod
setMinimumHeight(int minHeight)19993     public void setMinimumHeight(int minHeight) {
19994         mMinHeight = minHeight;
19995         requestLayout();
19996     }
19997 
19998     /**
19999      * Returns the minimum width of the view.
20000      *
20001      * @return the minimum width the view will try to be.
20002      *
20003      * @see #setMinimumWidth(int)
20004      *
20005      * @attr ref android.R.styleable#View_minWidth
20006      */
getMinimumWidth()20007     public int getMinimumWidth() {
20008         return mMinWidth;
20009     }
20010 
20011     /**
20012      * Sets the minimum width of the view. It is not guaranteed the view will
20013      * be able to achieve this minimum width (for example, if its parent layout
20014      * constrains it with less available width).
20015      *
20016      * @param minWidth The minimum width the view will try to be.
20017      *
20018      * @see #getMinimumWidth()
20019      *
20020      * @attr ref android.R.styleable#View_minWidth
20021      */
setMinimumWidth(int minWidth)20022     public void setMinimumWidth(int minWidth) {
20023         mMinWidth = minWidth;
20024         requestLayout();
20025 
20026     }
20027 
20028     /**
20029      * Get the animation currently associated with this view.
20030      *
20031      * @return The animation that is currently playing or
20032      *         scheduled to play for this view.
20033      */
getAnimation()20034     public Animation getAnimation() {
20035         return mCurrentAnimation;
20036     }
20037 
20038     /**
20039      * Start the specified animation now.
20040      *
20041      * @param animation the animation to start now
20042      */
startAnimation(Animation animation)20043     public void startAnimation(Animation animation) {
20044         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20045         setAnimation(animation);
20046         invalidateParentCaches();
20047         invalidate(true);
20048     }
20049 
20050     /**
20051      * Cancels any animations for this view.
20052      */
clearAnimation()20053     public void clearAnimation() {
20054         if (mCurrentAnimation != null) {
20055             mCurrentAnimation.detach();
20056         }
20057         mCurrentAnimation = null;
20058         invalidateParentIfNeeded();
20059     }
20060 
20061     /**
20062      * Sets the next animation to play for this view.
20063      * If you want the animation to play immediately, use
20064      * {@link #startAnimation(android.view.animation.Animation)} instead.
20065      * This method provides allows fine-grained
20066      * control over the start time and invalidation, but you
20067      * must make sure that 1) the animation has a start time set, and
20068      * 2) the view's parent (which controls animations on its children)
20069      * will be invalidated when the animation is supposed to
20070      * start.
20071      *
20072      * @param animation The next animation, or null.
20073      */
setAnimation(Animation animation)20074     public void setAnimation(Animation animation) {
20075         mCurrentAnimation = animation;
20076 
20077         if (animation != null) {
20078             // If the screen is off assume the animation start time is now instead of
20079             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20080             // would cause the animation to start when the screen turns back on
20081             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20082                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20083                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20084             }
20085             animation.reset();
20086         }
20087     }
20088 
20089     /**
20090      * Invoked by a parent ViewGroup to notify the start of the animation
20091      * currently associated with this view. If you override this method,
20092      * always call super.onAnimationStart();
20093      *
20094      * @see #setAnimation(android.view.animation.Animation)
20095      * @see #getAnimation()
20096      */
20097     @CallSuper
onAnimationStart()20098     protected void onAnimationStart() {
20099         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20100     }
20101 
20102     /**
20103      * Invoked by a parent ViewGroup to notify the end of the animation
20104      * currently associated with this view. If you override this method,
20105      * always call super.onAnimationEnd();
20106      *
20107      * @see #setAnimation(android.view.animation.Animation)
20108      * @see #getAnimation()
20109      */
20110     @CallSuper
onAnimationEnd()20111     protected void onAnimationEnd() {
20112         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20113     }
20114 
20115     /**
20116      * Invoked if there is a Transform that involves alpha. Subclass that can
20117      * draw themselves with the specified alpha should return true, and then
20118      * respect that alpha when their onDraw() is called. If this returns false
20119      * then the view may be redirected to draw into an offscreen buffer to
20120      * fulfill the request, which will look fine, but may be slower than if the
20121      * subclass handles it internally. The default implementation returns false.
20122      *
20123      * @param alpha The alpha (0..255) to apply to the view's drawing
20124      * @return true if the view can draw with the specified alpha.
20125      */
onSetAlpha(int alpha)20126     protected boolean onSetAlpha(int alpha) {
20127         return false;
20128     }
20129 
20130     /**
20131      * This is used by the RootView to perform an optimization when
20132      * the view hierarchy contains one or several SurfaceView.
20133      * SurfaceView is always considered transparent, but its children are not,
20134      * therefore all View objects remove themselves from the global transparent
20135      * region (passed as a parameter to this function).
20136      *
20137      * @param region The transparent region for this ViewAncestor (window).
20138      *
20139      * @return Returns true if the effective visibility of the view at this
20140      * point is opaque, regardless of the transparent region; returns false
20141      * if it is possible for underlying windows to be seen behind the view.
20142      *
20143      * {@hide}
20144      */
gatherTransparentRegion(Region region)20145     public boolean gatherTransparentRegion(Region region) {
20146         final AttachInfo attachInfo = mAttachInfo;
20147         if (region != null && attachInfo != null) {
20148             final int pflags = mPrivateFlags;
20149             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20150                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20151                 // remove it from the transparent region.
20152                 final int[] location = attachInfo.mTransparentLocation;
20153                 getLocationInWindow(location);
20154                 region.op(location[0], location[1], location[0] + mRight - mLeft,
20155                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
20156             } else {
20157                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20158                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20159                     // the background drawable's non-transparent parts from this transparent region.
20160                     applyDrawableToTransparentRegion(mBackground, region);
20161                 }
20162                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20163                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20164                     // Similarly, we remove the foreground drawable's non-transparent parts.
20165                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20166                 }
20167             }
20168         }
20169         return true;
20170     }
20171 
20172     /**
20173      * Play a sound effect for this view.
20174      *
20175      * <p>The framework will play sound effects for some built in actions, such as
20176      * clicking, but you may wish to play these effects in your widget,
20177      * for instance, for internal navigation.
20178      *
20179      * <p>The sound effect will only be played if sound effects are enabled by the user, and
20180      * {@link #isSoundEffectsEnabled()} is true.
20181      *
20182      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20183      */
playSoundEffect(int soundConstant)20184     public void playSoundEffect(int soundConstant) {
20185         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20186             return;
20187         }
20188         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20189     }
20190 
20191     /**
20192      * BZZZTT!!1!
20193      *
20194      * <p>Provide haptic feedback to the user for this view.
20195      *
20196      * <p>The framework will provide haptic feedback for some built in actions,
20197      * such as long presses, but you may wish to provide feedback for your
20198      * own widget.
20199      *
20200      * <p>The feedback will only be performed if
20201      * {@link #isHapticFeedbackEnabled()} is true.
20202      *
20203      * @param feedbackConstant One of the constants defined in
20204      * {@link HapticFeedbackConstants}
20205      */
performHapticFeedback(int feedbackConstant)20206     public boolean performHapticFeedback(int feedbackConstant) {
20207         return performHapticFeedback(feedbackConstant, 0);
20208     }
20209 
20210     /**
20211      * BZZZTT!!1!
20212      *
20213      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20214      *
20215      * @param feedbackConstant One of the constants defined in
20216      * {@link HapticFeedbackConstants}
20217      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20218      */
performHapticFeedback(int feedbackConstant, int flags)20219     public boolean performHapticFeedback(int feedbackConstant, int flags) {
20220         if (mAttachInfo == null) {
20221             return false;
20222         }
20223         //noinspection SimplifiableIfStatement
20224         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20225                 && !isHapticFeedbackEnabled()) {
20226             return false;
20227         }
20228         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20229                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20230     }
20231 
20232     /**
20233      * Request that the visibility of the status bar or other screen/window
20234      * decorations be changed.
20235      *
20236      * <p>This method is used to put the over device UI into temporary modes
20237      * where the user's attention is focused more on the application content,
20238      * by dimming or hiding surrounding system affordances.  This is typically
20239      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20240      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20241      * to be placed behind the action bar (and with these flags other system
20242      * affordances) so that smooth transitions between hiding and showing them
20243      * can be done.
20244      *
20245      * <p>Two representative examples of the use of system UI visibility is
20246      * implementing a content browsing application (like a magazine reader)
20247      * and a video playing application.
20248      *
20249      * <p>The first code shows a typical implementation of a View in a content
20250      * browsing application.  In this implementation, the application goes
20251      * into a content-oriented mode by hiding the status bar and action bar,
20252      * and putting the navigation elements into lights out mode.  The user can
20253      * then interact with content while in this mode.  Such an application should
20254      * provide an easy way for the user to toggle out of the mode (such as to
20255      * check information in the status bar or access notifications).  In the
20256      * implementation here, this is done simply by tapping on the content.
20257      *
20258      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20259      *      content}
20260      *
20261      * <p>This second code sample shows a typical implementation of a View
20262      * in a video playing application.  In this situation, while the video is
20263      * playing the application would like to go into a complete full-screen mode,
20264      * to use as much of the display as possible for the video.  When in this state
20265      * the user can not interact with the application; the system intercepts
20266      * touching on the screen to pop the UI out of full screen mode.  See
20267      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20268      *
20269      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20270      *      content}
20271      *
20272      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20273      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20274      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20275      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20276      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20277      */
setSystemUiVisibility(int visibility)20278     public void setSystemUiVisibility(int visibility) {
20279         if (visibility != mSystemUiVisibility) {
20280             mSystemUiVisibility = visibility;
20281             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20282                 mParent.recomputeViewAttributes(this);
20283             }
20284         }
20285     }
20286 
20287     /**
20288      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20289      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20290      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20291      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20292      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20293      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20294      */
getSystemUiVisibility()20295     public int getSystemUiVisibility() {
20296         return mSystemUiVisibility;
20297     }
20298 
20299     /**
20300      * Returns the current system UI visibility that is currently set for
20301      * the entire window.  This is the combination of the
20302      * {@link #setSystemUiVisibility(int)} values supplied by all of the
20303      * views in the window.
20304      */
getWindowSystemUiVisibility()20305     public int getWindowSystemUiVisibility() {
20306         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20307     }
20308 
20309     /**
20310      * Override to find out when the window's requested system UI visibility
20311      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20312      * This is different from the callbacks received through
20313      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20314      * in that this is only telling you about the local request of the window,
20315      * not the actual values applied by the system.
20316      */
onWindowSystemUiVisibilityChanged(int visible)20317     public void onWindowSystemUiVisibilityChanged(int visible) {
20318     }
20319 
20320     /**
20321      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20322      * the view hierarchy.
20323      */
dispatchWindowSystemUiVisiblityChanged(int visible)20324     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20325         onWindowSystemUiVisibilityChanged(visible);
20326     }
20327 
20328     /**
20329      * Set a listener to receive callbacks when the visibility of the system bar changes.
20330      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20331      */
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)20332     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20333         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20334         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20335             mParent.recomputeViewAttributes(this);
20336         }
20337     }
20338 
20339     /**
20340      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20341      * the view hierarchy.
20342      */
dispatchSystemUiVisibilityChanged(int visibility)20343     public void dispatchSystemUiVisibilityChanged(int visibility) {
20344         ListenerInfo li = mListenerInfo;
20345         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20346             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20347                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20348         }
20349     }
20350 
updateLocalSystemUiVisibility(int localValue, int localChanges)20351     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20352         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20353         if (val != mSystemUiVisibility) {
20354             setSystemUiVisibility(val);
20355             return true;
20356         }
20357         return false;
20358     }
20359 
20360     /** @hide */
setDisabledSystemUiVisibility(int flags)20361     public void setDisabledSystemUiVisibility(int flags) {
20362         if (mAttachInfo != null) {
20363             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20364                 mAttachInfo.mDisabledSystemUiVisibility = flags;
20365                 if (mParent != null) {
20366                     mParent.recomputeViewAttributes(this);
20367                 }
20368             }
20369         }
20370     }
20371 
20372     /**
20373      * Creates an image that the system displays during the drag and drop
20374      * operation. This is called a &quot;drag shadow&quot;. The default implementation
20375      * for a DragShadowBuilder based on a View returns an image that has exactly the same
20376      * appearance as the given View. The default also positions the center of the drag shadow
20377      * directly under the touch point. If no View is provided (the constructor with no parameters
20378      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20379      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20380      * default is an invisible drag shadow.
20381      * <p>
20382      * You are not required to use the View you provide to the constructor as the basis of the
20383      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20384      * anything you want as the drag shadow.
20385      * </p>
20386      * <p>
20387      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20388      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20389      *  size and position of the drag shadow. It uses this data to construct a
20390      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20391      *  so that your application can draw the shadow image in the Canvas.
20392      * </p>
20393      *
20394      * <div class="special reference">
20395      * <h3>Developer Guides</h3>
20396      * <p>For a guide to implementing drag and drop features, read the
20397      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20398      * </div>
20399      */
20400     public static class DragShadowBuilder {
20401         private final WeakReference<View> mView;
20402 
20403         /**
20404          * Constructs a shadow image builder based on a View. By default, the resulting drag
20405          * shadow will have the same appearance and dimensions as the View, with the touch point
20406          * over the center of the View.
20407          * @param view A View. Any View in scope can be used.
20408          */
DragShadowBuilder(View view)20409         public DragShadowBuilder(View view) {
20410             mView = new WeakReference<View>(view);
20411         }
20412 
20413         /**
20414          * Construct a shadow builder object with no associated View.  This
20415          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20416          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20417          * to supply the drag shadow's dimensions and appearance without
20418          * reference to any View object. If they are not overridden, then the result is an
20419          * invisible drag shadow.
20420          */
DragShadowBuilder()20421         public DragShadowBuilder() {
20422             mView = new WeakReference<View>(null);
20423         }
20424 
20425         /**
20426          * Returns the View object that had been passed to the
20427          * {@link #View.DragShadowBuilder(View)}
20428          * constructor.  If that View parameter was {@code null} or if the
20429          * {@link #View.DragShadowBuilder()}
20430          * constructor was used to instantiate the builder object, this method will return
20431          * null.
20432          *
20433          * @return The View object associate with this builder object.
20434          */
20435         @SuppressWarnings({"JavadocReference"})
getView()20436         final public View getView() {
20437             return mView.get();
20438         }
20439 
20440         /**
20441          * Provides the metrics for the shadow image. These include the dimensions of
20442          * the shadow image, and the point within that shadow that should
20443          * be centered under the touch location while dragging.
20444          * <p>
20445          * The default implementation sets the dimensions of the shadow to be the
20446          * same as the dimensions of the View itself and centers the shadow under
20447          * the touch point.
20448          * </p>
20449          *
20450          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20451          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20452          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20453          * image.
20454          *
20455          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20456          * shadow image that should be underneath the touch point during the drag and drop
20457          * operation. Your application must set {@link android.graphics.Point#x} to the
20458          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20459          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)20460         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20461             final View view = mView.get();
20462             if (view != null) {
20463                 outShadowSize.set(view.getWidth(), view.getHeight());
20464                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20465             } else {
20466                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20467             }
20468         }
20469 
20470         /**
20471          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20472          * based on the dimensions it received from the
20473          * {@link #onProvideShadowMetrics(Point, Point)} callback.
20474          *
20475          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20476          */
onDrawShadow(Canvas canvas)20477         public void onDrawShadow(Canvas canvas) {
20478             final View view = mView.get();
20479             if (view != null) {
20480                 view.draw(canvas);
20481             } else {
20482                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20483             }
20484         }
20485     }
20486 
20487     /**
20488      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20489      * startDragAndDrop()} for newer platform versions.
20490      */
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20491     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20492                                    Object myLocalState, int flags) {
20493         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20494     }
20495 
20496     /**
20497      * Starts a drag and drop operation. When your application calls this method, it passes a
20498      * {@link android.view.View.DragShadowBuilder} object to the system. The
20499      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20500      * to get metrics for the drag shadow, and then calls the object's
20501      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20502      * <p>
20503      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
20504      *  drag events to all the View objects in your application that are currently visible. It does
20505      *  this either by calling the View object's drag listener (an implementation of
20506      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20507      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20508      *  Both are passed a {@link android.view.DragEvent} object that has a
20509      *  {@link android.view.DragEvent#getAction()} value of
20510      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20511      * </p>
20512      * <p>
20513      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20514      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20515      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20516      * to the View the user selected for dragging.
20517      * </p>
20518      * @param data A {@link android.content.ClipData} object pointing to the data to be
20519      * transferred by the drag and drop operation.
20520      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20521      * drag shadow.
20522      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20523      * drop operation. This Object is put into every DragEvent object sent by the system during the
20524      * current drag.
20525      * <p>
20526      * myLocalState is a lightweight mechanism for the sending information from the dragged View
20527      * to the target Views. For example, it can contain flags that differentiate between a
20528      * a copy operation and a move operation.
20529      * </p>
20530      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20531      * flags, or any combination of the following:
20532      *     <ul>
20533      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
20534      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20535      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20536      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20537      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20538      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20539      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
20540      *     </ul>
20541      * @return {@code true} if the method completes successfully, or
20542      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20543      * do a drag, and so no drag operation is in progress.
20544      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20545     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20546             Object myLocalState, int flags) {
20547         if (ViewDebug.DEBUG_DRAG) {
20548             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20549         }
20550         if (mAttachInfo == null) {
20551             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20552             return false;
20553         }
20554         boolean okay = false;
20555 
20556         Point shadowSize = new Point();
20557         Point shadowTouchPoint = new Point();
20558         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20559 
20560         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20561                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20562             throw new IllegalStateException("Drag shadow dimensions must not be negative");
20563         }
20564 
20565         if (ViewDebug.DEBUG_DRAG) {
20566             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20567                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20568         }
20569         if (mAttachInfo.mDragSurface != null) {
20570             mAttachInfo.mDragSurface.release();
20571         }
20572         mAttachInfo.mDragSurface = new Surface();
20573         try {
20574             mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20575                     flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20576             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20577                     + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20578             if (mAttachInfo.mDragToken != null) {
20579                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20580                 try {
20581                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20582                     shadowBuilder.onDrawShadow(canvas);
20583                 } finally {
20584                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20585                 }
20586 
20587                 final ViewRootImpl root = getViewRootImpl();
20588 
20589                 // Cache the local state object for delivery with DragEvents
20590                 root.setLocalDragState(myLocalState);
20591 
20592                 // repurpose 'shadowSize' for the last touch point
20593                 root.getLastTouchPoint(shadowSize);
20594 
20595                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20596                         root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20597                         shadowTouchPoint.x, shadowTouchPoint.y, data);
20598                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20599             }
20600         } catch (Exception e) {
20601             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20602             mAttachInfo.mDragSurface.destroy();
20603             mAttachInfo.mDragSurface = null;
20604         }
20605 
20606         return okay;
20607     }
20608 
20609     /**
20610      * Cancels an ongoing drag and drop operation.
20611      * <p>
20612      * A {@link android.view.DragEvent} object with
20613      * {@link android.view.DragEvent#getAction()} value of
20614      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20615      * {@link android.view.DragEvent#getResult()} value of {@code false}
20616      * will be sent to every
20617      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20618      * even if they are not currently visible.
20619      * </p>
20620      * <p>
20621      * This method can be called on any View in the same window as the View on which
20622      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20623      * was called.
20624      * </p>
20625      */
cancelDragAndDrop()20626     public final void cancelDragAndDrop() {
20627         if (ViewDebug.DEBUG_DRAG) {
20628             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20629         }
20630         if (mAttachInfo == null) {
20631             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20632             return;
20633         }
20634         if (mAttachInfo.mDragToken != null) {
20635             try {
20636                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20637             } catch (Exception e) {
20638                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20639             }
20640             mAttachInfo.mDragToken = null;
20641         } else {
20642             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20643         }
20644     }
20645 
20646     /**
20647      * Updates the drag shadow for the ongoing drag and drop operation.
20648      *
20649      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20650      * new drag shadow.
20651      */
updateDragShadow(DragShadowBuilder shadowBuilder)20652     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20653         if (ViewDebug.DEBUG_DRAG) {
20654             Log.d(VIEW_LOG_TAG, "updateDragShadow");
20655         }
20656         if (mAttachInfo == null) {
20657             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20658             return;
20659         }
20660         if (mAttachInfo.mDragToken != null) {
20661             try {
20662                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20663                 try {
20664                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20665                     shadowBuilder.onDrawShadow(canvas);
20666                 } finally {
20667                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20668                 }
20669             } catch (Exception e) {
20670                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20671             }
20672         } else {
20673             Log.e(VIEW_LOG_TAG, "No active drag");
20674         }
20675     }
20676 
20677     /**
20678      * Starts a move from {startX, startY}, the amount of the movement will be the offset
20679      * between {startX, startY} and the new cursor positon.
20680      * @param startX horizontal coordinate where the move started.
20681      * @param startY vertical coordinate where the move started.
20682      * @return whether moving was started successfully.
20683      * @hide
20684      */
startMovingTask(float startX, float startY)20685     public final boolean startMovingTask(float startX, float startY) {
20686         if (ViewDebug.DEBUG_POSITIONING) {
20687             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20688         }
20689         try {
20690             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20691         } catch (RemoteException e) {
20692             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20693         }
20694         return false;
20695     }
20696 
20697     /**
20698      * Handles drag events sent by the system following a call to
20699      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20700      * startDragAndDrop()}.
20701      *<p>
20702      * When the system calls this method, it passes a
20703      * {@link android.view.DragEvent} object. A call to
20704      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20705      * in DragEvent. The method uses these to determine what is happening in the drag and drop
20706      * operation.
20707      * @param event The {@link android.view.DragEvent} sent by the system.
20708      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20709      * in DragEvent, indicating the type of drag event represented by this object.
20710      * @return {@code true} if the method was successful, otherwise {@code false}.
20711      * <p>
20712      *  The method should return {@code true} in response to an action type of
20713      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20714      *  operation.
20715      * </p>
20716      * <p>
20717      *  The method should also return {@code true} in response to an action type of
20718      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20719      *  {@code false} if it didn't.
20720      * </p>
20721      */
onDragEvent(DragEvent event)20722     public boolean onDragEvent(DragEvent event) {
20723         return false;
20724     }
20725 
20726     /**
20727      * Detects if this View is enabled and has a drag event listener.
20728      * If both are true, then it calls the drag event listener with the
20729      * {@link android.view.DragEvent} it received. If the drag event listener returns
20730      * {@code true}, then dispatchDragEvent() returns {@code true}.
20731      * <p>
20732      * For all other cases, the method calls the
20733      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20734      * method and returns its result.
20735      * </p>
20736      * <p>
20737      * This ensures that a drag event is always consumed, even if the View does not have a drag
20738      * event listener. However, if the View has a listener and the listener returns true, then
20739      * onDragEvent() is not called.
20740      * </p>
20741      */
dispatchDragEvent(DragEvent event)20742     public boolean dispatchDragEvent(DragEvent event) {
20743         ListenerInfo li = mListenerInfo;
20744         //noinspection SimplifiableIfStatement
20745         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20746                 && li.mOnDragListener.onDrag(this, event)) {
20747             return true;
20748         }
20749         return onDragEvent(event);
20750     }
20751 
canAcceptDrag()20752     boolean canAcceptDrag() {
20753         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20754     }
20755 
20756     /**
20757      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20758      * it is ever exposed at all.
20759      * @hide
20760      */
onCloseSystemDialogs(String reason)20761     public void onCloseSystemDialogs(String reason) {
20762     }
20763 
20764     /**
20765      * Given a Drawable whose bounds have been set to draw into this view,
20766      * update a Region being computed for
20767      * {@link #gatherTransparentRegion(android.graphics.Region)} so
20768      * that any non-transparent parts of the Drawable are removed from the
20769      * given transparent region.
20770      *
20771      * @param dr The Drawable whose transparency is to be applied to the region.
20772      * @param region A Region holding the current transparency information,
20773      * where any parts of the region that are set are considered to be
20774      * transparent.  On return, this region will be modified to have the
20775      * transparency information reduced by the corresponding parts of the
20776      * Drawable that are not transparent.
20777      * {@hide}
20778      */
applyDrawableToTransparentRegion(Drawable dr, Region region)20779     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20780         if (DBG) {
20781             Log.i("View", "Getting transparent region for: " + this);
20782         }
20783         final Region r = dr.getTransparentRegion();
20784         final Rect db = dr.getBounds();
20785         final AttachInfo attachInfo = mAttachInfo;
20786         if (r != null && attachInfo != null) {
20787             final int w = getRight()-getLeft();
20788             final int h = getBottom()-getTop();
20789             if (db.left > 0) {
20790                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20791                 r.op(0, 0, db.left, h, Region.Op.UNION);
20792             }
20793             if (db.right < w) {
20794                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20795                 r.op(db.right, 0, w, h, Region.Op.UNION);
20796             }
20797             if (db.top > 0) {
20798                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20799                 r.op(0, 0, w, db.top, Region.Op.UNION);
20800             }
20801             if (db.bottom < h) {
20802                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20803                 r.op(0, db.bottom, w, h, Region.Op.UNION);
20804             }
20805             final int[] location = attachInfo.mTransparentLocation;
20806             getLocationInWindow(location);
20807             r.translate(location[0], location[1]);
20808             region.op(r, Region.Op.INTERSECT);
20809         } else {
20810             region.op(db, Region.Op.DIFFERENCE);
20811         }
20812     }
20813 
checkForLongClick(int delayOffset, float x, float y)20814     private void checkForLongClick(int delayOffset, float x, float y) {
20815         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20816             mHasPerformedLongPress = false;
20817 
20818             if (mPendingCheckForLongPress == null) {
20819                 mPendingCheckForLongPress = new CheckForLongPress();
20820             }
20821             mPendingCheckForLongPress.setAnchor(x, y);
20822             mPendingCheckForLongPress.rememberWindowAttachCount();
20823             postDelayed(mPendingCheckForLongPress,
20824                     ViewConfiguration.getLongPressTimeout() - delayOffset);
20825         }
20826     }
20827 
20828     /**
20829      * Inflate a view from an XML resource.  This convenience method wraps the {@link
20830      * LayoutInflater} class, which provides a full range of options for view inflation.
20831      *
20832      * @param context The Context object for your activity or application.
20833      * @param resource The resource ID to inflate
20834      * @param root A view group that will be the parent.  Used to properly inflate the
20835      * layout_* parameters.
20836      * @see LayoutInflater
20837      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)20838     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20839         LayoutInflater factory = LayoutInflater.from(context);
20840         return factory.inflate(resource, root);
20841     }
20842 
20843     /**
20844      * Scroll the view with standard behavior for scrolling beyond the normal
20845      * content boundaries. Views that call this method should override
20846      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20847      * results of an over-scroll operation.
20848      *
20849      * Views can use this method to handle any touch or fling-based scrolling.
20850      *
20851      * @param deltaX Change in X in pixels
20852      * @param deltaY Change in Y in pixels
20853      * @param scrollX Current X scroll value in pixels before applying deltaX
20854      * @param scrollY Current Y scroll value in pixels before applying deltaY
20855      * @param scrollRangeX Maximum content scroll range along the X axis
20856      * @param scrollRangeY Maximum content scroll range along the Y axis
20857      * @param maxOverScrollX Number of pixels to overscroll by in either direction
20858      *          along the X axis.
20859      * @param maxOverScrollY Number of pixels to overscroll by in either direction
20860      *          along the Y axis.
20861      * @param isTouchEvent true if this scroll operation is the result of a touch event.
20862      * @return true if scrolling was clamped to an over-scroll boundary along either
20863      *          axis, false otherwise.
20864      */
20865     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)20866     protected boolean overScrollBy(int deltaX, int deltaY,
20867             int scrollX, int scrollY,
20868             int scrollRangeX, int scrollRangeY,
20869             int maxOverScrollX, int maxOverScrollY,
20870             boolean isTouchEvent) {
20871         final int overScrollMode = mOverScrollMode;
20872         final boolean canScrollHorizontal =
20873                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20874         final boolean canScrollVertical =
20875                 computeVerticalScrollRange() > computeVerticalScrollExtent();
20876         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20877                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20878         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20879                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20880 
20881         int newScrollX = scrollX + deltaX;
20882         if (!overScrollHorizontal) {
20883             maxOverScrollX = 0;
20884         }
20885 
20886         int newScrollY = scrollY + deltaY;
20887         if (!overScrollVertical) {
20888             maxOverScrollY = 0;
20889         }
20890 
20891         // Clamp values if at the limits and record
20892         final int left = -maxOverScrollX;
20893         final int right = maxOverScrollX + scrollRangeX;
20894         final int top = -maxOverScrollY;
20895         final int bottom = maxOverScrollY + scrollRangeY;
20896 
20897         boolean clampedX = false;
20898         if (newScrollX > right) {
20899             newScrollX = right;
20900             clampedX = true;
20901         } else if (newScrollX < left) {
20902             newScrollX = left;
20903             clampedX = true;
20904         }
20905 
20906         boolean clampedY = false;
20907         if (newScrollY > bottom) {
20908             newScrollY = bottom;
20909             clampedY = true;
20910         } else if (newScrollY < top) {
20911             newScrollY = top;
20912             clampedY = true;
20913         }
20914 
20915         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
20916 
20917         return clampedX || clampedY;
20918     }
20919 
20920     /**
20921      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
20922      * respond to the results of an over-scroll operation.
20923      *
20924      * @param scrollX New X scroll value in pixels
20925      * @param scrollY New Y scroll value in pixels
20926      * @param clampedX True if scrollX was clamped to an over-scroll boundary
20927      * @param clampedY True if scrollY was clamped to an over-scroll boundary
20928      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)20929     protected void onOverScrolled(int scrollX, int scrollY,
20930             boolean clampedX, boolean clampedY) {
20931         // Intentionally empty.
20932     }
20933 
20934     /**
20935      * Returns the over-scroll mode for this view. The result will be
20936      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20937      * (allow over-scrolling only if the view content is larger than the container),
20938      * or {@link #OVER_SCROLL_NEVER}.
20939      *
20940      * @return This view's over-scroll mode.
20941      */
getOverScrollMode()20942     public int getOverScrollMode() {
20943         return mOverScrollMode;
20944     }
20945 
20946     /**
20947      * Set the over-scroll mode for this view. Valid over-scroll modes are
20948      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20949      * (allow over-scrolling only if the view content is larger than the container),
20950      * or {@link #OVER_SCROLL_NEVER}.
20951      *
20952      * Setting the over-scroll mode of a view will have an effect only if the
20953      * view is capable of scrolling.
20954      *
20955      * @param overScrollMode The new over-scroll mode for this view.
20956      */
setOverScrollMode(int overScrollMode)20957     public void setOverScrollMode(int overScrollMode) {
20958         if (overScrollMode != OVER_SCROLL_ALWAYS &&
20959                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
20960                 overScrollMode != OVER_SCROLL_NEVER) {
20961             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
20962         }
20963         mOverScrollMode = overScrollMode;
20964     }
20965 
20966     /**
20967      * Enable or disable nested scrolling for this view.
20968      *
20969      * <p>If this property is set to true the view will be permitted to initiate nested
20970      * scrolling operations with a compatible parent view in the current hierarchy. If this
20971      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
20972      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
20973      * the nested scroll.</p>
20974      *
20975      * @param enabled true to enable nested scrolling, false to disable
20976      *
20977      * @see #isNestedScrollingEnabled()
20978      */
setNestedScrollingEnabled(boolean enabled)20979     public void setNestedScrollingEnabled(boolean enabled) {
20980         if (enabled) {
20981             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
20982         } else {
20983             stopNestedScroll();
20984             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
20985         }
20986     }
20987 
20988     /**
20989      * Returns true if nested scrolling is enabled for this view.
20990      *
20991      * <p>If nested scrolling is enabled and this View class implementation supports it,
20992      * this view will act as a nested scrolling child view when applicable, forwarding data
20993      * about the scroll operation in progress to a compatible and cooperating nested scrolling
20994      * parent.</p>
20995      *
20996      * @return true if nested scrolling is enabled
20997      *
20998      * @see #setNestedScrollingEnabled(boolean)
20999      */
isNestedScrollingEnabled()21000     public boolean isNestedScrollingEnabled() {
21001         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21002                 PFLAG3_NESTED_SCROLLING_ENABLED;
21003     }
21004 
21005     /**
21006      * Begin a nestable scroll operation along the given axes.
21007      *
21008      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21009      *
21010      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21011      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21012      * In the case of touch scrolling the nested scroll will be terminated automatically in
21013      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21014      * In the event of programmatic scrolling the caller must explicitly call
21015      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21016      *
21017      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21018      * If it returns false the caller may ignore the rest of this contract until the next scroll.
21019      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21020      *
21021      * <p>At each incremental step of the scroll the caller should invoke
21022      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21023      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21024      * parent at least partially consumed the scroll and the caller should adjust the amount it
21025      * scrolls by.</p>
21026      *
21027      * <p>After applying the remainder of the scroll delta the caller should invoke
21028      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21029      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21030      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21031      * </p>
21032      *
21033      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21034      *             {@link #SCROLL_AXIS_VERTICAL}.
21035      * @return true if a cooperative parent was found and nested scrolling has been enabled for
21036      *         the current gesture.
21037      *
21038      * @see #stopNestedScroll()
21039      * @see #dispatchNestedPreScroll(int, int, int[], int[])
21040      * @see #dispatchNestedScroll(int, int, int, int, int[])
21041      */
startNestedScroll(int axes)21042     public boolean startNestedScroll(int axes) {
21043         if (hasNestedScrollingParent()) {
21044             // Already in progress
21045             return true;
21046         }
21047         if (isNestedScrollingEnabled()) {
21048             ViewParent p = getParent();
21049             View child = this;
21050             while (p != null) {
21051                 try {
21052                     if (p.onStartNestedScroll(child, this, axes)) {
21053                         mNestedScrollingParent = p;
21054                         p.onNestedScrollAccepted(child, this, axes);
21055                         return true;
21056                     }
21057                 } catch (AbstractMethodError e) {
21058                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21059                             "method onStartNestedScroll", e);
21060                     // Allow the search upward to continue
21061                 }
21062                 if (p instanceof View) {
21063                     child = (View) p;
21064                 }
21065                 p = p.getParent();
21066             }
21067         }
21068         return false;
21069     }
21070 
21071     /**
21072      * Stop a nested scroll in progress.
21073      *
21074      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21075      *
21076      * @see #startNestedScroll(int)
21077      */
stopNestedScroll()21078     public void stopNestedScroll() {
21079         if (mNestedScrollingParent != null) {
21080             mNestedScrollingParent.onStopNestedScroll(this);
21081             mNestedScrollingParent = null;
21082         }
21083     }
21084 
21085     /**
21086      * Returns true if this view has a nested scrolling parent.
21087      *
21088      * <p>The presence of a nested scrolling parent indicates that this view has initiated
21089      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21090      *
21091      * @return whether this view has a nested scrolling parent
21092      */
hasNestedScrollingParent()21093     public boolean hasNestedScrollingParent() {
21094         return mNestedScrollingParent != null;
21095     }
21096 
21097     /**
21098      * Dispatch one step of a nested scroll in progress.
21099      *
21100      * <p>Implementations of views that support nested scrolling should call this to report
21101      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21102      * is not currently in progress or nested scrolling is not
21103      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21104      *
21105      * <p>Compatible View implementations should also call
21106      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21107      * consuming a component of the scroll event themselves.</p>
21108      *
21109      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21110      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21111      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21112      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21113      * @param offsetInWindow Optional. If not null, on return this will contain the offset
21114      *                       in local view coordinates of this view from before this operation
21115      *                       to after it completes. View implementations may use this to adjust
21116      *                       expected input coordinate tracking.
21117      * @return true if the event was dispatched, false if it could not be dispatched.
21118      * @see #dispatchNestedPreScroll(int, int, int[], int[])
21119      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)21120     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21121             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21122         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21123             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21124                 int startX = 0;
21125                 int startY = 0;
21126                 if (offsetInWindow != null) {
21127                     getLocationInWindow(offsetInWindow);
21128                     startX = offsetInWindow[0];
21129                     startY = offsetInWindow[1];
21130                 }
21131 
21132                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21133                         dxUnconsumed, dyUnconsumed);
21134 
21135                 if (offsetInWindow != null) {
21136                     getLocationInWindow(offsetInWindow);
21137                     offsetInWindow[0] -= startX;
21138                     offsetInWindow[1] -= startY;
21139                 }
21140                 return true;
21141             } else if (offsetInWindow != null) {
21142                 // No motion, no dispatch. Keep offsetInWindow up to date.
21143                 offsetInWindow[0] = 0;
21144                 offsetInWindow[1] = 0;
21145             }
21146         }
21147         return false;
21148     }
21149 
21150     /**
21151      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21152      *
21153      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21154      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21155      * scrolling operation to consume some or all of the scroll operation before the child view
21156      * consumes it.</p>
21157      *
21158      * @param dx Horizontal scroll distance in pixels
21159      * @param dy Vertical scroll distance in pixels
21160      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21161      *                 and consumed[1] the consumed dy.
21162      * @param offsetInWindow Optional. If not null, on return this will contain the offset
21163      *                       in local view coordinates of this view from before this operation
21164      *                       to after it completes. View implementations may use this to adjust
21165      *                       expected input coordinate tracking.
21166      * @return true if the parent consumed some or all of the scroll delta
21167      * @see #dispatchNestedScroll(int, int, int, int, int[])
21168      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)21169     public boolean dispatchNestedPreScroll(int dx, int dy,
21170             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21171         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21172             if (dx != 0 || dy != 0) {
21173                 int startX = 0;
21174                 int startY = 0;
21175                 if (offsetInWindow != null) {
21176                     getLocationInWindow(offsetInWindow);
21177                     startX = offsetInWindow[0];
21178                     startY = offsetInWindow[1];
21179                 }
21180 
21181                 if (consumed == null) {
21182                     if (mTempNestedScrollConsumed == null) {
21183                         mTempNestedScrollConsumed = new int[2];
21184                     }
21185                     consumed = mTempNestedScrollConsumed;
21186                 }
21187                 consumed[0] = 0;
21188                 consumed[1] = 0;
21189                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21190 
21191                 if (offsetInWindow != null) {
21192                     getLocationInWindow(offsetInWindow);
21193                     offsetInWindow[0] -= startX;
21194                     offsetInWindow[1] -= startY;
21195                 }
21196                 return consumed[0] != 0 || consumed[1] != 0;
21197             } else if (offsetInWindow != null) {
21198                 offsetInWindow[0] = 0;
21199                 offsetInWindow[1] = 0;
21200             }
21201         }
21202         return false;
21203     }
21204 
21205     /**
21206      * Dispatch a fling to a nested scrolling parent.
21207      *
21208      * <p>This method should be used to indicate that a nested scrolling child has detected
21209      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21210      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21211      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21212      * along a scrollable axis.</p>
21213      *
21214      * <p>If a nested scrolling child view would normally fling but it is at the edge of
21215      * its own content, it can use this method to delegate the fling to its nested scrolling
21216      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21217      *
21218      * @param velocityX Horizontal fling velocity in pixels per second
21219      * @param velocityY Vertical fling velocity in pixels per second
21220      * @param consumed true if the child consumed the fling, false otherwise
21221      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21222      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)21223     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21224         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21225             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21226         }
21227         return false;
21228     }
21229 
21230     /**
21231      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21232      *
21233      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21234      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21235      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21236      * before the child view consumes it. If this method returns <code>true</code>, a nested
21237      * parent view consumed the fling and this view should not scroll as a result.</p>
21238      *
21239      * <p>For a better user experience, only one view in a nested scrolling chain should consume
21240      * the fling at a time. If a parent view consumed the fling this method will return false.
21241      * Custom view implementations should account for this in two ways:</p>
21242      *
21243      * <ul>
21244      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21245      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21246      *     position regardless.</li>
21247      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21248      *     even to settle back to a valid idle position.</li>
21249      * </ul>
21250      *
21251      * <p>Views should also not offer fling velocities to nested parent views along an axis
21252      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21253      * should not offer a horizontal fling velocity to its parents since scrolling along that
21254      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21255      *
21256      * @param velocityX Horizontal fling velocity in pixels per second
21257      * @param velocityY Vertical fling velocity in pixels per second
21258      * @return true if a nested scrolling parent consumed the fling
21259      */
dispatchNestedPreFling(float velocityX, float velocityY)21260     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21261         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21262             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21263         }
21264         return false;
21265     }
21266 
21267     /**
21268      * Gets a scale factor that determines the distance the view should scroll
21269      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21270      * @return The vertical scroll scale factor.
21271      * @hide
21272      */
getVerticalScrollFactor()21273     protected float getVerticalScrollFactor() {
21274         if (mVerticalScrollFactor == 0) {
21275             TypedValue outValue = new TypedValue();
21276             if (!mContext.getTheme().resolveAttribute(
21277                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21278                 throw new IllegalStateException(
21279                         "Expected theme to define listPreferredItemHeight.");
21280             }
21281             mVerticalScrollFactor = outValue.getDimension(
21282                     mContext.getResources().getDisplayMetrics());
21283         }
21284         return mVerticalScrollFactor;
21285     }
21286 
21287     /**
21288      * Gets a scale factor that determines the distance the view should scroll
21289      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21290      * @return The horizontal scroll scale factor.
21291      * @hide
21292      */
getHorizontalScrollFactor()21293     protected float getHorizontalScrollFactor() {
21294         // TODO: Should use something else.
21295         return getVerticalScrollFactor();
21296     }
21297 
21298     /**
21299      * Return the value specifying the text direction or policy that was set with
21300      * {@link #setTextDirection(int)}.
21301      *
21302      * @return the defined text direction. It can be one of:
21303      *
21304      * {@link #TEXT_DIRECTION_INHERIT},
21305      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21306      * {@link #TEXT_DIRECTION_ANY_RTL},
21307      * {@link #TEXT_DIRECTION_LTR},
21308      * {@link #TEXT_DIRECTION_RTL},
21309      * {@link #TEXT_DIRECTION_LOCALE},
21310      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21311      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21312      *
21313      * @attr ref android.R.styleable#View_textDirection
21314      *
21315      * @hide
21316      */
21317     @ViewDebug.ExportedProperty(category = "text", mapping = {
21318             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21319             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21320             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21321             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21322             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21323             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21324             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21325             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21326     })
getRawTextDirection()21327     public int getRawTextDirection() {
21328         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21329     }
21330 
21331     /**
21332      * Set the text direction.
21333      *
21334      * @param textDirection the direction to set. Should be one of:
21335      *
21336      * {@link #TEXT_DIRECTION_INHERIT},
21337      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21338      * {@link #TEXT_DIRECTION_ANY_RTL},
21339      * {@link #TEXT_DIRECTION_LTR},
21340      * {@link #TEXT_DIRECTION_RTL},
21341      * {@link #TEXT_DIRECTION_LOCALE}
21342      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21343      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21344      *
21345      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21346      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21347      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21348      *
21349      * @attr ref android.R.styleable#View_textDirection
21350      */
setTextDirection(int textDirection)21351     public void setTextDirection(int textDirection) {
21352         if (getRawTextDirection() != textDirection) {
21353             // Reset the current text direction and the resolved one
21354             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21355             resetResolvedTextDirection();
21356             // Set the new text direction
21357             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21358             // Do resolution
21359             resolveTextDirection();
21360             // Notify change
21361             onRtlPropertiesChanged(getLayoutDirection());
21362             // Refresh
21363             requestLayout();
21364             invalidate(true);
21365         }
21366     }
21367 
21368     /**
21369      * Return the resolved text direction.
21370      *
21371      * @return the resolved text direction. Returns one of:
21372      *
21373      * {@link #TEXT_DIRECTION_FIRST_STRONG},
21374      * {@link #TEXT_DIRECTION_ANY_RTL},
21375      * {@link #TEXT_DIRECTION_LTR},
21376      * {@link #TEXT_DIRECTION_RTL},
21377      * {@link #TEXT_DIRECTION_LOCALE},
21378      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21379      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21380      *
21381      * @attr ref android.R.styleable#View_textDirection
21382      */
21383     @ViewDebug.ExportedProperty(category = "text", mapping = {
21384             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21385             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21386             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21387             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21388             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21389             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21390             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21391             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21392     })
getTextDirection()21393     public int getTextDirection() {
21394         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21395     }
21396 
21397     /**
21398      * Resolve the text direction.
21399      *
21400      * @return true if resolution has been done, false otherwise.
21401      *
21402      * @hide
21403      */
resolveTextDirection()21404     public boolean resolveTextDirection() {
21405         // Reset any previous text direction resolution
21406         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21407 
21408         if (hasRtlSupport()) {
21409             // Set resolved text direction flag depending on text direction flag
21410             final int textDirection = getRawTextDirection();
21411             switch(textDirection) {
21412                 case TEXT_DIRECTION_INHERIT:
21413                     if (!canResolveTextDirection()) {
21414                         // We cannot do the resolution if there is no parent, so use the default one
21415                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21416                         // Resolution will need to happen again later
21417                         return false;
21418                     }
21419 
21420                     // Parent has not yet resolved, so we still return the default
21421                     try {
21422                         if (!mParent.isTextDirectionResolved()) {
21423                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21424                             // Resolution will need to happen again later
21425                             return false;
21426                         }
21427                     } catch (AbstractMethodError e) {
21428                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21429                                 " does not fully implement ViewParent", e);
21430                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21431                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21432                         return true;
21433                     }
21434 
21435                     // Set current resolved direction to the same value as the parent's one
21436                     int parentResolvedDirection;
21437                     try {
21438                         parentResolvedDirection = mParent.getTextDirection();
21439                     } catch (AbstractMethodError e) {
21440                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21441                                 " does not fully implement ViewParent", e);
21442                         parentResolvedDirection = TEXT_DIRECTION_LTR;
21443                     }
21444                     switch (parentResolvedDirection) {
21445                         case TEXT_DIRECTION_FIRST_STRONG:
21446                         case TEXT_DIRECTION_ANY_RTL:
21447                         case TEXT_DIRECTION_LTR:
21448                         case TEXT_DIRECTION_RTL:
21449                         case TEXT_DIRECTION_LOCALE:
21450                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
21451                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
21452                             mPrivateFlags2 |=
21453                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21454                             break;
21455                         default:
21456                             // Default resolved direction is "first strong" heuristic
21457                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21458                     }
21459                     break;
21460                 case TEXT_DIRECTION_FIRST_STRONG:
21461                 case TEXT_DIRECTION_ANY_RTL:
21462                 case TEXT_DIRECTION_LTR:
21463                 case TEXT_DIRECTION_RTL:
21464                 case TEXT_DIRECTION_LOCALE:
21465                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
21466                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
21467                     // Resolved direction is the same as text direction
21468                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21469                     break;
21470                 default:
21471                     // Default resolved direction is "first strong" heuristic
21472                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21473             }
21474         } else {
21475             // Default resolved direction is "first strong" heuristic
21476             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21477         }
21478 
21479         // Set to resolved
21480         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21481         return true;
21482     }
21483 
21484     /**
21485      * Check if text direction resolution can be done.
21486      *
21487      * @return true if text direction resolution can be done otherwise return false.
21488      */
canResolveTextDirection()21489     public boolean canResolveTextDirection() {
21490         switch (getRawTextDirection()) {
21491             case TEXT_DIRECTION_INHERIT:
21492                 if (mParent != null) {
21493                     try {
21494                         return mParent.canResolveTextDirection();
21495                     } catch (AbstractMethodError e) {
21496                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21497                                 " does not fully implement ViewParent", e);
21498                     }
21499                 }
21500                 return false;
21501 
21502             default:
21503                 return true;
21504         }
21505     }
21506 
21507     /**
21508      * Reset resolved text direction. Text direction will be resolved during a call to
21509      * {@link #onMeasure(int, int)}.
21510      *
21511      * @hide
21512      */
resetResolvedTextDirection()21513     public void resetResolvedTextDirection() {
21514         // Reset any previous text direction resolution
21515         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21516         // Set to default value
21517         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21518     }
21519 
21520     /**
21521      * @return true if text direction is inherited.
21522      *
21523      * @hide
21524      */
isTextDirectionInherited()21525     public boolean isTextDirectionInherited() {
21526         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21527     }
21528 
21529     /**
21530      * @return true if text direction is resolved.
21531      */
isTextDirectionResolved()21532     public boolean isTextDirectionResolved() {
21533         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21534     }
21535 
21536     /**
21537      * Return the value specifying the text alignment or policy that was set with
21538      * {@link #setTextAlignment(int)}.
21539      *
21540      * @return the defined text alignment. It can be one of:
21541      *
21542      * {@link #TEXT_ALIGNMENT_INHERIT},
21543      * {@link #TEXT_ALIGNMENT_GRAVITY},
21544      * {@link #TEXT_ALIGNMENT_CENTER},
21545      * {@link #TEXT_ALIGNMENT_TEXT_START},
21546      * {@link #TEXT_ALIGNMENT_TEXT_END},
21547      * {@link #TEXT_ALIGNMENT_VIEW_START},
21548      * {@link #TEXT_ALIGNMENT_VIEW_END}
21549      *
21550      * @attr ref android.R.styleable#View_textAlignment
21551      *
21552      * @hide
21553      */
21554     @ViewDebug.ExportedProperty(category = "text", mapping = {
21555             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21556             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21557             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21558             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21559             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21560             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21561             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21562     })
21563     @TextAlignment
getRawTextAlignment()21564     public int getRawTextAlignment() {
21565         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21566     }
21567 
21568     /**
21569      * Set the text alignment.
21570      *
21571      * @param textAlignment The text alignment to set. Should be one of
21572      *
21573      * {@link #TEXT_ALIGNMENT_INHERIT},
21574      * {@link #TEXT_ALIGNMENT_GRAVITY},
21575      * {@link #TEXT_ALIGNMENT_CENTER},
21576      * {@link #TEXT_ALIGNMENT_TEXT_START},
21577      * {@link #TEXT_ALIGNMENT_TEXT_END},
21578      * {@link #TEXT_ALIGNMENT_VIEW_START},
21579      * {@link #TEXT_ALIGNMENT_VIEW_END}
21580      *
21581      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21582      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21583      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21584      *
21585      * @attr ref android.R.styleable#View_textAlignment
21586      */
setTextAlignment(@extAlignment int textAlignment)21587     public void setTextAlignment(@TextAlignment int textAlignment) {
21588         if (textAlignment != getRawTextAlignment()) {
21589             // Reset the current and resolved text alignment
21590             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21591             resetResolvedTextAlignment();
21592             // Set the new text alignment
21593             mPrivateFlags2 |=
21594                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21595             // Do resolution
21596             resolveTextAlignment();
21597             // Notify change
21598             onRtlPropertiesChanged(getLayoutDirection());
21599             // Refresh
21600             requestLayout();
21601             invalidate(true);
21602         }
21603     }
21604 
21605     /**
21606      * Return the resolved text alignment.
21607      *
21608      * @return the resolved text alignment. Returns one of:
21609      *
21610      * {@link #TEXT_ALIGNMENT_GRAVITY},
21611      * {@link #TEXT_ALIGNMENT_CENTER},
21612      * {@link #TEXT_ALIGNMENT_TEXT_START},
21613      * {@link #TEXT_ALIGNMENT_TEXT_END},
21614      * {@link #TEXT_ALIGNMENT_VIEW_START},
21615      * {@link #TEXT_ALIGNMENT_VIEW_END}
21616      *
21617      * @attr ref android.R.styleable#View_textAlignment
21618      */
21619     @ViewDebug.ExportedProperty(category = "text", mapping = {
21620             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21621             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21622             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21623             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21624             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21625             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21626             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21627     })
21628     @TextAlignment
getTextAlignment()21629     public int getTextAlignment() {
21630         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21631                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21632     }
21633 
21634     /**
21635      * Resolve the text alignment.
21636      *
21637      * @return true if resolution has been done, false otherwise.
21638      *
21639      * @hide
21640      */
resolveTextAlignment()21641     public boolean resolveTextAlignment() {
21642         // Reset any previous text alignment resolution
21643         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21644 
21645         if (hasRtlSupport()) {
21646             // Set resolved text alignment flag depending on text alignment flag
21647             final int textAlignment = getRawTextAlignment();
21648             switch (textAlignment) {
21649                 case TEXT_ALIGNMENT_INHERIT:
21650                     // Check if we can resolve the text alignment
21651                     if (!canResolveTextAlignment()) {
21652                         // We cannot do the resolution if there is no parent so use the default
21653                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21654                         // Resolution will need to happen again later
21655                         return false;
21656                     }
21657 
21658                     // Parent has not yet resolved, so we still return the default
21659                     try {
21660                         if (!mParent.isTextAlignmentResolved()) {
21661                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21662                             // Resolution will need to happen again later
21663                             return false;
21664                         }
21665                     } catch (AbstractMethodError e) {
21666                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21667                                 " does not fully implement ViewParent", e);
21668                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21669                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21670                         return true;
21671                     }
21672 
21673                     int parentResolvedTextAlignment;
21674                     try {
21675                         parentResolvedTextAlignment = mParent.getTextAlignment();
21676                     } catch (AbstractMethodError e) {
21677                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21678                                 " does not fully implement ViewParent", e);
21679                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21680                     }
21681                     switch (parentResolvedTextAlignment) {
21682                         case TEXT_ALIGNMENT_GRAVITY:
21683                         case TEXT_ALIGNMENT_TEXT_START:
21684                         case TEXT_ALIGNMENT_TEXT_END:
21685                         case TEXT_ALIGNMENT_CENTER:
21686                         case TEXT_ALIGNMENT_VIEW_START:
21687                         case TEXT_ALIGNMENT_VIEW_END:
21688                             // Resolved text alignment is the same as the parent resolved
21689                             // text alignment
21690                             mPrivateFlags2 |=
21691                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21692                             break;
21693                         default:
21694                             // Use default resolved text alignment
21695                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21696                     }
21697                     break;
21698                 case TEXT_ALIGNMENT_GRAVITY:
21699                 case TEXT_ALIGNMENT_TEXT_START:
21700                 case TEXT_ALIGNMENT_TEXT_END:
21701                 case TEXT_ALIGNMENT_CENTER:
21702                 case TEXT_ALIGNMENT_VIEW_START:
21703                 case TEXT_ALIGNMENT_VIEW_END:
21704                     // Resolved text alignment is the same as text alignment
21705                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21706                     break;
21707                 default:
21708                     // Use default resolved text alignment
21709                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21710             }
21711         } else {
21712             // Use default resolved text alignment
21713             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21714         }
21715 
21716         // Set the resolved
21717         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21718         return true;
21719     }
21720 
21721     /**
21722      * Check if text alignment resolution can be done.
21723      *
21724      * @return true if text alignment resolution can be done otherwise return false.
21725      */
canResolveTextAlignment()21726     public boolean canResolveTextAlignment() {
21727         switch (getRawTextAlignment()) {
21728             case TEXT_DIRECTION_INHERIT:
21729                 if (mParent != null) {
21730                     try {
21731                         return mParent.canResolveTextAlignment();
21732                     } catch (AbstractMethodError e) {
21733                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21734                                 " does not fully implement ViewParent", e);
21735                     }
21736                 }
21737                 return false;
21738 
21739             default:
21740                 return true;
21741         }
21742     }
21743 
21744     /**
21745      * Reset resolved text alignment. Text alignment will be resolved during a call to
21746      * {@link #onMeasure(int, int)}.
21747      *
21748      * @hide
21749      */
resetResolvedTextAlignment()21750     public void resetResolvedTextAlignment() {
21751         // Reset any previous text alignment resolution
21752         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21753         // Set to default
21754         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21755     }
21756 
21757     /**
21758      * @return true if text alignment is inherited.
21759      *
21760      * @hide
21761      */
isTextAlignmentInherited()21762     public boolean isTextAlignmentInherited() {
21763         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21764     }
21765 
21766     /**
21767      * @return true if text alignment is resolved.
21768      */
isTextAlignmentResolved()21769     public boolean isTextAlignmentResolved() {
21770         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21771     }
21772 
21773     /**
21774      * Generate a value suitable for use in {@link #setId(int)}.
21775      * This value will not collide with ID values generated at build time by aapt for R.id.
21776      *
21777      * @return a generated ID value
21778      */
generateViewId()21779     public static int generateViewId() {
21780         for (;;) {
21781             final int result = sNextGeneratedId.get();
21782             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21783             int newValue = result + 1;
21784             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21785             if (sNextGeneratedId.compareAndSet(result, newValue)) {
21786                 return result;
21787             }
21788         }
21789     }
21790 
21791     /**
21792      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21793      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21794      *                           a normal View or a ViewGroup with
21795      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21796      * @hide
21797      */
captureTransitioningViews(List<View> transitioningViews)21798     public void captureTransitioningViews(List<View> transitioningViews) {
21799         if (getVisibility() == View.VISIBLE) {
21800             transitioningViews.add(this);
21801         }
21802     }
21803 
21804     /**
21805      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21806      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21807      * @hide
21808      */
findNamedViews(Map<String, View> namedElements)21809     public void findNamedViews(Map<String, View> namedElements) {
21810         if (getVisibility() == VISIBLE || mGhostView != null) {
21811             String transitionName = getTransitionName();
21812             if (transitionName != null) {
21813                 namedElements.put(transitionName, this);
21814             }
21815         }
21816     }
21817 
21818     /**
21819      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
21820      * The default implementation does not care the location or event types, but some subclasses
21821      * may use it (such as WebViews).
21822      * @param event The MotionEvent from a mouse
21823      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
21824      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
21825      * @see PointerIcon
21826      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)21827     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
21828         final float x = event.getX(pointerIndex);
21829         final float y = event.getY(pointerIndex);
21830         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
21831             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
21832         }
21833         return mPointerIcon;
21834     }
21835 
21836     /**
21837      * Set the pointer icon for the current view.
21838      * Passing {@code null} will restore the pointer icon to its default value.
21839      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
21840      */
setPointerIcon(PointerIcon pointerIcon)21841     public void setPointerIcon(PointerIcon pointerIcon) {
21842         mPointerIcon = pointerIcon;
21843         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
21844             return;
21845         }
21846         try {
21847             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
21848         } catch (RemoteException e) {
21849         }
21850     }
21851 
21852     /**
21853      * Gets the pointer icon for the current view.
21854      */
getPointerIcon()21855     public PointerIcon getPointerIcon() {
21856         return mPointerIcon;
21857     }
21858 
21859     //
21860     // Properties
21861     //
21862     /**
21863      * A Property wrapper around the <code>alpha</code> functionality handled by the
21864      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21865      */
21866     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21867         @Override
21868         public void setValue(View object, float value) {
21869             object.setAlpha(value);
21870         }
21871 
21872         @Override
21873         public Float get(View object) {
21874             return object.getAlpha();
21875         }
21876     };
21877 
21878     /**
21879      * A Property wrapper around the <code>translationX</code> functionality handled by the
21880      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21881      */
21882     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21883         @Override
21884         public void setValue(View object, float value) {
21885             object.setTranslationX(value);
21886         }
21887 
21888                 @Override
21889         public Float get(View object) {
21890             return object.getTranslationX();
21891         }
21892     };
21893 
21894     /**
21895      * A Property wrapper around the <code>translationY</code> functionality handled by the
21896      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
21897      */
21898     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
21899         @Override
21900         public void setValue(View object, float value) {
21901             object.setTranslationY(value);
21902         }
21903 
21904         @Override
21905         public Float get(View object) {
21906             return object.getTranslationY();
21907         }
21908     };
21909 
21910     /**
21911      * A Property wrapper around the <code>translationZ</code> functionality handled by the
21912      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
21913      */
21914     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
21915         @Override
21916         public void setValue(View object, float value) {
21917             object.setTranslationZ(value);
21918         }
21919 
21920         @Override
21921         public Float get(View object) {
21922             return object.getTranslationZ();
21923         }
21924     };
21925 
21926     /**
21927      * A Property wrapper around the <code>x</code> functionality handled by the
21928      * {@link View#setX(float)} and {@link View#getX()} methods.
21929      */
21930     public static final Property<View, Float> X = new FloatProperty<View>("x") {
21931         @Override
21932         public void setValue(View object, float value) {
21933             object.setX(value);
21934         }
21935 
21936         @Override
21937         public Float get(View object) {
21938             return object.getX();
21939         }
21940     };
21941 
21942     /**
21943      * A Property wrapper around the <code>y</code> functionality handled by the
21944      * {@link View#setY(float)} and {@link View#getY()} methods.
21945      */
21946     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
21947         @Override
21948         public void setValue(View object, float value) {
21949             object.setY(value);
21950         }
21951 
21952         @Override
21953         public Float get(View object) {
21954             return object.getY();
21955         }
21956     };
21957 
21958     /**
21959      * A Property wrapper around the <code>z</code> functionality handled by the
21960      * {@link View#setZ(float)} and {@link View#getZ()} methods.
21961      */
21962     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
21963         @Override
21964         public void setValue(View object, float value) {
21965             object.setZ(value);
21966         }
21967 
21968         @Override
21969         public Float get(View object) {
21970             return object.getZ();
21971         }
21972     };
21973 
21974     /**
21975      * A Property wrapper around the <code>rotation</code> functionality handled by the
21976      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
21977      */
21978     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
21979         @Override
21980         public void setValue(View object, float value) {
21981             object.setRotation(value);
21982         }
21983 
21984         @Override
21985         public Float get(View object) {
21986             return object.getRotation();
21987         }
21988     };
21989 
21990     /**
21991      * A Property wrapper around the <code>rotationX</code> functionality handled by the
21992      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
21993      */
21994     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
21995         @Override
21996         public void setValue(View object, float value) {
21997             object.setRotationX(value);
21998         }
21999 
22000         @Override
22001         public Float get(View object) {
22002             return object.getRotationX();
22003         }
22004     };
22005 
22006     /**
22007      * A Property wrapper around the <code>rotationY</code> functionality handled by the
22008      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22009      */
22010     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22011         @Override
22012         public void setValue(View object, float value) {
22013             object.setRotationY(value);
22014         }
22015 
22016         @Override
22017         public Float get(View object) {
22018             return object.getRotationY();
22019         }
22020     };
22021 
22022     /**
22023      * A Property wrapper around the <code>scaleX</code> functionality handled by the
22024      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22025      */
22026     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22027         @Override
22028         public void setValue(View object, float value) {
22029             object.setScaleX(value);
22030         }
22031 
22032         @Override
22033         public Float get(View object) {
22034             return object.getScaleX();
22035         }
22036     };
22037 
22038     /**
22039      * A Property wrapper around the <code>scaleY</code> functionality handled by the
22040      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22041      */
22042     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22043         @Override
22044         public void setValue(View object, float value) {
22045             object.setScaleY(value);
22046         }
22047 
22048         @Override
22049         public Float get(View object) {
22050             return object.getScaleY();
22051         }
22052     };
22053 
22054     /**
22055      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22056      * Each MeasureSpec represents a requirement for either the width or the height.
22057      * A MeasureSpec is comprised of a size and a mode. There are three possible
22058      * modes:
22059      * <dl>
22060      * <dt>UNSPECIFIED</dt>
22061      * <dd>
22062      * The parent has not imposed any constraint on the child. It can be whatever size
22063      * it wants.
22064      * </dd>
22065      *
22066      * <dt>EXACTLY</dt>
22067      * <dd>
22068      * The parent has determined an exact size for the child. The child is going to be
22069      * given those bounds regardless of how big it wants to be.
22070      * </dd>
22071      *
22072      * <dt>AT_MOST</dt>
22073      * <dd>
22074      * The child can be as large as it wants up to the specified size.
22075      * </dd>
22076      * </dl>
22077      *
22078      * MeasureSpecs are implemented as ints to reduce object allocation. This class
22079      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22080      */
22081     public static class MeasureSpec {
22082         private static final int MODE_SHIFT = 30;
22083         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22084 
22085         /** @hide */
22086         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22087         @Retention(RetentionPolicy.SOURCE)
22088         public @interface MeasureSpecMode {}
22089 
22090         /**
22091          * Measure specification mode: The parent has not imposed any constraint
22092          * on the child. It can be whatever size it wants.
22093          */
22094         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22095 
22096         /**
22097          * Measure specification mode: The parent has determined an exact size
22098          * for the child. The child is going to be given those bounds regardless
22099          * of how big it wants to be.
22100          */
22101         public static final int EXACTLY     = 1 << MODE_SHIFT;
22102 
22103         /**
22104          * Measure specification mode: The child can be as large as it wants up
22105          * to the specified size.
22106          */
22107         public static final int AT_MOST     = 2 << MODE_SHIFT;
22108 
22109         /**
22110          * Creates a measure specification based on the supplied size and mode.
22111          *
22112          * The mode must always be one of the following:
22113          * <ul>
22114          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22115          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22116          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22117          * </ul>
22118          *
22119          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22120          * implementation was such that the order of arguments did not matter
22121          * and overflow in either value could impact the resulting MeasureSpec.
22122          * {@link android.widget.RelativeLayout} was affected by this bug.
22123          * Apps targeting API levels greater than 17 will get the fixed, more strict
22124          * behavior.</p>
22125          *
22126          * @param size the size of the measure specification
22127          * @param mode the mode of the measure specification
22128          * @return the measure specification based on size and mode
22129          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)22130         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22131                                           @MeasureSpecMode int mode) {
22132             if (sUseBrokenMakeMeasureSpec) {
22133                 return size + mode;
22134             } else {
22135                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
22136             }
22137         }
22138 
22139         /**
22140          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22141          * will automatically get a size of 0. Older apps expect this.
22142          *
22143          * @hide internal use only for compatibility with system widgets and older apps
22144          */
makeSafeMeasureSpec(int size, int mode)22145         public static int makeSafeMeasureSpec(int size, int mode) {
22146             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22147                 return 0;
22148             }
22149             return makeMeasureSpec(size, mode);
22150         }
22151 
22152         /**
22153          * Extracts the mode from the supplied measure specification.
22154          *
22155          * @param measureSpec the measure specification to extract the mode from
22156          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22157          *         {@link android.view.View.MeasureSpec#AT_MOST} or
22158          *         {@link android.view.View.MeasureSpec#EXACTLY}
22159          */
22160         @MeasureSpecMode
getMode(int measureSpec)22161         public static int getMode(int measureSpec) {
22162             //noinspection ResourceType
22163             return (measureSpec & MODE_MASK);
22164         }
22165 
22166         /**
22167          * Extracts the size from the supplied measure specification.
22168          *
22169          * @param measureSpec the measure specification to extract the size from
22170          * @return the size in pixels defined in the supplied measure specification
22171          */
getSize(int measureSpec)22172         public static int getSize(int measureSpec) {
22173             return (measureSpec & ~MODE_MASK);
22174         }
22175 
adjust(int measureSpec, int delta)22176         static int adjust(int measureSpec, int delta) {
22177             final int mode = getMode(measureSpec);
22178             int size = getSize(measureSpec);
22179             if (mode == UNSPECIFIED) {
22180                 // No need to adjust size for UNSPECIFIED mode.
22181                 return makeMeasureSpec(size, UNSPECIFIED);
22182             }
22183             size += delta;
22184             if (size < 0) {
22185                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22186                         ") spec: " + toString(measureSpec) + " delta: " + delta);
22187                 size = 0;
22188             }
22189             return makeMeasureSpec(size, mode);
22190         }
22191 
22192         /**
22193          * Returns a String representation of the specified measure
22194          * specification.
22195          *
22196          * @param measureSpec the measure specification to convert to a String
22197          * @return a String with the following format: "MeasureSpec: MODE SIZE"
22198          */
toString(int measureSpec)22199         public static String toString(int measureSpec) {
22200             int mode = getMode(measureSpec);
22201             int size = getSize(measureSpec);
22202 
22203             StringBuilder sb = new StringBuilder("MeasureSpec: ");
22204 
22205             if (mode == UNSPECIFIED)
22206                 sb.append("UNSPECIFIED ");
22207             else if (mode == EXACTLY)
22208                 sb.append("EXACTLY ");
22209             else if (mode == AT_MOST)
22210                 sb.append("AT_MOST ");
22211             else
22212                 sb.append(mode).append(" ");
22213 
22214             sb.append(size);
22215             return sb.toString();
22216         }
22217     }
22218 
22219     private final class CheckForLongPress implements Runnable {
22220         private int mOriginalWindowAttachCount;
22221         private float mX;
22222         private float mY;
22223 
22224         @Override
run()22225         public void run() {
22226             if (isPressed() && (mParent != null)
22227                     && mOriginalWindowAttachCount == mWindowAttachCount) {
22228                 if (performLongClick(mX, mY)) {
22229                     mHasPerformedLongPress = true;
22230                 }
22231             }
22232         }
22233 
setAnchor(float x, float y)22234         public void setAnchor(float x, float y) {
22235             mX = x;
22236             mY = y;
22237         }
22238 
rememberWindowAttachCount()22239         public void rememberWindowAttachCount() {
22240             mOriginalWindowAttachCount = mWindowAttachCount;
22241         }
22242     }
22243 
22244     private final class CheckForTap implements Runnable {
22245         public float x;
22246         public float y;
22247 
22248         @Override
run()22249         public void run() {
22250             mPrivateFlags &= ~PFLAG_PREPRESSED;
22251             setPressed(true, x, y);
22252             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22253         }
22254     }
22255 
22256     private final class PerformClick implements Runnable {
22257         @Override
run()22258         public void run() {
22259             performClick();
22260         }
22261     }
22262 
22263     /**
22264      * This method returns a ViewPropertyAnimator object, which can be used to animate
22265      * specific properties on this View.
22266      *
22267      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22268      */
animate()22269     public ViewPropertyAnimator animate() {
22270         if (mAnimator == null) {
22271             mAnimator = new ViewPropertyAnimator(this);
22272         }
22273         return mAnimator;
22274     }
22275 
22276     /**
22277      * Sets the name of the View to be used to identify Views in Transitions.
22278      * Names should be unique in the View hierarchy.
22279      *
22280      * @param transitionName The name of the View to uniquely identify it for Transitions.
22281      */
setTransitionName(String transitionName)22282     public final void setTransitionName(String transitionName) {
22283         mTransitionName = transitionName;
22284     }
22285 
22286     /**
22287      * Returns the name of the View to be used to identify Views in Transitions.
22288      * Names should be unique in the View hierarchy.
22289      *
22290      * <p>This returns null if the View has not been given a name.</p>
22291      *
22292      * @return The name used of the View to be used to identify Views in Transitions or null
22293      * if no name has been given.
22294      */
22295     @ViewDebug.ExportedProperty
getTransitionName()22296     public String getTransitionName() {
22297         return mTransitionName;
22298     }
22299 
22300     /**
22301      * @hide
22302      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)22303     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22304         // Do nothing.
22305     }
22306 
22307     /**
22308      * Interface definition for a callback to be invoked when a hardware key event is
22309      * dispatched to this view. The callback will be invoked before the key event is
22310      * given to the view. This is only useful for hardware keyboards; a software input
22311      * method has no obligation to trigger this listener.
22312      */
22313     public interface OnKeyListener {
22314         /**
22315          * Called when a hardware key is dispatched to a view. This allows listeners to
22316          * get a chance to respond before the target view.
22317          * <p>Key presses in software keyboards will generally NOT trigger this method,
22318          * although some may elect to do so in some situations. Do not assume a
22319          * software input method has to be key-based; even if it is, it may use key presses
22320          * in a different way than you expect, so there is no way to reliably catch soft
22321          * input key presses.
22322          *
22323          * @param v The view the key has been dispatched to.
22324          * @param keyCode The code for the physical key that was pressed
22325          * @param event The KeyEvent object containing full information about
22326          *        the event.
22327          * @return True if the listener has consumed the event, false otherwise.
22328          */
onKey(View v, int keyCode, KeyEvent event)22329         boolean onKey(View v, int keyCode, KeyEvent event);
22330     }
22331 
22332     /**
22333      * Interface definition for a callback to be invoked when a touch event is
22334      * dispatched to this view. The callback will be invoked before the touch
22335      * event is given to the view.
22336      */
22337     public interface OnTouchListener {
22338         /**
22339          * Called when a touch event is dispatched to a view. This allows listeners to
22340          * get a chance to respond before the target view.
22341          *
22342          * @param v The view the touch event has been dispatched to.
22343          * @param event The MotionEvent object containing full information about
22344          *        the event.
22345          * @return True if the listener has consumed the event, false otherwise.
22346          */
onTouch(View v, MotionEvent event)22347         boolean onTouch(View v, MotionEvent event);
22348     }
22349 
22350     /**
22351      * Interface definition for a callback to be invoked when a hover event is
22352      * dispatched to this view. The callback will be invoked before the hover
22353      * event is given to the view.
22354      */
22355     public interface OnHoverListener {
22356         /**
22357          * Called when a hover event is dispatched to a view. This allows listeners to
22358          * get a chance to respond before the target view.
22359          *
22360          * @param v The view the hover event has been dispatched to.
22361          * @param event The MotionEvent object containing full information about
22362          *        the event.
22363          * @return True if the listener has consumed the event, false otherwise.
22364          */
onHover(View v, MotionEvent event)22365         boolean onHover(View v, MotionEvent event);
22366     }
22367 
22368     /**
22369      * Interface definition for a callback to be invoked when a generic motion event is
22370      * dispatched to this view. The callback will be invoked before the generic motion
22371      * event is given to the view.
22372      */
22373     public interface OnGenericMotionListener {
22374         /**
22375          * Called when a generic motion event is dispatched to a view. This allows listeners to
22376          * get a chance to respond before the target view.
22377          *
22378          * @param v The view the generic motion event has been dispatched to.
22379          * @param event The MotionEvent object containing full information about
22380          *        the event.
22381          * @return True if the listener has consumed the event, false otherwise.
22382          */
onGenericMotion(View v, MotionEvent event)22383         boolean onGenericMotion(View v, MotionEvent event);
22384     }
22385 
22386     /**
22387      * Interface definition for a callback to be invoked when a view has been clicked and held.
22388      */
22389     public interface OnLongClickListener {
22390         /**
22391          * Called when a view has been clicked and held.
22392          *
22393          * @param v The view that was clicked and held.
22394          *
22395          * @return true if the callback consumed the long click, false otherwise.
22396          */
onLongClick(View v)22397         boolean onLongClick(View v);
22398     }
22399 
22400     /**
22401      * Interface definition for a callback to be invoked when a drag is being dispatched
22402      * to this view.  The callback will be invoked before the hosting view's own
22403      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
22404      * onDrag(event) behavior, it should return 'false' from this callback.
22405      *
22406      * <div class="special reference">
22407      * <h3>Developer Guides</h3>
22408      * <p>For a guide to implementing drag and drop features, read the
22409      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22410      * </div>
22411      */
22412     public interface OnDragListener {
22413         /**
22414          * Called when a drag event is dispatched to a view. This allows listeners
22415          * to get a chance to override base View behavior.
22416          *
22417          * @param v The View that received the drag event.
22418          * @param event The {@link android.view.DragEvent} object for the drag event.
22419          * @return {@code true} if the drag event was handled successfully, or {@code false}
22420          * if the drag event was not handled. Note that {@code false} will trigger the View
22421          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22422          */
onDrag(View v, DragEvent event)22423         boolean onDrag(View v, DragEvent event);
22424     }
22425 
22426     /**
22427      * Interface definition for a callback to be invoked when the focus state of
22428      * a view changed.
22429      */
22430     public interface OnFocusChangeListener {
22431         /**
22432          * Called when the focus state of a view has changed.
22433          *
22434          * @param v The view whose state has changed.
22435          * @param hasFocus The new focus state of v.
22436          */
onFocusChange(View v, boolean hasFocus)22437         void onFocusChange(View v, boolean hasFocus);
22438     }
22439 
22440     /**
22441      * Interface definition for a callback to be invoked when a view is clicked.
22442      */
22443     public interface OnClickListener {
22444         /**
22445          * Called when a view has been clicked.
22446          *
22447          * @param v The view that was clicked.
22448          */
onClick(View v)22449         void onClick(View v);
22450     }
22451 
22452     /**
22453      * Interface definition for a callback to be invoked when a view is context clicked.
22454      */
22455     public interface OnContextClickListener {
22456         /**
22457          * Called when a view is context clicked.
22458          *
22459          * @param v The view that has been context clicked.
22460          * @return true if the callback consumed the context click, false otherwise.
22461          */
onContextClick(View v)22462         boolean onContextClick(View v);
22463     }
22464 
22465     /**
22466      * Interface definition for a callback to be invoked when the context menu
22467      * for this view is being built.
22468      */
22469     public interface OnCreateContextMenuListener {
22470         /**
22471          * Called when the context menu for this view is being built. It is not
22472          * safe to hold onto the menu after this method returns.
22473          *
22474          * @param menu The context menu that is being built
22475          * @param v The view for which the context menu is being built
22476          * @param menuInfo Extra information about the item for which the
22477          *            context menu should be shown. This information will vary
22478          *            depending on the class of v.
22479          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)22480         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22481     }
22482 
22483     /**
22484      * Interface definition for a callback to be invoked when the status bar changes
22485      * visibility.  This reports <strong>global</strong> changes to the system UI
22486      * state, not what the application is requesting.
22487      *
22488      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22489      */
22490     public interface OnSystemUiVisibilityChangeListener {
22491         /**
22492          * Called when the status bar changes visibility because of a call to
22493          * {@link View#setSystemUiVisibility(int)}.
22494          *
22495          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22496          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22497          * This tells you the <strong>global</strong> state of these UI visibility
22498          * flags, not what your app is currently applying.
22499          */
onSystemUiVisibilityChange(int visibility)22500         public void onSystemUiVisibilityChange(int visibility);
22501     }
22502 
22503     /**
22504      * Interface definition for a callback to be invoked when this view is attached
22505      * or detached from its window.
22506      */
22507     public interface OnAttachStateChangeListener {
22508         /**
22509          * Called when the view is attached to a window.
22510          * @param v The view that was attached
22511          */
onViewAttachedToWindow(View v)22512         public void onViewAttachedToWindow(View v);
22513         /**
22514          * Called when the view is detached from a window.
22515          * @param v The view that was detached
22516          */
onViewDetachedFromWindow(View v)22517         public void onViewDetachedFromWindow(View v);
22518     }
22519 
22520     /**
22521      * Listener for applying window insets on a view in a custom way.
22522      *
22523      * <p>Apps may choose to implement this interface if they want to apply custom policy
22524      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22525      * is set, its
22526      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22527      * method will be called instead of the View's own
22528      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22529      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22530      * the View's normal behavior as part of its own.</p>
22531      */
22532     public interface OnApplyWindowInsetsListener {
22533         /**
22534          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22535          * on a View, this listener method will be called instead of the view's own
22536          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22537          *
22538          * @param v The view applying window insets
22539          * @param insets The insets to apply
22540          * @return The insets supplied, minus any insets that were consumed
22541          */
onApplyWindowInsets(View v, WindowInsets insets)22542         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22543     }
22544 
22545     private final class UnsetPressedState implements Runnable {
22546         @Override
run()22547         public void run() {
22548             setPressed(false);
22549         }
22550     }
22551 
22552     /**
22553      * Base class for derived classes that want to save and restore their own
22554      * state in {@link android.view.View#onSaveInstanceState()}.
22555      */
22556     public static class BaseSavedState extends AbsSavedState {
22557         String mStartActivityRequestWhoSaved;
22558 
22559         /**
22560          * Constructor used when reading from a parcel. Reads the state of the superclass.
22561          *
22562          * @param source parcel to read from
22563          */
BaseSavedState(Parcel source)22564         public BaseSavedState(Parcel source) {
22565             this(source, null);
22566         }
22567 
22568         /**
22569          * Constructor used when reading from a parcel using a given class loader.
22570          * Reads the state of the superclass.
22571          *
22572          * @param source parcel to read from
22573          * @param loader ClassLoader to use for reading
22574          */
BaseSavedState(Parcel source, ClassLoader loader)22575         public BaseSavedState(Parcel source, ClassLoader loader) {
22576             super(source, loader);
22577             mStartActivityRequestWhoSaved = source.readString();
22578         }
22579 
22580         /**
22581          * Constructor called by derived classes when creating their SavedState objects
22582          *
22583          * @param superState The state of the superclass of this view
22584          */
BaseSavedState(Parcelable superState)22585         public BaseSavedState(Parcelable superState) {
22586             super(superState);
22587         }
22588 
22589         @Override
writeToParcel(Parcel out, int flags)22590         public void writeToParcel(Parcel out, int flags) {
22591             super.writeToParcel(out, flags);
22592             out.writeString(mStartActivityRequestWhoSaved);
22593         }
22594 
22595         public static final Parcelable.Creator<BaseSavedState> CREATOR
22596                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22597             @Override
22598             public BaseSavedState createFromParcel(Parcel in) {
22599                 return new BaseSavedState(in);
22600             }
22601 
22602             @Override
22603             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22604                 return new BaseSavedState(in, loader);
22605             }
22606 
22607             @Override
22608             public BaseSavedState[] newArray(int size) {
22609                 return new BaseSavedState[size];
22610             }
22611         };
22612     }
22613 
22614     /**
22615      * A set of information given to a view when it is attached to its parent
22616      * window.
22617      */
22618     final static class AttachInfo {
22619         interface Callbacks {
playSoundEffect(int effectId)22620             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)22621             boolean performHapticFeedback(int effectId, boolean always);
22622         }
22623 
22624         /**
22625          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22626          * to a Handler. This class contains the target (View) to invalidate and
22627          * the coordinates of the dirty rectangle.
22628          *
22629          * For performance purposes, this class also implements a pool of up to
22630          * POOL_LIMIT objects that get reused. This reduces memory allocations
22631          * whenever possible.
22632          */
22633         static class InvalidateInfo {
22634             private static final int POOL_LIMIT = 10;
22635 
22636             private static final SynchronizedPool<InvalidateInfo> sPool =
22637                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22638 
22639             View target;
22640 
22641             int left;
22642             int top;
22643             int right;
22644             int bottom;
22645 
obtain()22646             public static InvalidateInfo obtain() {
22647                 InvalidateInfo instance = sPool.acquire();
22648                 return (instance != null) ? instance : new InvalidateInfo();
22649             }
22650 
recycle()22651             public void recycle() {
22652                 target = null;
22653                 sPool.release(this);
22654             }
22655         }
22656 
22657         final IWindowSession mSession;
22658 
22659         final IWindow mWindow;
22660 
22661         final IBinder mWindowToken;
22662 
22663         final Display mDisplay;
22664 
22665         final Callbacks mRootCallbacks;
22666 
22667         IWindowId mIWindowId;
22668         WindowId mWindowId;
22669 
22670         /**
22671          * The top view of the hierarchy.
22672          */
22673         View mRootView;
22674 
22675         IBinder mPanelParentWindowToken;
22676 
22677         boolean mHardwareAccelerated;
22678         boolean mHardwareAccelerationRequested;
22679         ThreadedRenderer mHardwareRenderer;
22680         List<RenderNode> mPendingAnimatingRenderNodes;
22681 
22682         /**
22683          * The state of the display to which the window is attached, as reported
22684          * by {@link Display#getState()}.  Note that the display state constants
22685          * declared by {@link Display} do not exactly line up with the screen state
22686          * constants declared by {@link View} (there are more display states than
22687          * screen states).
22688          */
22689         int mDisplayState = Display.STATE_UNKNOWN;
22690 
22691         /**
22692          * Scale factor used by the compatibility mode
22693          */
22694         float mApplicationScale;
22695 
22696         /**
22697          * Indicates whether the application is in compatibility mode
22698          */
22699         boolean mScalingRequired;
22700 
22701         /**
22702          * Left position of this view's window
22703          */
22704         int mWindowLeft;
22705 
22706         /**
22707          * Top position of this view's window
22708          */
22709         int mWindowTop;
22710 
22711         /**
22712          * Indicates whether views need to use 32-bit drawing caches
22713          */
22714         boolean mUse32BitDrawingCache;
22715 
22716         /**
22717          * For windows that are full-screen but using insets to layout inside
22718          * of the screen areas, these are the current insets to appear inside
22719          * the overscan area of the display.
22720          */
22721         final Rect mOverscanInsets = new Rect();
22722 
22723         /**
22724          * For windows that are full-screen but using insets to layout inside
22725          * of the screen decorations, these are the current insets for the
22726          * content of the window.
22727          */
22728         final Rect mContentInsets = new Rect();
22729 
22730         /**
22731          * For windows that are full-screen but using insets to layout inside
22732          * of the screen decorations, these are the current insets for the
22733          * actual visible parts of the window.
22734          */
22735         final Rect mVisibleInsets = new Rect();
22736 
22737         /**
22738          * For windows that are full-screen but using insets to layout inside
22739          * of the screen decorations, these are the current insets for the
22740          * stable system windows.
22741          */
22742         final Rect mStableInsets = new Rect();
22743 
22744         /**
22745          * For windows that include areas that are not covered by real surface these are the outsets
22746          * for real surface.
22747          */
22748         final Rect mOutsets = new Rect();
22749 
22750         /**
22751          * In multi-window we force show the navigation bar. Because we don't want that the surface
22752          * size changes in this mode, we instead have a flag whether the navigation bar size should
22753          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22754          */
22755         boolean mAlwaysConsumeNavBar;
22756 
22757         /**
22758          * The internal insets given by this window.  This value is
22759          * supplied by the client (through
22760          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22761          * be given to the window manager when changed to be used in laying
22762          * out windows behind it.
22763          */
22764         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22765                 = new ViewTreeObserver.InternalInsetsInfo();
22766 
22767         /**
22768          * Set to true when mGivenInternalInsets is non-empty.
22769          */
22770         boolean mHasNonEmptyGivenInternalInsets;
22771 
22772         /**
22773          * All views in the window's hierarchy that serve as scroll containers,
22774          * used to determine if the window can be resized or must be panned
22775          * to adjust for a soft input area.
22776          */
22777         final ArrayList<View> mScrollContainers = new ArrayList<View>();
22778 
22779         final KeyEvent.DispatcherState mKeyDispatchState
22780                 = new KeyEvent.DispatcherState();
22781 
22782         /**
22783          * Indicates whether the view's window currently has the focus.
22784          */
22785         boolean mHasWindowFocus;
22786 
22787         /**
22788          * The current visibility of the window.
22789          */
22790         int mWindowVisibility;
22791 
22792         /**
22793          * Indicates the time at which drawing started to occur.
22794          */
22795         long mDrawingTime;
22796 
22797         /**
22798          * Indicates whether or not ignoring the DIRTY_MASK flags.
22799          */
22800         boolean mIgnoreDirtyState;
22801 
22802         /**
22803          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22804          * to avoid clearing that flag prematurely.
22805          */
22806         boolean mSetIgnoreDirtyState = false;
22807 
22808         /**
22809          * Indicates whether the view's window is currently in touch mode.
22810          */
22811         boolean mInTouchMode;
22812 
22813         /**
22814          * Indicates whether the view has requested unbuffered input dispatching for the current
22815          * event stream.
22816          */
22817         boolean mUnbufferedDispatchRequested;
22818 
22819         /**
22820          * Indicates that ViewAncestor should trigger a global layout change
22821          * the next time it performs a traversal
22822          */
22823         boolean mRecomputeGlobalAttributes;
22824 
22825         /**
22826          * Always report new attributes at next traversal.
22827          */
22828         boolean mForceReportNewAttributes;
22829 
22830         /**
22831          * Set during a traveral if any views want to keep the screen on.
22832          */
22833         boolean mKeepScreenOn;
22834 
22835         /**
22836          * Set during a traveral if the light center needs to be updated.
22837          */
22838         boolean mNeedsUpdateLightCenter;
22839 
22840         /**
22841          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22842          */
22843         int mSystemUiVisibility;
22844 
22845         /**
22846          * Hack to force certain system UI visibility flags to be cleared.
22847          */
22848         int mDisabledSystemUiVisibility;
22849 
22850         /**
22851          * Last global system UI visibility reported by the window manager.
22852          */
22853         int mGlobalSystemUiVisibility;
22854 
22855         /**
22856          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22857          * attached.
22858          */
22859         boolean mHasSystemUiListeners;
22860 
22861         /**
22862          * Set if the window has requested to extend into the overscan region
22863          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22864          */
22865         boolean mOverscanRequested;
22866 
22867         /**
22868          * Set if the visibility of any views has changed.
22869          */
22870         boolean mViewVisibilityChanged;
22871 
22872         /**
22873          * Set to true if a view has been scrolled.
22874          */
22875         boolean mViewScrollChanged;
22876 
22877         /**
22878          * Set to true if high contrast mode enabled
22879          */
22880         boolean mHighContrastText;
22881 
22882         /**
22883          * Set to true if a pointer event is currently being handled.
22884          */
22885         boolean mHandlingPointerEvent;
22886 
22887         /**
22888          * Global to the view hierarchy used as a temporary for dealing with
22889          * x/y points in the transparent region computations.
22890          */
22891         final int[] mTransparentLocation = new int[2];
22892 
22893         /**
22894          * Global to the view hierarchy used as a temporary for dealing with
22895          * x/y points in the ViewGroup.invalidateChild implementation.
22896          */
22897         final int[] mInvalidateChildLocation = new int[2];
22898 
22899         /**
22900          * Global to the view hierarchy used as a temporary for dealng with
22901          * computing absolute on-screen location.
22902          */
22903         final int[] mTmpLocation = new int[2];
22904 
22905         /**
22906          * Global to the view hierarchy used as a temporary for dealing with
22907          * x/y location when view is transformed.
22908          */
22909         final float[] mTmpTransformLocation = new float[2];
22910 
22911         /**
22912          * The view tree observer used to dispatch global events like
22913          * layout, pre-draw, touch mode change, etc.
22914          */
22915         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
22916 
22917         /**
22918          * A Canvas used by the view hierarchy to perform bitmap caching.
22919          */
22920         Canvas mCanvas;
22921 
22922         /**
22923          * The view root impl.
22924          */
22925         final ViewRootImpl mViewRootImpl;
22926 
22927         /**
22928          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
22929          * handler can be used to pump events in the UI events queue.
22930          */
22931         final Handler mHandler;
22932 
22933         /**
22934          * Temporary for use in computing invalidate rectangles while
22935          * calling up the hierarchy.
22936          */
22937         final Rect mTmpInvalRect = new Rect();
22938 
22939         /**
22940          * Temporary for use in computing hit areas with transformed views
22941          */
22942         final RectF mTmpTransformRect = new RectF();
22943 
22944         /**
22945          * Temporary for use in computing hit areas with transformed views
22946          */
22947         final RectF mTmpTransformRect1 = new RectF();
22948 
22949         /**
22950          * Temporary list of rectanges.
22951          */
22952         final List<RectF> mTmpRectList = new ArrayList<>();
22953 
22954         /**
22955          * Temporary for use in transforming invalidation rect
22956          */
22957         final Matrix mTmpMatrix = new Matrix();
22958 
22959         /**
22960          * Temporary for use in transforming invalidation rect
22961          */
22962         final Transformation mTmpTransformation = new Transformation();
22963 
22964         /**
22965          * Temporary for use in querying outlines from OutlineProviders
22966          */
22967         final Outline mTmpOutline = new Outline();
22968 
22969         /**
22970          * Temporary list for use in collecting focusable descendents of a view.
22971          */
22972         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
22973 
22974         /**
22975          * The id of the window for accessibility purposes.
22976          */
22977         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
22978 
22979         /**
22980          * Flags related to accessibility processing.
22981          *
22982          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
22983          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
22984          */
22985         int mAccessibilityFetchFlags;
22986 
22987         /**
22988          * The drawable for highlighting accessibility focus.
22989          */
22990         Drawable mAccessibilityFocusDrawable;
22991 
22992         /**
22993          * Show where the margins, bounds and layout bounds are for each view.
22994          */
22995         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
22996 
22997         /**
22998          * Point used to compute visible regions.
22999          */
23000         final Point mPoint = new Point();
23001 
23002         /**
23003          * Used to track which View originated a requestLayout() call, used when
23004          * requestLayout() is called during layout.
23005          */
23006         View mViewRequestingLayout;
23007 
23008         /**
23009          * Used to track views that need (at least) a partial relayout at their current size
23010          * during the next traversal.
23011          */
23012         List<View> mPartialLayoutViews = new ArrayList<>();
23013 
23014         /**
23015          * Swapped with mPartialLayoutViews during layout to avoid concurrent
23016          * modification. Lazily assigned during ViewRootImpl layout.
23017          */
23018         List<View> mEmptyPartialLayoutViews;
23019 
23020         /**
23021          * Used to track the identity of the current drag operation.
23022          */
23023         IBinder mDragToken;
23024 
23025         /**
23026          * The drag shadow surface for the current drag operation.
23027          */
23028         public Surface mDragSurface;
23029 
23030         /**
23031          * Creates a new set of attachment information with the specified
23032          * events handler and thread.
23033          *
23034          * @param handler the events handler the view must use
23035          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer)23036         AttachInfo(IWindowSession session, IWindow window, Display display,
23037                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23038             mSession = session;
23039             mWindow = window;
23040             mWindowToken = window.asBinder();
23041             mDisplay = display;
23042             mViewRootImpl = viewRootImpl;
23043             mHandler = handler;
23044             mRootCallbacks = effectPlayer;
23045         }
23046     }
23047 
23048     /**
23049      * <p>ScrollabilityCache holds various fields used by a View when scrolling
23050      * is supported. This avoids keeping too many unused fields in most
23051      * instances of View.</p>
23052      */
23053     private static class ScrollabilityCache implements Runnable {
23054 
23055         /**
23056          * Scrollbars are not visible
23057          */
23058         public static final int OFF = 0;
23059 
23060         /**
23061          * Scrollbars are visible
23062          */
23063         public static final int ON = 1;
23064 
23065         /**
23066          * Scrollbars are fading away
23067          */
23068         public static final int FADING = 2;
23069 
23070         public boolean fadeScrollBars;
23071 
23072         public int fadingEdgeLength;
23073         public int scrollBarDefaultDelayBeforeFade;
23074         public int scrollBarFadeDuration;
23075 
23076         public int scrollBarSize;
23077         public ScrollBarDrawable scrollBar;
23078         public float[] interpolatorValues;
23079         public View host;
23080 
23081         public final Paint paint;
23082         public final Matrix matrix;
23083         public Shader shader;
23084 
23085         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23086 
23087         private static final float[] OPAQUE = { 255 };
23088         private static final float[] TRANSPARENT = { 0.0f };
23089 
23090         /**
23091          * When fading should start. This time moves into the future every time
23092          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23093          */
23094         public long fadeStartTime;
23095 
23096 
23097         /**
23098          * The current state of the scrollbars: ON, OFF, or FADING
23099          */
23100         public int state = OFF;
23101 
23102         private int mLastColor;
23103 
23104         public final Rect mScrollBarBounds = new Rect();
23105 
23106         public static final int NOT_DRAGGING = 0;
23107         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23108         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23109         public int mScrollBarDraggingState = NOT_DRAGGING;
23110 
23111         public float mScrollBarDraggingPos = 0;
23112 
ScrollabilityCache(ViewConfiguration configuration, View host)23113         public ScrollabilityCache(ViewConfiguration configuration, View host) {
23114             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23115             scrollBarSize = configuration.getScaledScrollBarSize();
23116             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23117             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23118 
23119             paint = new Paint();
23120             matrix = new Matrix();
23121             // use use a height of 1, and then wack the matrix each time we
23122             // actually use it.
23123             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23124             paint.setShader(shader);
23125             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23126 
23127             this.host = host;
23128         }
23129 
setFadeColor(int color)23130         public void setFadeColor(int color) {
23131             if (color != mLastColor) {
23132                 mLastColor = color;
23133 
23134                 if (color != 0) {
23135                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23136                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23137                     paint.setShader(shader);
23138                     // Restore the default transfer mode (src_over)
23139                     paint.setXfermode(null);
23140                 } else {
23141                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23142                     paint.setShader(shader);
23143                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23144                 }
23145             }
23146         }
23147 
run()23148         public void run() {
23149             long now = AnimationUtils.currentAnimationTimeMillis();
23150             if (now >= fadeStartTime) {
23151 
23152                 // the animation fades the scrollbars out by changing
23153                 // the opacity (alpha) from fully opaque to fully
23154                 // transparent
23155                 int nextFrame = (int) now;
23156                 int framesCount = 0;
23157 
23158                 Interpolator interpolator = scrollBarInterpolator;
23159 
23160                 // Start opaque
23161                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23162 
23163                 // End transparent
23164                 nextFrame += scrollBarFadeDuration;
23165                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23166 
23167                 state = FADING;
23168 
23169                 // Kick off the fade animation
23170                 host.invalidate(true);
23171             }
23172         }
23173     }
23174 
23175     /**
23176      * Resuable callback for sending
23177      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23178      */
23179     private class SendViewScrolledAccessibilityEvent implements Runnable {
23180         public volatile boolean mIsPending;
23181 
run()23182         public void run() {
23183             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23184             mIsPending = false;
23185         }
23186     }
23187 
23188     /**
23189      * <p>
23190      * This class represents a delegate that can be registered in a {@link View}
23191      * to enhance accessibility support via composition rather via inheritance.
23192      * It is specifically targeted to widget developers that extend basic View
23193      * classes i.e. classes in package android.view, that would like their
23194      * applications to be backwards compatible.
23195      * </p>
23196      * <div class="special reference">
23197      * <h3>Developer Guides</h3>
23198      * <p>For more information about making applications accessible, read the
23199      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23200      * developer guide.</p>
23201      * </div>
23202      * <p>
23203      * A scenario in which a developer would like to use an accessibility delegate
23204      * is overriding a method introduced in a later API version then the minimal API
23205      * version supported by the application. For example, the method
23206      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23207      * in API version 4 when the accessibility APIs were first introduced. If a
23208      * developer would like his application to run on API version 4 devices (assuming
23209      * all other APIs used by the application are version 4 or lower) and take advantage
23210      * of this method, instead of overriding the method which would break the application's
23211      * backwards compatibility, he can override the corresponding method in this
23212      * delegate and register the delegate in the target View if the API version of
23213      * the system is high enough i.e. the API version is same or higher to the API
23214      * version that introduced
23215      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23216      * </p>
23217      * <p>
23218      * Here is an example implementation:
23219      * </p>
23220      * <code><pre><p>
23221      * if (Build.VERSION.SDK_INT >= 14) {
23222      *     // If the API version is equal of higher than the version in
23223      *     // which onInitializeAccessibilityNodeInfo was introduced we
23224      *     // register a delegate with a customized implementation.
23225      *     View view = findViewById(R.id.view_id);
23226      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23227      *         public void onInitializeAccessibilityNodeInfo(View host,
23228      *                 AccessibilityNodeInfo info) {
23229      *             // Let the default implementation populate the info.
23230      *             super.onInitializeAccessibilityNodeInfo(host, info);
23231      *             // Set some other information.
23232      *             info.setEnabled(host.isEnabled());
23233      *         }
23234      *     });
23235      * }
23236      * </code></pre></p>
23237      * <p>
23238      * This delegate contains methods that correspond to the accessibility methods
23239      * in View. If a delegate has been specified the implementation in View hands
23240      * off handling to the corresponding method in this delegate. The default
23241      * implementation the delegate methods behaves exactly as the corresponding
23242      * method in View for the case of no accessibility delegate been set. Hence,
23243      * to customize the behavior of a View method, clients can override only the
23244      * corresponding delegate method without altering the behavior of the rest
23245      * accessibility related methods of the host view.
23246      * </p>
23247      * <p>
23248      * <strong>Note:</strong> On platform versions prior to
23249      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23250      * views in the {@code android.widget.*} package are called <i>before</i>
23251      * host methods. This prevents certain properties such as class name from
23252      * being modified by overriding
23253      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23254      * as any changes will be overwritten by the host class.
23255      * <p>
23256      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23257      * methods are called <i>after</i> host methods, which all properties to be
23258      * modified without being overwritten by the host class.
23259      */
23260     public static class AccessibilityDelegate {
23261 
23262         /**
23263          * Sends an accessibility event of the given type. If accessibility is not
23264          * enabled this method has no effect.
23265          * <p>
23266          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23267          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23268          * been set.
23269          * </p>
23270          *
23271          * @param host The View hosting the delegate.
23272          * @param eventType The type of the event to send.
23273          *
23274          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23275          */
sendAccessibilityEvent(View host, int eventType)23276         public void sendAccessibilityEvent(View host, int eventType) {
23277             host.sendAccessibilityEventInternal(eventType);
23278         }
23279 
23280         /**
23281          * Performs the specified accessibility action on the view. For
23282          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23283          * <p>
23284          * The default implementation behaves as
23285          * {@link View#performAccessibilityAction(int, Bundle)
23286          *  View#performAccessibilityAction(int, Bundle)} for the case of
23287          *  no accessibility delegate been set.
23288          * </p>
23289          *
23290          * @param action The action to perform.
23291          * @return Whether the action was performed.
23292          *
23293          * @see View#performAccessibilityAction(int, Bundle)
23294          *      View#performAccessibilityAction(int, Bundle)
23295          */
performAccessibilityAction(View host, int action, Bundle args)23296         public boolean performAccessibilityAction(View host, int action, Bundle args) {
23297             return host.performAccessibilityActionInternal(action, args);
23298         }
23299 
23300         /**
23301          * Sends an accessibility event. This method behaves exactly as
23302          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23303          * empty {@link AccessibilityEvent} and does not perform a check whether
23304          * accessibility is enabled.
23305          * <p>
23306          * The default implementation behaves as
23307          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23308          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23309          * the case of no accessibility delegate been set.
23310          * </p>
23311          *
23312          * @param host The View hosting the delegate.
23313          * @param event The event to send.
23314          *
23315          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23316          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23317          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)23318         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23319             host.sendAccessibilityEventUncheckedInternal(event);
23320         }
23321 
23322         /**
23323          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23324          * to its children for adding their text content to the event.
23325          * <p>
23326          * The default implementation behaves as
23327          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23328          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23329          * the case of no accessibility delegate been set.
23330          * </p>
23331          *
23332          * @param host The View hosting the delegate.
23333          * @param event The event.
23334          * @return True if the event population was completed.
23335          *
23336          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23337          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23338          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)23339         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23340             return host.dispatchPopulateAccessibilityEventInternal(event);
23341         }
23342 
23343         /**
23344          * Gives a chance to the host View to populate the accessibility event with its
23345          * text content.
23346          * <p>
23347          * The default implementation behaves as
23348          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23349          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23350          * the case of no accessibility delegate been set.
23351          * </p>
23352          *
23353          * @param host The View hosting the delegate.
23354          * @param event The accessibility event which to populate.
23355          *
23356          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23357          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23358          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)23359         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23360             host.onPopulateAccessibilityEventInternal(event);
23361         }
23362 
23363         /**
23364          * Initializes an {@link AccessibilityEvent} with information about the
23365          * the host View which is the event source.
23366          * <p>
23367          * The default implementation behaves as
23368          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23369          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23370          * the case of no accessibility delegate been set.
23371          * </p>
23372          *
23373          * @param host The View hosting the delegate.
23374          * @param event The event to initialize.
23375          *
23376          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23377          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
23378          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)23379         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23380             host.onInitializeAccessibilityEventInternal(event);
23381         }
23382 
23383         /**
23384          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23385          * <p>
23386          * The default implementation behaves as
23387          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23388          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23389          * the case of no accessibility delegate been set.
23390          * </p>
23391          *
23392          * @param host The View hosting the delegate.
23393          * @param info The instance to initialize.
23394          *
23395          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23396          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23397          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)23398         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23399             host.onInitializeAccessibilityNodeInfoInternal(info);
23400         }
23401 
23402         /**
23403          * Called when a child of the host View has requested sending an
23404          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23405          * to augment the event.
23406          * <p>
23407          * The default implementation behaves as
23408          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23409          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23410          * the case of no accessibility delegate been set.
23411          * </p>
23412          *
23413          * @param host The View hosting the delegate.
23414          * @param child The child which requests sending the event.
23415          * @param event The event to be sent.
23416          * @return True if the event should be sent
23417          *
23418          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23419          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23420          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)23421         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23422                 AccessibilityEvent event) {
23423             return host.onRequestSendAccessibilityEventInternal(child, event);
23424         }
23425 
23426         /**
23427          * Gets the provider for managing a virtual view hierarchy rooted at this View
23428          * and reported to {@link android.accessibilityservice.AccessibilityService}s
23429          * that explore the window content.
23430          * <p>
23431          * The default implementation behaves as
23432          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23433          * the case of no accessibility delegate been set.
23434          * </p>
23435          *
23436          * @return The provider.
23437          *
23438          * @see AccessibilityNodeProvider
23439          */
getAccessibilityNodeProvider(View host)23440         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23441             return null;
23442         }
23443 
23444         /**
23445          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23446          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23447          * This method is responsible for obtaining an accessibility node info from a
23448          * pool of reusable instances and calling
23449          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23450          * view to initialize the former.
23451          * <p>
23452          * <strong>Note:</strong> The client is responsible for recycling the obtained
23453          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23454          * creation.
23455          * </p>
23456          * <p>
23457          * The default implementation behaves as
23458          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23459          * the case of no accessibility delegate been set.
23460          * </p>
23461          * @return A populated {@link AccessibilityNodeInfo}.
23462          *
23463          * @see AccessibilityNodeInfo
23464          *
23465          * @hide
23466          */
createAccessibilityNodeInfo(View host)23467         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23468             return host.createAccessibilityNodeInfoInternal();
23469         }
23470     }
23471 
23472     private class MatchIdPredicate implements Predicate<View> {
23473         public int mId;
23474 
23475         @Override
apply(View view)23476         public boolean apply(View view) {
23477             return (view.mID == mId);
23478         }
23479     }
23480 
23481     private class MatchLabelForPredicate implements Predicate<View> {
23482         private int mLabeledId;
23483 
23484         @Override
apply(View view)23485         public boolean apply(View view) {
23486             return (view.mLabelForId == mLabeledId);
23487         }
23488     }
23489 
23490     private class SendViewStateChangedAccessibilityEvent implements Runnable {
23491         private int mChangeTypes = 0;
23492         private boolean mPosted;
23493         private boolean mPostedWithDelay;
23494         private long mLastEventTimeMillis;
23495 
23496         @Override
run()23497         public void run() {
23498             mPosted = false;
23499             mPostedWithDelay = false;
23500             mLastEventTimeMillis = SystemClock.uptimeMillis();
23501             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23502                 final AccessibilityEvent event = AccessibilityEvent.obtain();
23503                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23504                 event.setContentChangeTypes(mChangeTypes);
23505                 sendAccessibilityEventUnchecked(event);
23506             }
23507             mChangeTypes = 0;
23508         }
23509 
runOrPost(int changeType)23510         public void runOrPost(int changeType) {
23511             mChangeTypes |= changeType;
23512 
23513             // If this is a live region or the child of a live region, collect
23514             // all events from this frame and send them on the next frame.
23515             if (inLiveRegion()) {
23516                 // If we're already posted with a delay, remove that.
23517                 if (mPostedWithDelay) {
23518                     removeCallbacks(this);
23519                     mPostedWithDelay = false;
23520                 }
23521                 // Only post if we're not already posted.
23522                 if (!mPosted) {
23523                     post(this);
23524                     mPosted = true;
23525                 }
23526                 return;
23527             }
23528 
23529             if (mPosted) {
23530                 return;
23531             }
23532 
23533             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23534             final long minEventIntevalMillis =
23535                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23536             if (timeSinceLastMillis >= minEventIntevalMillis) {
23537                 removeCallbacks(this);
23538                 run();
23539             } else {
23540                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23541                 mPostedWithDelay = true;
23542             }
23543         }
23544     }
23545 
inLiveRegion()23546     private boolean inLiveRegion() {
23547         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23548             return true;
23549         }
23550 
23551         ViewParent parent = getParent();
23552         while (parent instanceof View) {
23553             if (((View) parent).getAccessibilityLiveRegion()
23554                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23555                 return true;
23556             }
23557             parent = parent.getParent();
23558         }
23559 
23560         return false;
23561     }
23562 
23563     /**
23564      * Dump all private flags in readable format, useful for documentation and
23565      * sanity checking.
23566      */
dumpFlags()23567     private static void dumpFlags() {
23568         final HashMap<String, String> found = Maps.newHashMap();
23569         try {
23570             for (Field field : View.class.getDeclaredFields()) {
23571                 final int modifiers = field.getModifiers();
23572                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23573                     if (field.getType().equals(int.class)) {
23574                         final int value = field.getInt(null);
23575                         dumpFlag(found, field.getName(), value);
23576                     } else if (field.getType().equals(int[].class)) {
23577                         final int[] values = (int[]) field.get(null);
23578                         for (int i = 0; i < values.length; i++) {
23579                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23580                         }
23581                     }
23582                 }
23583             }
23584         } catch (IllegalAccessException e) {
23585             throw new RuntimeException(e);
23586         }
23587 
23588         final ArrayList<String> keys = Lists.newArrayList();
23589         keys.addAll(found.keySet());
23590         Collections.sort(keys);
23591         for (String key : keys) {
23592             Log.d(VIEW_LOG_TAG, found.get(key));
23593         }
23594     }
23595 
dumpFlag(HashMap<String, String> found, String name, int value)23596     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23597         // Sort flags by prefix, then by bits, always keeping unique keys
23598         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23599         final int prefix = name.indexOf('_');
23600         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23601         final String output = bits + " " + name;
23602         found.put(key, output);
23603     }
23604 
23605     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)23606     public void encode(@NonNull ViewHierarchyEncoder stream) {
23607         stream.beginObject(this);
23608         encodeProperties(stream);
23609         stream.endObject();
23610     }
23611 
23612     /** {@hide} */
23613     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)23614     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23615         Object resolveId = ViewDebug.resolveId(getContext(), mID);
23616         if (resolveId instanceof String) {
23617             stream.addProperty("id", (String) resolveId);
23618         } else {
23619             stream.addProperty("id", mID);
23620         }
23621 
23622         stream.addProperty("misc:transformation.alpha",
23623                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23624         stream.addProperty("misc:transitionName", getTransitionName());
23625 
23626         // layout
23627         stream.addProperty("layout:left", mLeft);
23628         stream.addProperty("layout:right", mRight);
23629         stream.addProperty("layout:top", mTop);
23630         stream.addProperty("layout:bottom", mBottom);
23631         stream.addProperty("layout:width", getWidth());
23632         stream.addProperty("layout:height", getHeight());
23633         stream.addProperty("layout:layoutDirection", getLayoutDirection());
23634         stream.addProperty("layout:layoutRtl", isLayoutRtl());
23635         stream.addProperty("layout:hasTransientState", hasTransientState());
23636         stream.addProperty("layout:baseline", getBaseline());
23637 
23638         // layout params
23639         ViewGroup.LayoutParams layoutParams = getLayoutParams();
23640         if (layoutParams != null) {
23641             stream.addPropertyKey("layoutParams");
23642             layoutParams.encode(stream);
23643         }
23644 
23645         // scrolling
23646         stream.addProperty("scrolling:scrollX", mScrollX);
23647         stream.addProperty("scrolling:scrollY", mScrollY);
23648 
23649         // padding
23650         stream.addProperty("padding:paddingLeft", mPaddingLeft);
23651         stream.addProperty("padding:paddingRight", mPaddingRight);
23652         stream.addProperty("padding:paddingTop", mPaddingTop);
23653         stream.addProperty("padding:paddingBottom", mPaddingBottom);
23654         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23655         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23656         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23657         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23658         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23659 
23660         // measurement
23661         stream.addProperty("measurement:minHeight", mMinHeight);
23662         stream.addProperty("measurement:minWidth", mMinWidth);
23663         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23664         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23665 
23666         // drawing
23667         stream.addProperty("drawing:elevation", getElevation());
23668         stream.addProperty("drawing:translationX", getTranslationX());
23669         stream.addProperty("drawing:translationY", getTranslationY());
23670         stream.addProperty("drawing:translationZ", getTranslationZ());
23671         stream.addProperty("drawing:rotation", getRotation());
23672         stream.addProperty("drawing:rotationX", getRotationX());
23673         stream.addProperty("drawing:rotationY", getRotationY());
23674         stream.addProperty("drawing:scaleX", getScaleX());
23675         stream.addProperty("drawing:scaleY", getScaleY());
23676         stream.addProperty("drawing:pivotX", getPivotX());
23677         stream.addProperty("drawing:pivotY", getPivotY());
23678         stream.addProperty("drawing:opaque", isOpaque());
23679         stream.addProperty("drawing:alpha", getAlpha());
23680         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23681         stream.addProperty("drawing:shadow", hasShadow());
23682         stream.addProperty("drawing:solidColor", getSolidColor());
23683         stream.addProperty("drawing:layerType", mLayerType);
23684         stream.addProperty("drawing:willNotDraw", willNotDraw());
23685         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23686         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23687         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23688         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23689 
23690         // focus
23691         stream.addProperty("focus:hasFocus", hasFocus());
23692         stream.addProperty("focus:isFocused", isFocused());
23693         stream.addProperty("focus:isFocusable", isFocusable());
23694         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23695 
23696         stream.addProperty("misc:clickable", isClickable());
23697         stream.addProperty("misc:pressed", isPressed());
23698         stream.addProperty("misc:selected", isSelected());
23699         stream.addProperty("misc:touchMode", isInTouchMode());
23700         stream.addProperty("misc:hovered", isHovered());
23701         stream.addProperty("misc:activated", isActivated());
23702 
23703         stream.addProperty("misc:visibility", getVisibility());
23704         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23705         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23706 
23707         stream.addProperty("misc:enabled", isEnabled());
23708         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23709         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23710 
23711         // theme attributes
23712         Resources.Theme theme = getContext().getTheme();
23713         if (theme != null) {
23714             stream.addPropertyKey("theme");
23715             theme.encode(stream);
23716         }
23717 
23718         // view attribute information
23719         int n = mAttributes != null ? mAttributes.length : 0;
23720         stream.addProperty("meta:__attrCount__", n/2);
23721         for (int i = 0; i < n; i += 2) {
23722             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23723         }
23724 
23725         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23726 
23727         // text
23728         stream.addProperty("text:textDirection", getTextDirection());
23729         stream.addProperty("text:textAlignment", getTextAlignment());
23730 
23731         // accessibility
23732         CharSequence contentDescription = getContentDescription();
23733         stream.addProperty("accessibility:contentDescription",
23734                 contentDescription == null ? "" : contentDescription.toString());
23735         stream.addProperty("accessibility:labelFor", getLabelFor());
23736         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23737     }
23738 }
23739