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.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.content.ClipData;
25 import android.content.Context;
26 import android.content.res.ColorStateList;
27 import android.content.res.Configuration;
28 import android.content.res.Resources;
29 import android.content.res.TypedArray;
30 import android.graphics.Bitmap;
31 import android.graphics.Canvas;
32 import android.graphics.Insets;
33 import android.graphics.Interpolator;
34 import android.graphics.LinearGradient;
35 import android.graphics.Matrix;
36 import android.graphics.Outline;
37 import android.graphics.Paint;
38 import android.graphics.Path;
39 import android.graphics.PathMeasure;
40 import android.graphics.PixelFormat;
41 import android.graphics.Point;
42 import android.graphics.PorterDuff;
43 import android.graphics.PorterDuffXfermode;
44 import android.graphics.Rect;
45 import android.graphics.RectF;
46 import android.graphics.Region;
47 import android.graphics.Shader;
48 import android.graphics.drawable.ColorDrawable;
49 import android.graphics.drawable.Drawable;
50 import android.hardware.display.DisplayManagerGlobal;
51 import android.os.Bundle;
52 import android.os.Handler;
53 import android.os.IBinder;
54 import android.os.Parcel;
55 import android.os.Parcelable;
56 import android.os.RemoteException;
57 import android.os.SystemClock;
58 import android.os.SystemProperties;
59 import android.os.Trace;
60 import android.text.TextUtils;
61 import android.util.AttributeSet;
62 import android.util.FloatProperty;
63 import android.util.LayoutDirection;
64 import android.util.Log;
65 import android.util.LongSparseLongArray;
66 import android.util.Pools.SynchronizedPool;
67 import android.util.Property;
68 import android.util.SparseArray;
69 import android.util.SuperNotCalledException;
70 import android.util.TypedValue;
71 import android.view.ContextMenu.ContextMenuInfo;
72 import android.view.AccessibilityIterators.TextSegmentIterator;
73 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
74 import android.view.AccessibilityIterators.WordTextSegmentIterator;
75 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
76 import android.view.accessibility.AccessibilityEvent;
77 import android.view.accessibility.AccessibilityEventSource;
78 import android.view.accessibility.AccessibilityManager;
79 import android.view.accessibility.AccessibilityNodeInfo;
80 import android.view.accessibility.AccessibilityNodeProvider;
81 import android.view.animation.Animation;
82 import android.view.animation.AnimationUtils;
83 import android.view.animation.Transformation;
84 import android.view.inputmethod.EditorInfo;
85 import android.view.inputmethod.InputConnection;
86 import android.view.inputmethod.InputMethodManager;
87 import android.widget.ScrollBarDrawable;
88 
89 import static android.os.Build.VERSION_CODES.*;
90 import static java.lang.Math.max;
91 
92 import com.android.internal.R;
93 import com.android.internal.util.Predicate;
94 import com.android.internal.view.menu.MenuBuilder;
95 import com.google.android.collect.Lists;
96 import com.google.android.collect.Maps;
97 
98 import java.lang.annotation.Retention;
99 import java.lang.annotation.RetentionPolicy;
100 import java.lang.ref.WeakReference;
101 import java.lang.reflect.Field;
102 import java.lang.reflect.InvocationTargetException;
103 import java.lang.reflect.Method;
104 import java.lang.reflect.Modifier;
105 import java.util.ArrayList;
106 import java.util.Arrays;
107 import java.util.Collections;
108 import java.util.HashMap;
109 import java.util.List;
110 import java.util.Locale;
111 import java.util.Map;
112 import java.util.concurrent.CopyOnWriteArrayList;
113 import java.util.concurrent.atomic.AtomicInteger;
114 
115 /**
116  * <p>
117  * This class represents the basic building block for user interface components. A View
118  * occupies a rectangular area on the screen and is responsible for drawing and
119  * event handling. View is the base class for <em>widgets</em>, which are
120  * used to create interactive UI components (buttons, text fields, etc.). The
121  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
122  * are invisible containers that hold other Views (or other ViewGroups) and define
123  * their layout properties.
124  * </p>
125  *
126  * <div class="special reference">
127  * <h3>Developer Guides</h3>
128  * <p>For information about using this class to develop your application's user interface,
129  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
130  * </div>
131  *
132  * <a name="Using"></a>
133  * <h3>Using Views</h3>
134  * <p>
135  * All of the views in a window are arranged in a single tree. You can add views
136  * either from code or by specifying a tree of views in one or more XML layout
137  * files. There are many specialized subclasses of views that act as controls or
138  * are capable of displaying text, images, or other content.
139  * </p>
140  * <p>
141  * Once you have created a tree of views, there are typically a few types of
142  * common operations you may wish to perform:
143  * <ul>
144  * <li><strong>Set properties:</strong> for example setting the text of a
145  * {@link android.widget.TextView}. The available properties and the methods
146  * that set them will vary among the different subclasses of views. Note that
147  * properties that are known at build time can be set in the XML layout
148  * files.</li>
149  * <li><strong>Set focus:</strong> The framework will handled moving focus in
150  * response to user input. To force focus to a specific view, call
151  * {@link #requestFocus}.</li>
152  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
153  * that will be notified when something interesting happens to the view. For
154  * example, all views will let you set a listener to be notified when the view
155  * gains or loses focus. You can register such a listener using
156  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
157  * Other view subclasses offer more specialized listeners. For example, a Button
158  * exposes a listener to notify clients when the button is clicked.</li>
159  * <li><strong>Set visibility:</strong> You can hide or show views using
160  * {@link #setVisibility(int)}.</li>
161  * </ul>
162  * </p>
163  * <p><em>
164  * Note: The Android framework is responsible for measuring, laying out and
165  * drawing views. You should not call methods that perform these actions on
166  * views yourself unless you are actually implementing a
167  * {@link android.view.ViewGroup}.
168  * </em></p>
169  *
170  * <a name="Lifecycle"></a>
171  * <h3>Implementing a Custom View</h3>
172  *
173  * <p>
174  * To implement a custom view, you will usually begin by providing overrides for
175  * some of the standard methods that the framework calls on all views. You do
176  * not need to override all of these methods. In fact, you can start by just
177  * overriding {@link #onDraw(android.graphics.Canvas)}.
178  * <table border="2" width="85%" align="center" cellpadding="5">
179  *     <thead>
180  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
181  *     </thead>
182  *
183  *     <tbody>
184  *     <tr>
185  *         <td rowspan="2">Creation</td>
186  *         <td>Constructors</td>
187  *         <td>There is a form of the constructor that are called when the view
188  *         is created from code and a form that is called when the view is
189  *         inflated from a layout file. The second form should parse and apply
190  *         any attributes defined in the layout file.
191  *         </td>
192  *     </tr>
193  *     <tr>
194  *         <td><code>{@link #onFinishInflate()}</code></td>
195  *         <td>Called after a view and all of its children has been inflated
196  *         from XML.</td>
197  *     </tr>
198  *
199  *     <tr>
200  *         <td rowspan="3">Layout</td>
201  *         <td><code>{@link #onMeasure(int, int)}</code></td>
202  *         <td>Called to determine the size requirements for this view and all
203  *         of its children.
204  *         </td>
205  *     </tr>
206  *     <tr>
207  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
208  *         <td>Called when this view should assign a size and position to all
209  *         of its children.
210  *         </td>
211  *     </tr>
212  *     <tr>
213  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
214  *         <td>Called when the size of this view has changed.
215  *         </td>
216  *     </tr>
217  *
218  *     <tr>
219  *         <td>Drawing</td>
220  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
221  *         <td>Called when the view should render its content.
222  *         </td>
223  *     </tr>
224  *
225  *     <tr>
226  *         <td rowspan="4">Event processing</td>
227  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
228  *         <td>Called when a new hardware key event occurs.
229  *         </td>
230  *     </tr>
231  *     <tr>
232  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
233  *         <td>Called when a hardware key up event occurs.
234  *         </td>
235  *     </tr>
236  *     <tr>
237  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
238  *         <td>Called when a trackball motion event occurs.
239  *         </td>
240  *     </tr>
241  *     <tr>
242  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
243  *         <td>Called when a touch screen motion event occurs.
244  *         </td>
245  *     </tr>
246  *
247  *     <tr>
248  *         <td rowspan="2">Focus</td>
249  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
250  *         <td>Called when the view gains or loses focus.
251  *         </td>
252  *     </tr>
253  *
254  *     <tr>
255  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
256  *         <td>Called when the window containing the view gains or loses focus.
257  *         </td>
258  *     </tr>
259  *
260  *     <tr>
261  *         <td rowspan="3">Attaching</td>
262  *         <td><code>{@link #onAttachedToWindow()}</code></td>
263  *         <td>Called when the view is attached to a window.
264  *         </td>
265  *     </tr>
266  *
267  *     <tr>
268  *         <td><code>{@link #onDetachedFromWindow}</code></td>
269  *         <td>Called when the view is detached from its window.
270  *         </td>
271  *     </tr>
272  *
273  *     <tr>
274  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
275  *         <td>Called when the visibility of the window containing the view
276  *         has changed.
277  *         </td>
278  *     </tr>
279  *     </tbody>
280  *
281  * </table>
282  * </p>
283  *
284  * <a name="IDs"></a>
285  * <h3>IDs</h3>
286  * Views may have an integer id associated with them. These ids are typically
287  * assigned in the layout XML files, and are used to find specific views within
288  * the view tree. A common pattern is to:
289  * <ul>
290  * <li>Define a Button in the layout file and assign it a unique ID.
291  * <pre>
292  * &lt;Button
293  *     android:id="@+id/my_button"
294  *     android:layout_width="wrap_content"
295  *     android:layout_height="wrap_content"
296  *     android:text="@string/my_button_text"/&gt;
297  * </pre></li>
298  * <li>From the onCreate method of an Activity, find the Button
299  * <pre class="prettyprint">
300  *      Button myButton = (Button) findViewById(R.id.my_button);
301  * </pre></li>
302  * </ul>
303  * <p>
304  * View IDs need not be unique throughout the tree, but it is good practice to
305  * ensure that they are at least unique within the part of the tree you are
306  * searching.
307  * </p>
308  *
309  * <a name="Position"></a>
310  * <h3>Position</h3>
311  * <p>
312  * The geometry of a view is that of a rectangle. A view has a location,
313  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
314  * two dimensions, expressed as a width and a height. The unit for location
315  * and dimensions is the pixel.
316  * </p>
317  *
318  * <p>
319  * It is possible to retrieve the location of a view by invoking the methods
320  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
321  * coordinate of the rectangle representing the view. The latter returns the
322  * top, or Y, coordinate of the rectangle representing the view. These methods
323  * both return the location of the view relative to its parent. For instance,
324  * when getLeft() returns 20, that means the view is located 20 pixels to the
325  * right of the left edge of its direct parent.
326  * </p>
327  *
328  * <p>
329  * In addition, several convenience methods are offered to avoid unnecessary
330  * computations, namely {@link #getRight()} and {@link #getBottom()}.
331  * These methods return the coordinates of the right and bottom edges of the
332  * rectangle representing the view. For instance, calling {@link #getRight()}
333  * is similar to the following computation: <code>getLeft() + getWidth()</code>
334  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
335  * </p>
336  *
337  * <a name="SizePaddingMargins"></a>
338  * <h3>Size, padding and margins</h3>
339  * <p>
340  * The size of a view is expressed with a width and a height. A view actually
341  * possess two pairs of width and height values.
342  * </p>
343  *
344  * <p>
345  * The first pair is known as <em>measured width</em> and
346  * <em>measured height</em>. These dimensions define how big a view wants to be
347  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
348  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
349  * and {@link #getMeasuredHeight()}.
350  * </p>
351  *
352  * <p>
353  * The second pair is simply known as <em>width</em> and <em>height</em>, or
354  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
355  * dimensions define the actual size of the view on screen, at drawing time and
356  * after layout. These values may, but do not have to, be different from the
357  * measured width and height. The width and height can be obtained by calling
358  * {@link #getWidth()} and {@link #getHeight()}.
359  * </p>
360  *
361  * <p>
362  * To measure its dimensions, a view takes into account its padding. The padding
363  * is expressed in pixels for the left, top, right and bottom parts of the view.
364  * Padding can be used to offset the content of the view by a specific amount of
365  * pixels. For instance, a left padding of 2 will push the view's content by
366  * 2 pixels to the right of the left edge. Padding can be set using the
367  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
368  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
369  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
370  * {@link #getPaddingEnd()}.
371  * </p>
372  *
373  * <p>
374  * Even though a view can define a padding, it does not provide any support for
375  * margins. However, view groups provide such a support. Refer to
376  * {@link android.view.ViewGroup} and
377  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
378  * </p>
379  *
380  * <a name="Layout"></a>
381  * <h3>Layout</h3>
382  * <p>
383  * Layout is a two pass process: a measure pass and a layout pass. The measuring
384  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
385  * of the view tree. Each view pushes dimension specifications down the tree
386  * during the recursion. At the end of the measure pass, every view has stored
387  * its measurements. The second pass happens in
388  * {@link #layout(int,int,int,int)} and is also top-down. During
389  * this pass each parent is responsible for positioning all of its children
390  * using the sizes computed in the measure pass.
391  * </p>
392  *
393  * <p>
394  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
395  * {@link #getMeasuredHeight()} values must be set, along with those for all of
396  * that view's descendants. A view's measured width and measured height values
397  * must respect the constraints imposed by the view's parents. This guarantees
398  * that at the end of the measure pass, all parents accept all of their
399  * children's measurements. A parent view may call measure() more than once on
400  * its children. For example, the parent may measure each child once with
401  * unspecified dimensions to find out how big they want to be, then call
402  * measure() on them again with actual numbers if the sum of all the children's
403  * unconstrained sizes is too big or too small.
404  * </p>
405  *
406  * <p>
407  * The measure pass uses two classes to communicate dimensions. The
408  * {@link MeasureSpec} class is used by views to tell their parents how they
409  * want to be measured and positioned. The base LayoutParams class just
410  * describes how big the view wants to be for both width and height. For each
411  * dimension, it can specify one of:
412  * <ul>
413  * <li> an exact number
414  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
415  * (minus padding)
416  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
417  * enclose its content (plus padding).
418  * </ul>
419  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
420  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
421  * an X and Y value.
422  * </p>
423  *
424  * <p>
425  * MeasureSpecs are used to push requirements down the tree from parent to
426  * child. A MeasureSpec can be in one of three modes:
427  * <ul>
428  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
429  * of a child view. For example, a LinearLayout may call measure() on its child
430  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
431  * tall the child view wants to be given a width of 240 pixels.
432  * <li>EXACTLY: This is used by the parent to impose an exact size on the
433  * child. The child must use this size, and guarantee that all of its
434  * descendants will fit within this size.
435  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
436  * child. The child must guarantee that it and all of its descendants will fit
437  * within this size.
438  * </ul>
439  * </p>
440  *
441  * <p>
442  * To intiate a layout, call {@link #requestLayout}. This method is typically
443  * called by a view on itself when it believes that is can no longer fit within
444  * its current bounds.
445  * </p>
446  *
447  * <a name="Drawing"></a>
448  * <h3>Drawing</h3>
449  * <p>
450  * Drawing is handled by walking the tree and recording the drawing commands of
451  * any View that needs to update. After this, the drawing commands of the
452  * entire tree are issued to screen, clipped to the newly damaged area.
453  * </p>
454  *
455  * <p>
456  * The tree is largely recorded and drawn in order, with parents drawn before
457  * (i.e., behind) their children, with siblings drawn in the order they appear
458  * in the tree. If you set a background drawable for a View, then the View will
459  * draw it before calling back to its <code>onDraw()</code> method. The child
460  * drawing order can be overridden with
461  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
462  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
463  * </p>
464  *
465  * <p>
466  * To force a view to draw, call {@link #invalidate()}.
467  * </p>
468  *
469  * <a name="EventHandlingThreading"></a>
470  * <h3>Event Handling and Threading</h3>
471  * <p>
472  * The basic cycle of a view is as follows:
473  * <ol>
474  * <li>An event comes in and is dispatched to the appropriate view. The view
475  * handles the event and notifies any listeners.</li>
476  * <li>If in the course of processing the event, the view's bounds may need
477  * to be changed, the view will call {@link #requestLayout()}.</li>
478  * <li>Similarly, if in the course of processing the event the view's appearance
479  * may need to be changed, the view will call {@link #invalidate()}.</li>
480  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
481  * the framework will take care of measuring, laying out, and drawing the tree
482  * as appropriate.</li>
483  * </ol>
484  * </p>
485  *
486  * <p><em>Note: The entire view tree is single threaded. You must always be on
487  * the UI thread when calling any method on any view.</em>
488  * If you are doing work on other threads and want to update the state of a view
489  * from that thread, you should use a {@link Handler}.
490  * </p>
491  *
492  * <a name="FocusHandling"></a>
493  * <h3>Focus Handling</h3>
494  * <p>
495  * The framework will handle routine focus movement in response to user input.
496  * This includes changing the focus as views are removed or hidden, or as new
497  * views become available. Views indicate their willingness to take focus
498  * through the {@link #isFocusable} method. To change whether a view can take
499  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
500  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
501  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
502  * </p>
503  * <p>
504  * Focus movement is based on an algorithm which finds the nearest neighbor in a
505  * given direction. In rare cases, the default algorithm may not match the
506  * intended behavior of the developer. In these situations, you can provide
507  * explicit overrides by using these XML attributes in the layout file:
508  * <pre>
509  * nextFocusDown
510  * nextFocusLeft
511  * nextFocusRight
512  * nextFocusUp
513  * </pre>
514  * </p>
515  *
516  *
517  * <p>
518  * To get a particular view to take focus, call {@link #requestFocus()}.
519  * </p>
520  *
521  * <a name="TouchMode"></a>
522  * <h3>Touch Mode</h3>
523  * <p>
524  * When a user is navigating a user interface via directional keys such as a D-pad, it is
525  * necessary to give focus to actionable items such as buttons so the user can see
526  * what will take input.  If the device has touch capabilities, however, and the user
527  * begins interacting with the interface by touching it, it is no longer necessary to
528  * always highlight, or give focus to, a particular view.  This motivates a mode
529  * for interaction named 'touch mode'.
530  * </p>
531  * <p>
532  * For a touch capable device, once the user touches the screen, the device
533  * will enter touch mode.  From this point onward, only views for which
534  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
535  * Other views that are touchable, like buttons, will not take focus when touched; they will
536  * only fire the on click listeners.
537  * </p>
538  * <p>
539  * Any time a user hits a directional key, such as a D-pad direction, the view device will
540  * exit touch mode, and find a view to take focus, so that the user may resume interacting
541  * with the user interface without touching the screen again.
542  * </p>
543  * <p>
544  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
545  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
546  * </p>
547  *
548  * <a name="Scrolling"></a>
549  * <h3>Scrolling</h3>
550  * <p>
551  * The framework provides basic support for views that wish to internally
552  * scroll their content. This includes keeping track of the X and Y scroll
553  * offset as well as mechanisms for drawing scrollbars. See
554  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
555  * {@link #awakenScrollBars()} for more details.
556  * </p>
557  *
558  * <a name="Tags"></a>
559  * <h3>Tags</h3>
560  * <p>
561  * Unlike IDs, tags are not used to identify views. Tags are essentially an
562  * extra piece of information that can be associated with a view. They are most
563  * often used as a convenience to store data related to views in the views
564  * themselves rather than by putting them in a separate structure.
565  * </p>
566  *
567  * <a name="Properties"></a>
568  * <h3>Properties</h3>
569  * <p>
570  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
571  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
572  * available both in the {@link Property} form as well as in similarly-named setter/getter
573  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
574  * be used to set persistent state associated with these rendering-related properties on the view.
575  * The properties and methods can also be used in conjunction with
576  * {@link android.animation.Animator Animator}-based animations, described more in the
577  * <a href="#Animation">Animation</a> section.
578  * </p>
579  *
580  * <a name="Animation"></a>
581  * <h3>Animation</h3>
582  * <p>
583  * Starting with Android 3.0, the preferred way of animating views is to use the
584  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
585  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
586  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
587  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
588  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
589  * makes animating these View properties particularly easy and efficient.
590  * </p>
591  * <p>
592  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
593  * You can attach an {@link Animation} object to a view using
594  * {@link #setAnimation(Animation)} or
595  * {@link #startAnimation(Animation)}. The animation can alter the scale,
596  * rotation, translation and alpha of a view over time. If the animation is
597  * attached to a view that has children, the animation will affect the entire
598  * subtree rooted by that node. When an animation is started, the framework will
599  * take care of redrawing the appropriate views until the animation completes.
600  * </p>
601  *
602  * <a name="Security"></a>
603  * <h3>Security</h3>
604  * <p>
605  * Sometimes it is essential that an application be able to verify that an action
606  * is being performed with the full knowledge and consent of the user, such as
607  * granting a permission request, making a purchase or clicking on an advertisement.
608  * Unfortunately, a malicious application could try to spoof the user into
609  * performing these actions, unaware, by concealing the intended purpose of the view.
610  * As a remedy, the framework offers a touch filtering mechanism that can be used to
611  * improve the security of views that provide access to sensitive functionality.
612  * </p><p>
613  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
614  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
615  * will discard touches that are received whenever the view's window is obscured by
616  * another visible window.  As a result, the view will not receive touches whenever a
617  * toast, dialog or other window appears above the view's window.
618  * </p><p>
619  * For more fine-grained control over security, consider overriding the
620  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
621  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
622  * </p>
623  *
624  * @attr ref android.R.styleable#View_alpha
625  * @attr ref android.R.styleable#View_background
626  * @attr ref android.R.styleable#View_clickable
627  * @attr ref android.R.styleable#View_contentDescription
628  * @attr ref android.R.styleable#View_drawingCacheQuality
629  * @attr ref android.R.styleable#View_duplicateParentState
630  * @attr ref android.R.styleable#View_id
631  * @attr ref android.R.styleable#View_requiresFadingEdge
632  * @attr ref android.R.styleable#View_fadeScrollbars
633  * @attr ref android.R.styleable#View_fadingEdgeLength
634  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
635  * @attr ref android.R.styleable#View_fitsSystemWindows
636  * @attr ref android.R.styleable#View_isScrollContainer
637  * @attr ref android.R.styleable#View_focusable
638  * @attr ref android.R.styleable#View_focusableInTouchMode
639  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
640  * @attr ref android.R.styleable#View_keepScreenOn
641  * @attr ref android.R.styleable#View_layerType
642  * @attr ref android.R.styleable#View_layoutDirection
643  * @attr ref android.R.styleable#View_longClickable
644  * @attr ref android.R.styleable#View_minHeight
645  * @attr ref android.R.styleable#View_minWidth
646  * @attr ref android.R.styleable#View_nextFocusDown
647  * @attr ref android.R.styleable#View_nextFocusLeft
648  * @attr ref android.R.styleable#View_nextFocusRight
649  * @attr ref android.R.styleable#View_nextFocusUp
650  * @attr ref android.R.styleable#View_onClick
651  * @attr ref android.R.styleable#View_padding
652  * @attr ref android.R.styleable#View_paddingBottom
653  * @attr ref android.R.styleable#View_paddingLeft
654  * @attr ref android.R.styleable#View_paddingRight
655  * @attr ref android.R.styleable#View_paddingTop
656  * @attr ref android.R.styleable#View_paddingStart
657  * @attr ref android.R.styleable#View_paddingEnd
658  * @attr ref android.R.styleable#View_saveEnabled
659  * @attr ref android.R.styleable#View_rotation
660  * @attr ref android.R.styleable#View_rotationX
661  * @attr ref android.R.styleable#View_rotationY
662  * @attr ref android.R.styleable#View_scaleX
663  * @attr ref android.R.styleable#View_scaleY
664  * @attr ref android.R.styleable#View_scrollX
665  * @attr ref android.R.styleable#View_scrollY
666  * @attr ref android.R.styleable#View_scrollbarSize
667  * @attr ref android.R.styleable#View_scrollbarStyle
668  * @attr ref android.R.styleable#View_scrollbars
669  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
670  * @attr ref android.R.styleable#View_scrollbarFadeDuration
671  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
672  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
673  * @attr ref android.R.styleable#View_scrollbarThumbVertical
674  * @attr ref android.R.styleable#View_scrollbarTrackVertical
675  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
676  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
677  * @attr ref android.R.styleable#View_stateListAnimator
678  * @attr ref android.R.styleable#View_transitionName
679  * @attr ref android.R.styleable#View_soundEffectsEnabled
680  * @attr ref android.R.styleable#View_tag
681  * @attr ref android.R.styleable#View_textAlignment
682  * @attr ref android.R.styleable#View_textDirection
683  * @attr ref android.R.styleable#View_transformPivotX
684  * @attr ref android.R.styleable#View_transformPivotY
685  * @attr ref android.R.styleable#View_translationX
686  * @attr ref android.R.styleable#View_translationY
687  * @attr ref android.R.styleable#View_translationZ
688  * @attr ref android.R.styleable#View_visibility
689  *
690  * @see android.view.ViewGroup
691  */
692 public class View implements Drawable.Callback, KeyEvent.Callback,
693         AccessibilityEventSource {
694     private static final boolean DBG = false;
695 
696     /**
697      * The logging tag used by this class with android.util.Log.
698      */
699     protected static final String VIEW_LOG_TAG = "View";
700 
701     /**
702      * When set to true, apps will draw debugging information about their layouts.
703      *
704      * @hide
705      */
706     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
707 
708     /**
709      * When set to true, this view will save its attribute data.
710      *
711      * @hide
712      */
713     public static boolean mDebugViewAttributes = false;
714 
715     /**
716      * Used to mark a View that has no ID.
717      */
718     public static final int NO_ID = -1;
719 
720     /**
721      * Signals that compatibility booleans have been initialized according to
722      * target SDK versions.
723      */
724     private static boolean sCompatibilityDone = false;
725 
726     /**
727      * Use the old (broken) way of building MeasureSpecs.
728      */
729     private static boolean sUseBrokenMakeMeasureSpec = false;
730 
731     /**
732      * Ignore any optimizations using the measure cache.
733      */
734     private static boolean sIgnoreMeasureCache = false;
735 
736     /**
737      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
738      * calling setFlags.
739      */
740     private static final int NOT_FOCUSABLE = 0x00000000;
741 
742     /**
743      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
744      * setFlags.
745      */
746     private static final int FOCUSABLE = 0x00000001;
747 
748     /**
749      * Mask for use with setFlags indicating bits used for focus.
750      */
751     private static final int FOCUSABLE_MASK = 0x00000001;
752 
753     /**
754      * This view will adjust its padding to fit sytem windows (e.g. status bar)
755      */
756     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
757 
758     /** @hide */
759     @IntDef({VISIBLE, INVISIBLE, GONE})
760     @Retention(RetentionPolicy.SOURCE)
761     public @interface Visibility {}
762 
763     /**
764      * This view is visible.
765      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
766      * android:visibility}.
767      */
768     public static final int VISIBLE = 0x00000000;
769 
770     /**
771      * This view is invisible, but it still takes up space for layout purposes.
772      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
773      * android:visibility}.
774      */
775     public static final int INVISIBLE = 0x00000004;
776 
777     /**
778      * This view is invisible, and it doesn't take any space for layout
779      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
780      * android:visibility}.
781      */
782     public static final int GONE = 0x00000008;
783 
784     /**
785      * Mask for use with setFlags indicating bits used for visibility.
786      * {@hide}
787      */
788     static final int VISIBILITY_MASK = 0x0000000C;
789 
790     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
791 
792     /**
793      * This view is enabled. Interpretation varies by subclass.
794      * Use with ENABLED_MASK when calling setFlags.
795      * {@hide}
796      */
797     static final int ENABLED = 0x00000000;
798 
799     /**
800      * This view is disabled. Interpretation varies by subclass.
801      * Use with ENABLED_MASK when calling setFlags.
802      * {@hide}
803      */
804     static final int DISABLED = 0x00000020;
805 
806    /**
807     * Mask for use with setFlags indicating bits used for indicating whether
808     * this view is enabled
809     * {@hide}
810     */
811     static final int ENABLED_MASK = 0x00000020;
812 
813     /**
814      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
815      * called and further optimizations will be performed. It is okay to have
816      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
817      * {@hide}
818      */
819     static final int WILL_NOT_DRAW = 0x00000080;
820 
821     /**
822      * Mask for use with setFlags indicating bits used for indicating whether
823      * this view is will draw
824      * {@hide}
825      */
826     static final int DRAW_MASK = 0x00000080;
827 
828     /**
829      * <p>This view doesn't show scrollbars.</p>
830      * {@hide}
831      */
832     static final int SCROLLBARS_NONE = 0x00000000;
833 
834     /**
835      * <p>This view shows horizontal scrollbars.</p>
836      * {@hide}
837      */
838     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
839 
840     /**
841      * <p>This view shows vertical scrollbars.</p>
842      * {@hide}
843      */
844     static final int SCROLLBARS_VERTICAL = 0x00000200;
845 
846     /**
847      * <p>Mask for use with setFlags indicating bits used for indicating which
848      * scrollbars are enabled.</p>
849      * {@hide}
850      */
851     static final int SCROLLBARS_MASK = 0x00000300;
852 
853     /**
854      * Indicates that the view should filter touches when its window is obscured.
855      * Refer to the class comments for more information about this security feature.
856      * {@hide}
857      */
858     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
859 
860     /**
861      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
862      * that they are optional and should be skipped if the window has
863      * requested system UI flags that ignore those insets for layout.
864      */
865     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
866 
867     /**
868      * <p>This view doesn't show fading edges.</p>
869      * {@hide}
870      */
871     static final int FADING_EDGE_NONE = 0x00000000;
872 
873     /**
874      * <p>This view shows horizontal fading edges.</p>
875      * {@hide}
876      */
877     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
878 
879     /**
880      * <p>This view shows vertical fading edges.</p>
881      * {@hide}
882      */
883     static final int FADING_EDGE_VERTICAL = 0x00002000;
884 
885     /**
886      * <p>Mask for use with setFlags indicating bits used for indicating which
887      * fading edges are enabled.</p>
888      * {@hide}
889      */
890     static final int FADING_EDGE_MASK = 0x00003000;
891 
892     /**
893      * <p>Indicates this view can be clicked. When clickable, a View reacts
894      * to clicks by notifying the OnClickListener.<p>
895      * {@hide}
896      */
897     static final int CLICKABLE = 0x00004000;
898 
899     /**
900      * <p>Indicates this view is caching its drawing into a bitmap.</p>
901      * {@hide}
902      */
903     static final int DRAWING_CACHE_ENABLED = 0x00008000;
904 
905     /**
906      * <p>Indicates that no icicle should be saved for this view.<p>
907      * {@hide}
908      */
909     static final int SAVE_DISABLED = 0x000010000;
910 
911     /**
912      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
913      * property.</p>
914      * {@hide}
915      */
916     static final int SAVE_DISABLED_MASK = 0x000010000;
917 
918     /**
919      * <p>Indicates that no drawing cache should ever be created for this view.<p>
920      * {@hide}
921      */
922     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
923 
924     /**
925      * <p>Indicates this view can take / keep focus when int touch mode.</p>
926      * {@hide}
927      */
928     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
929 
930     /** @hide */
931     @Retention(RetentionPolicy.SOURCE)
932     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
933     public @interface DrawingCacheQuality {}
934 
935     /**
936      * <p>Enables low quality mode for the drawing cache.</p>
937      */
938     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
939 
940     /**
941      * <p>Enables high quality mode for the drawing cache.</p>
942      */
943     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
944 
945     /**
946      * <p>Enables automatic quality mode for the drawing cache.</p>
947      */
948     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
949 
950     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
951             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
952     };
953 
954     /**
955      * <p>Mask for use with setFlags indicating bits used for the cache
956      * quality property.</p>
957      * {@hide}
958      */
959     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
960 
961     /**
962      * <p>
963      * Indicates this view can be long clicked. When long clickable, a View
964      * reacts to long clicks by notifying the OnLongClickListener or showing a
965      * context menu.
966      * </p>
967      * {@hide}
968      */
969     static final int LONG_CLICKABLE = 0x00200000;
970 
971     /**
972      * <p>Indicates that this view gets its drawable states from its direct parent
973      * and ignores its original internal states.</p>
974      *
975      * @hide
976      */
977     static final int DUPLICATE_PARENT_STATE = 0x00400000;
978 
979     /** @hide */
980     @IntDef({
981         SCROLLBARS_INSIDE_OVERLAY,
982         SCROLLBARS_INSIDE_INSET,
983         SCROLLBARS_OUTSIDE_OVERLAY,
984         SCROLLBARS_OUTSIDE_INSET
985     })
986     @Retention(RetentionPolicy.SOURCE)
987     public @interface ScrollBarStyle {}
988 
989     /**
990      * The scrollbar style to display the scrollbars inside the content area,
991      * without increasing the padding. The scrollbars will be overlaid with
992      * translucency on the view's content.
993      */
994     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
995 
996     /**
997      * The scrollbar style to display the scrollbars inside the padded area,
998      * increasing the padding of the view. The scrollbars will not overlap the
999      * content area of the view.
1000      */
1001     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1002 
1003     /**
1004      * The scrollbar style to display the scrollbars at the edge of the view,
1005      * without increasing the padding. The scrollbars will be overlaid with
1006      * translucency.
1007      */
1008     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1009 
1010     /**
1011      * The scrollbar style to display the scrollbars at the edge of the view,
1012      * increasing the padding of the view. The scrollbars will only overlap the
1013      * background, if any.
1014      */
1015     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1016 
1017     /**
1018      * Mask to check if the scrollbar style is overlay or inset.
1019      * {@hide}
1020      */
1021     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1022 
1023     /**
1024      * Mask to check if the scrollbar style is inside or outside.
1025      * {@hide}
1026      */
1027     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1028 
1029     /**
1030      * Mask for scrollbar style.
1031      * {@hide}
1032      */
1033     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1034 
1035     /**
1036      * View flag indicating that the screen should remain on while the
1037      * window containing this view is visible to the user.  This effectively
1038      * takes care of automatically setting the WindowManager's
1039      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1040      */
1041     public static final int KEEP_SCREEN_ON = 0x04000000;
1042 
1043     /**
1044      * View flag indicating whether this view should have sound effects enabled
1045      * for events such as clicking and touching.
1046      */
1047     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1048 
1049     /**
1050      * View flag indicating whether this view should have haptic feedback
1051      * enabled for events such as long presses.
1052      */
1053     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1054 
1055     /**
1056      * <p>Indicates that the view hierarchy should stop saving state when
1057      * it reaches this view.  If state saving is initiated immediately at
1058      * the view, it will be allowed.
1059      * {@hide}
1060      */
1061     static final int PARENT_SAVE_DISABLED = 0x20000000;
1062 
1063     /**
1064      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1065      * {@hide}
1066      */
1067     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1068 
1069     /** @hide */
1070     @IntDef(flag = true,
1071             value = {
1072                 FOCUSABLES_ALL,
1073                 FOCUSABLES_TOUCH_MODE
1074             })
1075     @Retention(RetentionPolicy.SOURCE)
1076     public @interface FocusableMode {}
1077 
1078     /**
1079      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1080      * should add all focusable Views regardless if they are focusable in touch mode.
1081      */
1082     public static final int FOCUSABLES_ALL = 0x00000000;
1083 
1084     /**
1085      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1086      * should add only Views focusable in touch mode.
1087      */
1088     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1089 
1090     /** @hide */
1091     @IntDef({
1092             FOCUS_BACKWARD,
1093             FOCUS_FORWARD,
1094             FOCUS_LEFT,
1095             FOCUS_UP,
1096             FOCUS_RIGHT,
1097             FOCUS_DOWN
1098     })
1099     @Retention(RetentionPolicy.SOURCE)
1100     public @interface FocusDirection {}
1101 
1102     /** @hide */
1103     @IntDef({
1104             FOCUS_LEFT,
1105             FOCUS_UP,
1106             FOCUS_RIGHT,
1107             FOCUS_DOWN
1108     })
1109     @Retention(RetentionPolicy.SOURCE)
1110     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1111 
1112     /**
1113      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1114      * item.
1115      */
1116     public static final int FOCUS_BACKWARD = 0x00000001;
1117 
1118     /**
1119      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1120      * item.
1121      */
1122     public static final int FOCUS_FORWARD = 0x00000002;
1123 
1124     /**
1125      * Use with {@link #focusSearch(int)}. Move focus to the left.
1126      */
1127     public static final int FOCUS_LEFT = 0x00000011;
1128 
1129     /**
1130      * Use with {@link #focusSearch(int)}. Move focus up.
1131      */
1132     public static final int FOCUS_UP = 0x00000021;
1133 
1134     /**
1135      * Use with {@link #focusSearch(int)}. Move focus to the right.
1136      */
1137     public static final int FOCUS_RIGHT = 0x00000042;
1138 
1139     /**
1140      * Use with {@link #focusSearch(int)}. Move focus down.
1141      */
1142     public static final int FOCUS_DOWN = 0x00000082;
1143 
1144     /**
1145      * Bits of {@link #getMeasuredWidthAndState()} and
1146      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1147      */
1148     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1149 
1150     /**
1151      * Bits of {@link #getMeasuredWidthAndState()} and
1152      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1153      */
1154     public static final int MEASURED_STATE_MASK = 0xff000000;
1155 
1156     /**
1157      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1158      * for functions that combine both width and height into a single int,
1159      * such as {@link #getMeasuredState()} and the childState argument of
1160      * {@link #resolveSizeAndState(int, int, int)}.
1161      */
1162     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1163 
1164     /**
1165      * Bit of {@link #getMeasuredWidthAndState()} and
1166      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1167      * is smaller that the space the view would like to have.
1168      */
1169     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1170 
1171     /**
1172      * Base View state sets
1173      */
1174     // Singles
1175     /**
1176      * Indicates the view has no states set. States are used with
1177      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1178      * view depending on its state.
1179      *
1180      * @see android.graphics.drawable.Drawable
1181      * @see #getDrawableState()
1182      */
1183     protected static final int[] EMPTY_STATE_SET;
1184     /**
1185      * Indicates the view is enabled. States are used with
1186      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1187      * view depending on its state.
1188      *
1189      * @see android.graphics.drawable.Drawable
1190      * @see #getDrawableState()
1191      */
1192     protected static final int[] ENABLED_STATE_SET;
1193     /**
1194      * Indicates the view is focused. States are used with
1195      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1196      * view depending on its state.
1197      *
1198      * @see android.graphics.drawable.Drawable
1199      * @see #getDrawableState()
1200      */
1201     protected static final int[] FOCUSED_STATE_SET;
1202     /**
1203      * Indicates the view is selected. States are used with
1204      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1205      * view depending on its state.
1206      *
1207      * @see android.graphics.drawable.Drawable
1208      * @see #getDrawableState()
1209      */
1210     protected static final int[] SELECTED_STATE_SET;
1211     /**
1212      * Indicates the view is pressed. States are used with
1213      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1214      * view depending on its state.
1215      *
1216      * @see android.graphics.drawable.Drawable
1217      * @see #getDrawableState()
1218      */
1219     protected static final int[] PRESSED_STATE_SET;
1220     /**
1221      * Indicates the view's window has focus. States are used with
1222      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1223      * view depending on its state.
1224      *
1225      * @see android.graphics.drawable.Drawable
1226      * @see #getDrawableState()
1227      */
1228     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1229     // Doubles
1230     /**
1231      * Indicates the view is enabled and has the focus.
1232      *
1233      * @see #ENABLED_STATE_SET
1234      * @see #FOCUSED_STATE_SET
1235      */
1236     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1237     /**
1238      * Indicates the view is enabled and selected.
1239      *
1240      * @see #ENABLED_STATE_SET
1241      * @see #SELECTED_STATE_SET
1242      */
1243     protected static final int[] ENABLED_SELECTED_STATE_SET;
1244     /**
1245      * Indicates the view is enabled and that its window has focus.
1246      *
1247      * @see #ENABLED_STATE_SET
1248      * @see #WINDOW_FOCUSED_STATE_SET
1249      */
1250     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1251     /**
1252      * Indicates the view is focused and selected.
1253      *
1254      * @see #FOCUSED_STATE_SET
1255      * @see #SELECTED_STATE_SET
1256      */
1257     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1258     /**
1259      * Indicates the view has the focus and that its window has the focus.
1260      *
1261      * @see #FOCUSED_STATE_SET
1262      * @see #WINDOW_FOCUSED_STATE_SET
1263      */
1264     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1265     /**
1266      * Indicates the view is selected and that its window has the focus.
1267      *
1268      * @see #SELECTED_STATE_SET
1269      * @see #WINDOW_FOCUSED_STATE_SET
1270      */
1271     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1272     // Triples
1273     /**
1274      * Indicates the view is enabled, focused and selected.
1275      *
1276      * @see #ENABLED_STATE_SET
1277      * @see #FOCUSED_STATE_SET
1278      * @see #SELECTED_STATE_SET
1279      */
1280     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1281     /**
1282      * Indicates the view is enabled, focused and its window has the focus.
1283      *
1284      * @see #ENABLED_STATE_SET
1285      * @see #FOCUSED_STATE_SET
1286      * @see #WINDOW_FOCUSED_STATE_SET
1287      */
1288     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1289     /**
1290      * Indicates the view is enabled, selected and its window has the focus.
1291      *
1292      * @see #ENABLED_STATE_SET
1293      * @see #SELECTED_STATE_SET
1294      * @see #WINDOW_FOCUSED_STATE_SET
1295      */
1296     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1297     /**
1298      * Indicates the view is focused, selected and its window has the focus.
1299      *
1300      * @see #FOCUSED_STATE_SET
1301      * @see #SELECTED_STATE_SET
1302      * @see #WINDOW_FOCUSED_STATE_SET
1303      */
1304     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1305     /**
1306      * Indicates the view is enabled, focused, selected and its window
1307      * has the focus.
1308      *
1309      * @see #ENABLED_STATE_SET
1310      * @see #FOCUSED_STATE_SET
1311      * @see #SELECTED_STATE_SET
1312      * @see #WINDOW_FOCUSED_STATE_SET
1313      */
1314     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1315     /**
1316      * Indicates the view is pressed and its window has the focus.
1317      *
1318      * @see #PRESSED_STATE_SET
1319      * @see #WINDOW_FOCUSED_STATE_SET
1320      */
1321     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1322     /**
1323      * Indicates the view is pressed and selected.
1324      *
1325      * @see #PRESSED_STATE_SET
1326      * @see #SELECTED_STATE_SET
1327      */
1328     protected static final int[] PRESSED_SELECTED_STATE_SET;
1329     /**
1330      * Indicates the view is pressed, selected and its window has the focus.
1331      *
1332      * @see #PRESSED_STATE_SET
1333      * @see #SELECTED_STATE_SET
1334      * @see #WINDOW_FOCUSED_STATE_SET
1335      */
1336     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1337     /**
1338      * Indicates the view is pressed and focused.
1339      *
1340      * @see #PRESSED_STATE_SET
1341      * @see #FOCUSED_STATE_SET
1342      */
1343     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1344     /**
1345      * Indicates the view is pressed, focused and its window has the focus.
1346      *
1347      * @see #PRESSED_STATE_SET
1348      * @see #FOCUSED_STATE_SET
1349      * @see #WINDOW_FOCUSED_STATE_SET
1350      */
1351     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1352     /**
1353      * Indicates the view is pressed, focused and selected.
1354      *
1355      * @see #PRESSED_STATE_SET
1356      * @see #SELECTED_STATE_SET
1357      * @see #FOCUSED_STATE_SET
1358      */
1359     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1360     /**
1361      * Indicates the view is pressed, focused, selected and its window has the focus.
1362      *
1363      * @see #PRESSED_STATE_SET
1364      * @see #FOCUSED_STATE_SET
1365      * @see #SELECTED_STATE_SET
1366      * @see #WINDOW_FOCUSED_STATE_SET
1367      */
1368     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1369     /**
1370      * Indicates the view is pressed and enabled.
1371      *
1372      * @see #PRESSED_STATE_SET
1373      * @see #ENABLED_STATE_SET
1374      */
1375     protected static final int[] PRESSED_ENABLED_STATE_SET;
1376     /**
1377      * Indicates the view is pressed, enabled and its window has the focus.
1378      *
1379      * @see #PRESSED_STATE_SET
1380      * @see #ENABLED_STATE_SET
1381      * @see #WINDOW_FOCUSED_STATE_SET
1382      */
1383     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1384     /**
1385      * Indicates the view is pressed, enabled and selected.
1386      *
1387      * @see #PRESSED_STATE_SET
1388      * @see #ENABLED_STATE_SET
1389      * @see #SELECTED_STATE_SET
1390      */
1391     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1392     /**
1393      * Indicates the view is pressed, enabled, selected and its window has the
1394      * focus.
1395      *
1396      * @see #PRESSED_STATE_SET
1397      * @see #ENABLED_STATE_SET
1398      * @see #SELECTED_STATE_SET
1399      * @see #WINDOW_FOCUSED_STATE_SET
1400      */
1401     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1402     /**
1403      * Indicates the view is pressed, enabled and focused.
1404      *
1405      * @see #PRESSED_STATE_SET
1406      * @see #ENABLED_STATE_SET
1407      * @see #FOCUSED_STATE_SET
1408      */
1409     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1410     /**
1411      * Indicates the view is pressed, enabled, focused and its window has the
1412      * focus.
1413      *
1414      * @see #PRESSED_STATE_SET
1415      * @see #ENABLED_STATE_SET
1416      * @see #FOCUSED_STATE_SET
1417      * @see #WINDOW_FOCUSED_STATE_SET
1418      */
1419     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1420     /**
1421      * Indicates the view is pressed, enabled, focused and selected.
1422      *
1423      * @see #PRESSED_STATE_SET
1424      * @see #ENABLED_STATE_SET
1425      * @see #SELECTED_STATE_SET
1426      * @see #FOCUSED_STATE_SET
1427      */
1428     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1429     /**
1430      * Indicates the view is pressed, enabled, focused, selected and its window
1431      * has the focus.
1432      *
1433      * @see #PRESSED_STATE_SET
1434      * @see #ENABLED_STATE_SET
1435      * @see #SELECTED_STATE_SET
1436      * @see #FOCUSED_STATE_SET
1437      * @see #WINDOW_FOCUSED_STATE_SET
1438      */
1439     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1440 
1441     /**
1442      * The order here is very important to {@link #getDrawableState()}
1443      */
1444     private static final int[][] VIEW_STATE_SETS;
1445 
1446     static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1447     static final int VIEW_STATE_SELECTED = 1 << 1;
1448     static final int VIEW_STATE_FOCUSED = 1 << 2;
1449     static final int VIEW_STATE_ENABLED = 1 << 3;
1450     static final int VIEW_STATE_PRESSED = 1 << 4;
1451     static final int VIEW_STATE_ACTIVATED = 1 << 5;
1452     static final int VIEW_STATE_ACCELERATED = 1 << 6;
1453     static final int VIEW_STATE_HOVERED = 1 << 7;
1454     static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1455     static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1456 
1457     static final int[] VIEW_STATE_IDS = new int[] {
1458         R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1459         R.attr.state_selected,          VIEW_STATE_SELECTED,
1460         R.attr.state_focused,           VIEW_STATE_FOCUSED,
1461         R.attr.state_enabled,           VIEW_STATE_ENABLED,
1462         R.attr.state_pressed,           VIEW_STATE_PRESSED,
1463         R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1464         R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1465         R.attr.state_hovered,           VIEW_STATE_HOVERED,
1466         R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1467         R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED
1468     };
1469 
1470     static {
1471         if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1472             throw new IllegalStateException(
1473                     "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1474         }
1475         int[] orderedIds = new int[VIEW_STATE_IDS.length];
1476         for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1477             int viewState = R.styleable.ViewDrawableStates[i];
1478             for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1479                 if (VIEW_STATE_IDS[j] == viewState) {
1480                     orderedIds[i * 2] = viewState;
1481                     orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1482                 }
1483             }
1484         }
1485         final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1486         VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1487         for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1488             int numBits = Integer.bitCount(i);
1489             int[] set = new int[numBits];
1490             int pos = 0;
1491             for (int j = 0; j < orderedIds.length; j += 2) {
1492                 if ((i & orderedIds[j+1]) != 0) {
1493                     set[pos++] = orderedIds[j];
1494                 }
1495             }
1496             VIEW_STATE_SETS[i] = set;
1497         }
1498 
1499         EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1500         WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1501         SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1502         SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1503                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1504         FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1505         FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1506                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1507         FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1508                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1509         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1510                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1511                 | VIEW_STATE_FOCUSED];
1512         ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1513         ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1514                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1515         ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1516                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1517         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1518                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1519                 | VIEW_STATE_ENABLED];
1520         ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1521                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1522         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1523                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1524                 | VIEW_STATE_ENABLED];
1525         ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1526                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1527                 | VIEW_STATE_ENABLED];
1528         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1529                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1530                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1531 
1532         PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1533         PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1534                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1535         PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1536                 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1537         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1538                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1539                 | VIEW_STATE_PRESSED];
1540         PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1541                 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1542         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1543                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1544                 | VIEW_STATE_PRESSED];
1545         PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1546                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1547                 | VIEW_STATE_PRESSED];
1548         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1549                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1550                 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1551         PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1552                 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1553         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1554                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1555                 | VIEW_STATE_PRESSED];
1556         PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1557                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1558                 | VIEW_STATE_PRESSED];
1559         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1560                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1561                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1562         PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1563                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1564                 | VIEW_STATE_PRESSED];
1565         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1566                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1567                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1568         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1569                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1570                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1571         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1572                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1573                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1574                 | VIEW_STATE_PRESSED];
1575     }
1576 
1577     /**
1578      * Accessibility event types that are dispatched for text population.
1579      */
1580     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1581             AccessibilityEvent.TYPE_VIEW_CLICKED
1582             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1583             | AccessibilityEvent.TYPE_VIEW_SELECTED
1584             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1585             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1586             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1587             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1588             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1589             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1590             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1591             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1592 
1593     /**
1594      * Temporary Rect currently for use in setBackground().  This will probably
1595      * be extended in the future to hold our own class with more than just
1596      * a Rect. :)
1597      */
1598     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1599 
1600     /**
1601      * Map used to store views' tags.
1602      */
1603     private SparseArray<Object> mKeyedTags;
1604 
1605     /**
1606      * The next available accessibility id.
1607      */
1608     private static int sNextAccessibilityViewId;
1609 
1610     /**
1611      * The animation currently associated with this view.
1612      * @hide
1613      */
1614     protected Animation mCurrentAnimation = null;
1615 
1616     /**
1617      * Width as measured during measure pass.
1618      * {@hide}
1619      */
1620     @ViewDebug.ExportedProperty(category = "measurement")
1621     int mMeasuredWidth;
1622 
1623     /**
1624      * Height as measured during measure pass.
1625      * {@hide}
1626      */
1627     @ViewDebug.ExportedProperty(category = "measurement")
1628     int mMeasuredHeight;
1629 
1630     /**
1631      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1632      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1633      * its display list. This flag, used only when hw accelerated, allows us to clear the
1634      * flag while retaining this information until it's needed (at getDisplayList() time and
1635      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1636      *
1637      * {@hide}
1638      */
1639     boolean mRecreateDisplayList = false;
1640 
1641     /**
1642      * The view's identifier.
1643      * {@hide}
1644      *
1645      * @see #setId(int)
1646      * @see #getId()
1647      */
1648     @ViewDebug.ExportedProperty(resolveId = true)
1649     int mID = NO_ID;
1650 
1651     /**
1652      * The stable ID of this view for accessibility purposes.
1653      */
1654     int mAccessibilityViewId = NO_ID;
1655 
1656     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1657 
1658     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1659 
1660     /**
1661      * The view's tag.
1662      * {@hide}
1663      *
1664      * @see #setTag(Object)
1665      * @see #getTag()
1666      */
1667     protected Object mTag = null;
1668 
1669     // for mPrivateFlags:
1670     /** {@hide} */
1671     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1672     /** {@hide} */
1673     static final int PFLAG_FOCUSED                     = 0x00000002;
1674     /** {@hide} */
1675     static final int PFLAG_SELECTED                    = 0x00000004;
1676     /** {@hide} */
1677     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1678     /** {@hide} */
1679     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1680     /** {@hide} */
1681     static final int PFLAG_DRAWN                       = 0x00000020;
1682     /**
1683      * When this flag is set, this view is running an animation on behalf of its
1684      * children and should therefore not cancel invalidate requests, even if they
1685      * lie outside of this view's bounds.
1686      *
1687      * {@hide}
1688      */
1689     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1690     /** {@hide} */
1691     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1692     /** {@hide} */
1693     static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1694     /** {@hide} */
1695     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1696     /** {@hide} */
1697     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1698     /** {@hide} */
1699     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1700     /** {@hide} */
1701     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1702     /** {@hide} */
1703     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1704 
1705     private static final int PFLAG_PRESSED             = 0x00004000;
1706 
1707     /** {@hide} */
1708     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1709     /**
1710      * Flag used to indicate that this view should be drawn once more (and only once
1711      * more) after its animation has completed.
1712      * {@hide}
1713      */
1714     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1715 
1716     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1717 
1718     /**
1719      * Indicates that the View returned true when onSetAlpha() was called and that
1720      * the alpha must be restored.
1721      * {@hide}
1722      */
1723     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1724 
1725     /**
1726      * Set by {@link #setScrollContainer(boolean)}.
1727      */
1728     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1729 
1730     /**
1731      * Set by {@link #setScrollContainer(boolean)}.
1732      */
1733     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1734 
1735     /**
1736      * View flag indicating whether this view was invalidated (fully or partially.)
1737      *
1738      * @hide
1739      */
1740     static final int PFLAG_DIRTY                       = 0x00200000;
1741 
1742     /**
1743      * View flag indicating whether this view was invalidated by an opaque
1744      * invalidate request.
1745      *
1746      * @hide
1747      */
1748     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1749 
1750     /**
1751      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1752      *
1753      * @hide
1754      */
1755     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1756 
1757     /**
1758      * Indicates whether the background is opaque.
1759      *
1760      * @hide
1761      */
1762     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1763 
1764     /**
1765      * Indicates whether the scrollbars are opaque.
1766      *
1767      * @hide
1768      */
1769     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1770 
1771     /**
1772      * Indicates whether the view is opaque.
1773      *
1774      * @hide
1775      */
1776     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1777 
1778     /**
1779      * Indicates a prepressed state;
1780      * the short time between ACTION_DOWN and recognizing
1781      * a 'real' press. Prepressed is used to recognize quick taps
1782      * even when they are shorter than ViewConfiguration.getTapTimeout().
1783      *
1784      * @hide
1785      */
1786     private static final int PFLAG_PREPRESSED          = 0x02000000;
1787 
1788     /**
1789      * Indicates whether the view is temporarily detached.
1790      *
1791      * @hide
1792      */
1793     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1794 
1795     /**
1796      * Indicates that we should awaken scroll bars once attached
1797      *
1798      * @hide
1799      */
1800     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1801 
1802     /**
1803      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1804      * @hide
1805      */
1806     private static final int PFLAG_HOVERED             = 0x10000000;
1807 
1808     /**
1809      * no longer needed, should be reused
1810      */
1811     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1812 
1813     /** {@hide} */
1814     static final int PFLAG_ACTIVATED                   = 0x40000000;
1815 
1816     /**
1817      * Indicates that this view was specifically invalidated, not just dirtied because some
1818      * child view was invalidated. The flag is used to determine when we need to recreate
1819      * a view's display list (as opposed to just returning a reference to its existing
1820      * display list).
1821      *
1822      * @hide
1823      */
1824     static final int PFLAG_INVALIDATED                 = 0x80000000;
1825 
1826     /**
1827      * Masks for mPrivateFlags2, as generated by dumpFlags():
1828      *
1829      * |-------|-------|-------|-------|
1830      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1831      *                                1  PFLAG2_DRAG_HOVERED
1832      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1833      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1834      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1835      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1836      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1837      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1838      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1839      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1840      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1841      *                         111       PFLAG2_TEXT_DIRECTION_MASK
1842      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1843      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1844      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1845      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1846      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1847      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1848      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1849      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1850      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1851      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1852      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1853      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1854      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1855      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1856      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1857      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1858      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1859      *     1                             PFLAG2_VIEW_QUICK_REJECTED
1860      *    1                              PFLAG2_PADDING_RESOLVED
1861      *   1                               PFLAG2_DRAWABLE_RESOLVED
1862      *  1                                PFLAG2_HAS_TRANSIENT_STATE
1863      * |-------|-------|-------|-------|
1864      */
1865 
1866     /**
1867      * Indicates that this view has reported that it can accept the current drag's content.
1868      * Cleared when the drag operation concludes.
1869      * @hide
1870      */
1871     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1872 
1873     /**
1874      * Indicates that this view is currently directly under the drag location in a
1875      * drag-and-drop operation involving content that it can accept.  Cleared when
1876      * the drag exits the view, or when the drag operation concludes.
1877      * @hide
1878      */
1879     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1880 
1881     /** @hide */
1882     @IntDef({
1883         LAYOUT_DIRECTION_LTR,
1884         LAYOUT_DIRECTION_RTL,
1885         LAYOUT_DIRECTION_INHERIT,
1886         LAYOUT_DIRECTION_LOCALE
1887     })
1888     @Retention(RetentionPolicy.SOURCE)
1889     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1890     public @interface LayoutDir {}
1891 
1892     /** @hide */
1893     @IntDef({
1894         LAYOUT_DIRECTION_LTR,
1895         LAYOUT_DIRECTION_RTL
1896     })
1897     @Retention(RetentionPolicy.SOURCE)
1898     public @interface ResolvedLayoutDir {}
1899 
1900     /**
1901      * Horizontal layout direction of this view is from Left to Right.
1902      * Use with {@link #setLayoutDirection}.
1903      */
1904     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1905 
1906     /**
1907      * Horizontal layout direction of this view is from Right to Left.
1908      * Use with {@link #setLayoutDirection}.
1909      */
1910     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1911 
1912     /**
1913      * Horizontal layout direction of this view is inherited from its parent.
1914      * Use with {@link #setLayoutDirection}.
1915      */
1916     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1917 
1918     /**
1919      * Horizontal layout direction of this view is from deduced from the default language
1920      * script for the locale. Use with {@link #setLayoutDirection}.
1921      */
1922     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1923 
1924     /**
1925      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1926      * @hide
1927      */
1928     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1929 
1930     /**
1931      * Mask for use with private flags indicating bits used for horizontal layout direction.
1932      * @hide
1933      */
1934     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1935 
1936     /**
1937      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1938      * right-to-left direction.
1939      * @hide
1940      */
1941     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1942 
1943     /**
1944      * Indicates whether the view horizontal layout direction has been resolved.
1945      * @hide
1946      */
1947     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1948 
1949     /**
1950      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1951      * @hide
1952      */
1953     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1954             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1955 
1956     /*
1957      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1958      * flag value.
1959      * @hide
1960      */
1961     private static final int[] LAYOUT_DIRECTION_FLAGS = {
1962             LAYOUT_DIRECTION_LTR,
1963             LAYOUT_DIRECTION_RTL,
1964             LAYOUT_DIRECTION_INHERIT,
1965             LAYOUT_DIRECTION_LOCALE
1966     };
1967 
1968     /**
1969      * Default horizontal layout direction.
1970      */
1971     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1972 
1973     /**
1974      * Default horizontal layout direction.
1975      * @hide
1976      */
1977     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1978 
1979     /**
1980      * Text direction is inherited thru {@link ViewGroup}
1981      */
1982     public static final int TEXT_DIRECTION_INHERIT = 0;
1983 
1984     /**
1985      * Text direction is using "first strong algorithm". The first strong directional character
1986      * determines the paragraph direction. If there is no strong directional character, the
1987      * paragraph direction is the view's resolved layout direction.
1988      */
1989     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1990 
1991     /**
1992      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1993      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1994      * If there are neither, the paragraph direction is the view's resolved layout direction.
1995      */
1996     public static final int TEXT_DIRECTION_ANY_RTL = 2;
1997 
1998     /**
1999      * Text direction is forced to LTR.
2000      */
2001     public static final int TEXT_DIRECTION_LTR = 3;
2002 
2003     /**
2004      * Text direction is forced to RTL.
2005      */
2006     public static final int TEXT_DIRECTION_RTL = 4;
2007 
2008     /**
2009      * Text direction is coming from the system Locale.
2010      */
2011     public static final int TEXT_DIRECTION_LOCALE = 5;
2012 
2013     /**
2014      * Default text direction is inherited
2015      */
2016     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2017 
2018     /**
2019      * Default resolved text direction
2020      * @hide
2021      */
2022     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2023 
2024     /**
2025      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2026      * @hide
2027      */
2028     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2029 
2030     /**
2031      * Mask for use with private flags indicating bits used for text direction.
2032      * @hide
2033      */
2034     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2035             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2036 
2037     /**
2038      * Array of text direction flags for mapping attribute "textDirection" to correct
2039      * flag value.
2040      * @hide
2041      */
2042     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2043             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2044             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2045             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2046             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2047             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2048             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2049     };
2050 
2051     /**
2052      * Indicates whether the view text direction has been resolved.
2053      * @hide
2054      */
2055     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2056             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2057 
2058     /**
2059      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2060      * @hide
2061      */
2062     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2063 
2064     /**
2065      * Mask for use with private flags indicating bits used for resolved text direction.
2066      * @hide
2067      */
2068     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2069             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2070 
2071     /**
2072      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2073      * @hide
2074      */
2075     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2076             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2077 
2078     /** @hide */
2079     @IntDef({
2080         TEXT_ALIGNMENT_INHERIT,
2081         TEXT_ALIGNMENT_GRAVITY,
2082         TEXT_ALIGNMENT_CENTER,
2083         TEXT_ALIGNMENT_TEXT_START,
2084         TEXT_ALIGNMENT_TEXT_END,
2085         TEXT_ALIGNMENT_VIEW_START,
2086         TEXT_ALIGNMENT_VIEW_END
2087     })
2088     @Retention(RetentionPolicy.SOURCE)
2089     public @interface TextAlignment {}
2090 
2091     /**
2092      * Default text alignment. The text alignment of this View is inherited from its parent.
2093      * Use with {@link #setTextAlignment(int)}
2094      */
2095     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2096 
2097     /**
2098      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2099      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2100      *
2101      * Use with {@link #setTextAlignment(int)}
2102      */
2103     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2104 
2105     /**
2106      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2107      *
2108      * Use with {@link #setTextAlignment(int)}
2109      */
2110     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2111 
2112     /**
2113      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2114      *
2115      * Use with {@link #setTextAlignment(int)}
2116      */
2117     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2118 
2119     /**
2120      * Center the paragraph, e.g. ALIGN_CENTER.
2121      *
2122      * Use with {@link #setTextAlignment(int)}
2123      */
2124     public static final int TEXT_ALIGNMENT_CENTER = 4;
2125 
2126     /**
2127      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2128      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2129      *
2130      * Use with {@link #setTextAlignment(int)}
2131      */
2132     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2133 
2134     /**
2135      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2136      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2137      *
2138      * Use with {@link #setTextAlignment(int)}
2139      */
2140     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2141 
2142     /**
2143      * Default text alignment is inherited
2144      */
2145     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2146 
2147     /**
2148      * Default resolved text alignment
2149      * @hide
2150      */
2151     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2152 
2153     /**
2154       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2155       * @hide
2156       */
2157     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2158 
2159     /**
2160       * Mask for use with private flags indicating bits used for text alignment.
2161       * @hide
2162       */
2163     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2164 
2165     /**
2166      * Array of text direction flags for mapping attribute "textAlignment" to correct
2167      * flag value.
2168      * @hide
2169      */
2170     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2171             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2172             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2173             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2174             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2175             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2176             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2177             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2178     };
2179 
2180     /**
2181      * Indicates whether the view text alignment has been resolved.
2182      * @hide
2183      */
2184     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2185 
2186     /**
2187      * Bit shift to get the resolved text alignment.
2188      * @hide
2189      */
2190     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2191 
2192     /**
2193      * Mask for use with private flags indicating bits used for text alignment.
2194      * @hide
2195      */
2196     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2197             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2198 
2199     /**
2200      * Indicates whether if the view text alignment has been resolved to gravity
2201      */
2202     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2203             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2204 
2205     // Accessiblity constants for mPrivateFlags2
2206 
2207     /**
2208      * Shift for the bits in {@link #mPrivateFlags2} related to the
2209      * "importantForAccessibility" attribute.
2210      */
2211     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2212 
2213     /**
2214      * Automatically determine whether a view is important for accessibility.
2215      */
2216     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2217 
2218     /**
2219      * The view is important for accessibility.
2220      */
2221     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2222 
2223     /**
2224      * The view is not important for accessibility.
2225      */
2226     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2227 
2228     /**
2229      * The view is not important for accessibility, nor are any of its
2230      * descendant views.
2231      */
2232     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2233 
2234     /**
2235      * The default whether the view is important for accessibility.
2236      */
2237     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2238 
2239     /**
2240      * Mask for obtainig the bits which specify how to determine
2241      * whether a view is important for accessibility.
2242      */
2243     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2244         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2245         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2246         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2247 
2248     /**
2249      * Shift for the bits in {@link #mPrivateFlags2} related to the
2250      * "accessibilityLiveRegion" attribute.
2251      */
2252     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2253 
2254     /**
2255      * Live region mode specifying that accessibility services should not
2256      * automatically announce changes to this view. This is the default live
2257      * region mode for most views.
2258      * <p>
2259      * Use with {@link #setAccessibilityLiveRegion(int)}.
2260      */
2261     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2262 
2263     /**
2264      * Live region mode specifying that accessibility services should announce
2265      * changes to this view.
2266      * <p>
2267      * Use with {@link #setAccessibilityLiveRegion(int)}.
2268      */
2269     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2270 
2271     /**
2272      * Live region mode specifying that accessibility services should interrupt
2273      * ongoing speech to immediately announce changes to this view.
2274      * <p>
2275      * Use with {@link #setAccessibilityLiveRegion(int)}.
2276      */
2277     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2278 
2279     /**
2280      * The default whether the view is important for accessibility.
2281      */
2282     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2283 
2284     /**
2285      * Mask for obtaining the bits which specify a view's accessibility live
2286      * region mode.
2287      */
2288     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2289             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2290             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2291 
2292     /**
2293      * Flag indicating whether a view has accessibility focus.
2294      */
2295     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2296 
2297     /**
2298      * Flag whether the accessibility state of the subtree rooted at this view changed.
2299      */
2300     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2301 
2302     /**
2303      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2304      * is used to check whether later changes to the view's transform should invalidate the
2305      * view to force the quickReject test to run again.
2306      */
2307     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2308 
2309     /**
2310      * Flag indicating that start/end padding has been resolved into left/right padding
2311      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2312      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2313      * during measurement. In some special cases this is required such as when an adapter-based
2314      * view measures prospective children without attaching them to a window.
2315      */
2316     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2317 
2318     /**
2319      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2320      */
2321     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2322 
2323     /**
2324      * Indicates that the view is tracking some sort of transient state
2325      * that the app should not need to be aware of, but that the framework
2326      * should take special care to preserve.
2327      */
2328     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2329 
2330     /**
2331      * Group of bits indicating that RTL properties resolution is done.
2332      */
2333     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2334             PFLAG2_TEXT_DIRECTION_RESOLVED |
2335             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2336             PFLAG2_PADDING_RESOLVED |
2337             PFLAG2_DRAWABLE_RESOLVED;
2338 
2339     // There are a couple of flags left in mPrivateFlags2
2340 
2341     /* End of masks for mPrivateFlags2 */
2342 
2343     /**
2344      * Masks for mPrivateFlags3, as generated by dumpFlags():
2345      *
2346      * |-------|-------|-------|-------|
2347      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2348      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2349      *                               1   PFLAG3_IS_LAID_OUT
2350      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2351      *                             1     PFLAG3_CALLED_SUPER
2352      * |-------|-------|-------|-------|
2353      */
2354 
2355     /**
2356      * Flag indicating that view has a transform animation set on it. This is used to track whether
2357      * an animation is cleared between successive frames, in order to tell the associated
2358      * DisplayList to clear its animation matrix.
2359      */
2360     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2361 
2362     /**
2363      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2364      * animation is cleared between successive frames, in order to tell the associated
2365      * DisplayList to restore its alpha value.
2366      */
2367     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2368 
2369     /**
2370      * Flag indicating that the view has been through at least one layout since it
2371      * was last attached to a window.
2372      */
2373     static final int PFLAG3_IS_LAID_OUT = 0x4;
2374 
2375     /**
2376      * Flag indicating that a call to measure() was skipped and should be done
2377      * instead when layout() is invoked.
2378      */
2379     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2380 
2381     /**
2382      * Flag indicating that an overridden method correctly called down to
2383      * the superclass implementation as required by the API spec.
2384      */
2385     static final int PFLAG3_CALLED_SUPER = 0x10;
2386 
2387     /**
2388      * Flag indicating that we're in the process of applying window insets.
2389      */
2390     static final int PFLAG3_APPLYING_INSETS = 0x20;
2391 
2392     /**
2393      * Flag indicating that we're in the process of fitting system windows using the old method.
2394      */
2395     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2396 
2397     /**
2398      * Flag indicating that nested scrolling is enabled for this view.
2399      * The view will optionally cooperate with views up its parent chain to allow for
2400      * integrated nested scrolling along the same axis.
2401      */
2402     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2403 
2404     /* End of masks for mPrivateFlags3 */
2405 
2406     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2407 
2408     /**
2409      * Always allow a user to over-scroll this view, provided it is a
2410      * view that can scroll.
2411      *
2412      * @see #getOverScrollMode()
2413      * @see #setOverScrollMode(int)
2414      */
2415     public static final int OVER_SCROLL_ALWAYS = 0;
2416 
2417     /**
2418      * Allow a user to over-scroll this view only if the content is large
2419      * enough to meaningfully scroll, provided it is a view that can scroll.
2420      *
2421      * @see #getOverScrollMode()
2422      * @see #setOverScrollMode(int)
2423      */
2424     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2425 
2426     /**
2427      * Never allow a user to over-scroll this view.
2428      *
2429      * @see #getOverScrollMode()
2430      * @see #setOverScrollMode(int)
2431      */
2432     public static final int OVER_SCROLL_NEVER = 2;
2433 
2434     /**
2435      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2436      * requested the system UI (status bar) to be visible (the default).
2437      *
2438      * @see #setSystemUiVisibility(int)
2439      */
2440     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2441 
2442     /**
2443      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2444      * system UI to enter an unobtrusive "low profile" mode.
2445      *
2446      * <p>This is for use in games, book readers, video players, or any other
2447      * "immersive" application where the usual system chrome is deemed too distracting.
2448      *
2449      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2450      *
2451      * @see #setSystemUiVisibility(int)
2452      */
2453     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2454 
2455     /**
2456      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2457      * system navigation be temporarily hidden.
2458      *
2459      * <p>This is an even less obtrusive state than that called for by
2460      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2461      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2462      * those to disappear. This is useful (in conjunction with the
2463      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2464      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2465      * window flags) for displaying content using every last pixel on the display.
2466      *
2467      * <p>There is a limitation: because navigation controls are so important, the least user
2468      * interaction will cause them to reappear immediately.  When this happens, both
2469      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2470      * so that both elements reappear at the same time.
2471      *
2472      * @see #setSystemUiVisibility(int)
2473      */
2474     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2475 
2476     /**
2477      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2478      * into the normal fullscreen mode so that its content can take over the screen
2479      * while still allowing the user to interact with the application.
2480      *
2481      * <p>This has the same visual effect as
2482      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2483      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2484      * meaning that non-critical screen decorations (such as the status bar) will be
2485      * hidden while the user is in the View's window, focusing the experience on
2486      * that content.  Unlike the window flag, if you are using ActionBar in
2487      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2488      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2489      * hide the action bar.
2490      *
2491      * <p>This approach to going fullscreen is best used over the window flag when
2492      * it is a transient state -- that is, the application does this at certain
2493      * points in its user interaction where it wants to allow the user to focus
2494      * on content, but not as a continuous state.  For situations where the application
2495      * would like to simply stay full screen the entire time (such as a game that
2496      * wants to take over the screen), the
2497      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2498      * is usually a better approach.  The state set here will be removed by the system
2499      * in various situations (such as the user moving to another application) like
2500      * the other system UI states.
2501      *
2502      * <p>When using this flag, the application should provide some easy facility
2503      * for the user to go out of it.  A common example would be in an e-book
2504      * reader, where tapping on the screen brings back whatever screen and UI
2505      * decorations that had been hidden while the user was immersed in reading
2506      * the book.
2507      *
2508      * @see #setSystemUiVisibility(int)
2509      */
2510     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2511 
2512     /**
2513      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2514      * flags, we would like a stable view of the content insets given to
2515      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2516      * will always represent the worst case that the application can expect
2517      * as a continuous state.  In the stock Android UI this is the space for
2518      * the system bar, nav bar, and status bar, but not more transient elements
2519      * such as an input method.
2520      *
2521      * The stable layout your UI sees is based on the system UI modes you can
2522      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2523      * then you will get a stable layout for changes of the
2524      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2525      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2526      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2527      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2528      * with a stable layout.  (Note that you should avoid using
2529      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2530      *
2531      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2532      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2533      * then a hidden status bar will be considered a "stable" state for purposes
2534      * here.  This allows your UI to continually hide the status bar, while still
2535      * using the system UI flags to hide the action bar while still retaining
2536      * a stable layout.  Note that changing the window fullscreen flag will never
2537      * provide a stable layout for a clean transition.
2538      *
2539      * <p>If you are using ActionBar in
2540      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2541      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2542      * insets it adds to those given to the application.
2543      */
2544     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2545 
2546     /**
2547      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2548      * to be layed out as if it has requested
2549      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2550      * allows it to avoid artifacts when switching in and out of that mode, at
2551      * the expense that some of its user interface may be covered by screen
2552      * decorations when they are shown.  You can perform layout of your inner
2553      * UI elements to account for the navigation system UI through the
2554      * {@link #fitSystemWindows(Rect)} method.
2555      */
2556     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2557 
2558     /**
2559      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2560      * to be layed out as if it has requested
2561      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2562      * allows it to avoid artifacts when switching in and out of that mode, at
2563      * the expense that some of its user interface may be covered by screen
2564      * decorations when they are shown.  You can perform layout of your inner
2565      * UI elements to account for non-fullscreen system UI through the
2566      * {@link #fitSystemWindows(Rect)} method.
2567      */
2568     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2569 
2570     /**
2571      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2572      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2573      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2574      * user interaction.
2575      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2576      * has an effect when used in combination with that flag.</p>
2577      */
2578     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2579 
2580     /**
2581      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2582      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2583      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2584      * experience while also hiding the system bars.  If this flag is not set,
2585      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2586      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2587      * if the user swipes from the top of the screen.
2588      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2589      * system gestures, such as swiping from the top of the screen.  These transient system bars
2590      * will overlay app’s content, may have some degree of transparency, and will automatically
2591      * hide after a short timeout.
2592      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2593      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2594      * with one or both of those flags.</p>
2595      */
2596     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2597 
2598     /**
2599      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2600      */
2601     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2602 
2603     /**
2604      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2605      */
2606     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2607 
2608     /**
2609      * @hide
2610      *
2611      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2612      * out of the public fields to keep the undefined bits out of the developer's way.
2613      *
2614      * Flag to make the status bar not expandable.  Unless you also
2615      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2616      */
2617     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2618 
2619     /**
2620      * @hide
2621      *
2622      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2623      * out of the public fields to keep the undefined bits out of the developer's way.
2624      *
2625      * Flag to hide notification icons and scrolling ticker text.
2626      */
2627     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2628 
2629     /**
2630      * @hide
2631      *
2632      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2633      * out of the public fields to keep the undefined bits out of the developer's way.
2634      *
2635      * Flag to disable incoming notification alerts.  This will not block
2636      * icons, but it will block sound, vibrating and other visual or aural notifications.
2637      */
2638     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2639 
2640     /**
2641      * @hide
2642      *
2643      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2644      * out of the public fields to keep the undefined bits out of the developer's way.
2645      *
2646      * Flag to hide only the scrolling ticker.  Note that
2647      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2648      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2649      */
2650     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2651 
2652     /**
2653      * @hide
2654      *
2655      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2656      * out of the public fields to keep the undefined bits out of the developer's way.
2657      *
2658      * Flag to hide the center system info area.
2659      */
2660     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2661 
2662     /**
2663      * @hide
2664      *
2665      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2666      * out of the public fields to keep the undefined bits out of the developer's way.
2667      *
2668      * Flag to hide only the home button.  Don't use this
2669      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2670      */
2671     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2672 
2673     /**
2674      * @hide
2675      *
2676      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2677      * out of the public fields to keep the undefined bits out of the developer's way.
2678      *
2679      * Flag to hide only the back button. Don't use this
2680      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2681      */
2682     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2683 
2684     /**
2685      * @hide
2686      *
2687      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2688      * out of the public fields to keep the undefined bits out of the developer's way.
2689      *
2690      * Flag to hide only the clock.  You might use this if your activity has
2691      * its own clock making the status bar's clock redundant.
2692      */
2693     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2694 
2695     /**
2696      * @hide
2697      *
2698      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2699      * out of the public fields to keep the undefined bits out of the developer's way.
2700      *
2701      * Flag to hide only the recent apps button. Don't use this
2702      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2703      */
2704     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2705 
2706     /**
2707      * @hide
2708      *
2709      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2710      * out of the public fields to keep the undefined bits out of the developer's way.
2711      *
2712      * Flag to disable the global search gesture. Don't use this
2713      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2714      */
2715     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2716 
2717     /**
2718      * @hide
2719      *
2720      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2721      * out of the public fields to keep the undefined bits out of the developer's way.
2722      *
2723      * Flag to specify that the status bar is displayed in transient mode.
2724      */
2725     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2726 
2727     /**
2728      * @hide
2729      *
2730      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2731      * out of the public fields to keep the undefined bits out of the developer's way.
2732      *
2733      * Flag to specify that the navigation bar is displayed in transient mode.
2734      */
2735     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2736 
2737     /**
2738      * @hide
2739      *
2740      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2741      * out of the public fields to keep the undefined bits out of the developer's way.
2742      *
2743      * Flag to specify that the hidden status bar would like to be shown.
2744      */
2745     public static final int STATUS_BAR_UNHIDE = 0x10000000;
2746 
2747     /**
2748      * @hide
2749      *
2750      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2751      * out of the public fields to keep the undefined bits out of the developer's way.
2752      *
2753      * Flag to specify that the hidden navigation bar would like to be shown.
2754      */
2755     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2756 
2757     /**
2758      * @hide
2759      *
2760      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2761      * out of the public fields to keep the undefined bits out of the developer's way.
2762      *
2763      * Flag to specify that the status bar is displayed in translucent mode.
2764      */
2765     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2766 
2767     /**
2768      * @hide
2769      *
2770      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2771      * out of the public fields to keep the undefined bits out of the developer's way.
2772      *
2773      * Flag to specify that the navigation bar is displayed in translucent mode.
2774      */
2775     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2776 
2777     /**
2778      * @hide
2779      *
2780      * Whether Recents is visible or not.
2781      */
2782     public static final int RECENT_APPS_VISIBLE = 0x00004000;
2783 
2784     /**
2785      * @hide
2786      *
2787      * Makes system ui transparent.
2788      */
2789     public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2790 
2791     /**
2792      * @hide
2793      */
2794     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2795 
2796     /**
2797      * These are the system UI flags that can be cleared by events outside
2798      * of an application.  Currently this is just the ability to tap on the
2799      * screen while hiding the navigation bar to have it return.
2800      * @hide
2801      */
2802     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2803             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2804             | SYSTEM_UI_FLAG_FULLSCREEN;
2805 
2806     /**
2807      * Flags that can impact the layout in relation to system UI.
2808      */
2809     public static final int SYSTEM_UI_LAYOUT_FLAGS =
2810             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2811             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2812 
2813     /** @hide */
2814     @IntDef(flag = true,
2815             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2816     @Retention(RetentionPolicy.SOURCE)
2817     public @interface FindViewFlags {}
2818 
2819     /**
2820      * Find views that render the specified text.
2821      *
2822      * @see #findViewsWithText(ArrayList, CharSequence, int)
2823      */
2824     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2825 
2826     /**
2827      * Find find views that contain the specified content description.
2828      *
2829      * @see #findViewsWithText(ArrayList, CharSequence, int)
2830      */
2831     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2832 
2833     /**
2834      * Find views that contain {@link AccessibilityNodeProvider}. Such
2835      * a View is a root of virtual view hierarchy and may contain the searched
2836      * text. If this flag is set Views with providers are automatically
2837      * added and it is a responsibility of the client to call the APIs of
2838      * the provider to determine whether the virtual tree rooted at this View
2839      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2840      * representing the virtual views with this text.
2841      *
2842      * @see #findViewsWithText(ArrayList, CharSequence, int)
2843      *
2844      * @hide
2845      */
2846     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2847 
2848     /**
2849      * The undefined cursor position.
2850      *
2851      * @hide
2852      */
2853     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2854 
2855     /**
2856      * Indicates that the screen has changed state and is now off.
2857      *
2858      * @see #onScreenStateChanged(int)
2859      */
2860     public static final int SCREEN_STATE_OFF = 0x0;
2861 
2862     /**
2863      * Indicates that the screen has changed state and is now on.
2864      *
2865      * @see #onScreenStateChanged(int)
2866      */
2867     public static final int SCREEN_STATE_ON = 0x1;
2868 
2869     /**
2870      * Indicates no axis of view scrolling.
2871      */
2872     public static final int SCROLL_AXIS_NONE = 0;
2873 
2874     /**
2875      * Indicates scrolling along the horizontal axis.
2876      */
2877     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2878 
2879     /**
2880      * Indicates scrolling along the vertical axis.
2881      */
2882     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2883 
2884     /**
2885      * Controls the over-scroll mode for this view.
2886      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2887      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2888      * and {@link #OVER_SCROLL_NEVER}.
2889      */
2890     private int mOverScrollMode;
2891 
2892     /**
2893      * The parent this view is attached to.
2894      * {@hide}
2895      *
2896      * @see #getParent()
2897      */
2898     protected ViewParent mParent;
2899 
2900     /**
2901      * {@hide}
2902      */
2903     AttachInfo mAttachInfo;
2904 
2905     /**
2906      * {@hide}
2907      */
2908     @ViewDebug.ExportedProperty(flagMapping = {
2909         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2910                 name = "FORCE_LAYOUT"),
2911         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2912                 name = "LAYOUT_REQUIRED"),
2913         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2914             name = "DRAWING_CACHE_INVALID", outputIf = false),
2915         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2916         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2917         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2918         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2919     }, formatToHexString = true)
2920     int mPrivateFlags;
2921     int mPrivateFlags2;
2922     int mPrivateFlags3;
2923 
2924     /**
2925      * This view's request for the visibility of the status bar.
2926      * @hide
2927      */
2928     @ViewDebug.ExportedProperty(flagMapping = {
2929         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2930                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2931                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2932         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2933                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2934                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2935         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2936                                 equals = SYSTEM_UI_FLAG_VISIBLE,
2937                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2938     }, formatToHexString = true)
2939     int mSystemUiVisibility;
2940 
2941     /**
2942      * Reference count for transient state.
2943      * @see #setHasTransientState(boolean)
2944      */
2945     int mTransientStateCount = 0;
2946 
2947     /**
2948      * Count of how many windows this view has been attached to.
2949      */
2950     int mWindowAttachCount;
2951 
2952     /**
2953      * The layout parameters associated with this view and used by the parent
2954      * {@link android.view.ViewGroup} to determine how this view should be
2955      * laid out.
2956      * {@hide}
2957      */
2958     protected ViewGroup.LayoutParams mLayoutParams;
2959 
2960     /**
2961      * The view flags hold various views states.
2962      * {@hide}
2963      */
2964     @ViewDebug.ExportedProperty(formatToHexString = true)
2965     int mViewFlags;
2966 
2967     static class TransformationInfo {
2968         /**
2969          * The transform matrix for the View. This transform is calculated internally
2970          * based on the translation, rotation, and scale properties.
2971          *
2972          * Do *not* use this variable directly; instead call getMatrix(), which will
2973          * load the value from the View's RenderNode.
2974          */
2975         private final Matrix mMatrix = new Matrix();
2976 
2977         /**
2978          * The inverse transform matrix for the View. This transform is calculated
2979          * internally based on the translation, rotation, and scale properties.
2980          *
2981          * Do *not* use this variable directly; instead call getInverseMatrix(),
2982          * which will load the value from the View's RenderNode.
2983          */
2984         private Matrix mInverseMatrix;
2985 
2986         /**
2987          * The opacity of the View. This is a value from 0 to 1, where 0 means
2988          * completely transparent and 1 means completely opaque.
2989          */
2990         @ViewDebug.ExportedProperty
2991         float mAlpha = 1f;
2992 
2993         /**
2994          * The opacity of the view as manipulated by the Fade transition. This is a hidden
2995          * property only used by transitions, which is composited with the other alpha
2996          * values to calculate the final visual alpha value.
2997          */
2998         float mTransitionAlpha = 1f;
2999     }
3000 
3001     TransformationInfo mTransformationInfo;
3002 
3003     /**
3004      * Current clip bounds. to which all drawing of this view are constrained.
3005      */
3006     Rect mClipBounds = null;
3007 
3008     private boolean mLastIsOpaque;
3009 
3010     /**
3011      * The distance in pixels from the left edge of this view's parent
3012      * to the left edge of this view.
3013      * {@hide}
3014      */
3015     @ViewDebug.ExportedProperty(category = "layout")
3016     protected int mLeft;
3017     /**
3018      * The distance in pixels from the left edge of this view's parent
3019      * to the right edge of this view.
3020      * {@hide}
3021      */
3022     @ViewDebug.ExportedProperty(category = "layout")
3023     protected int mRight;
3024     /**
3025      * The distance in pixels from the top edge of this view's parent
3026      * to the top edge of this view.
3027      * {@hide}
3028      */
3029     @ViewDebug.ExportedProperty(category = "layout")
3030     protected int mTop;
3031     /**
3032      * The distance in pixels from the top edge of this view's parent
3033      * to the bottom edge of this view.
3034      * {@hide}
3035      */
3036     @ViewDebug.ExportedProperty(category = "layout")
3037     protected int mBottom;
3038 
3039     /**
3040      * The offset, in pixels, by which the content of this view is scrolled
3041      * horizontally.
3042      * {@hide}
3043      */
3044     @ViewDebug.ExportedProperty(category = "scrolling")
3045     protected int mScrollX;
3046     /**
3047      * The offset, in pixels, by which the content of this view is scrolled
3048      * vertically.
3049      * {@hide}
3050      */
3051     @ViewDebug.ExportedProperty(category = "scrolling")
3052     protected int mScrollY;
3053 
3054     /**
3055      * The left padding in pixels, that is the distance in pixels between the
3056      * left edge of this view and the left edge of its content.
3057      * {@hide}
3058      */
3059     @ViewDebug.ExportedProperty(category = "padding")
3060     protected int mPaddingLeft = 0;
3061     /**
3062      * The right padding in pixels, that is the distance in pixels between the
3063      * right edge of this view and the right edge of its content.
3064      * {@hide}
3065      */
3066     @ViewDebug.ExportedProperty(category = "padding")
3067     protected int mPaddingRight = 0;
3068     /**
3069      * The top padding in pixels, that is the distance in pixels between the
3070      * top edge of this view and the top edge of its content.
3071      * {@hide}
3072      */
3073     @ViewDebug.ExportedProperty(category = "padding")
3074     protected int mPaddingTop;
3075     /**
3076      * The bottom padding in pixels, that is the distance in pixels between the
3077      * bottom edge of this view and the bottom edge of its content.
3078      * {@hide}
3079      */
3080     @ViewDebug.ExportedProperty(category = "padding")
3081     protected int mPaddingBottom;
3082 
3083     /**
3084      * The layout insets in pixels, that is the distance in pixels between the
3085      * visible edges of this view its bounds.
3086      */
3087     private Insets mLayoutInsets;
3088 
3089     /**
3090      * Briefly describes the view and is primarily used for accessibility support.
3091      */
3092     private CharSequence mContentDescription;
3093 
3094     /**
3095      * Specifies the id of a view for which this view serves as a label for
3096      * accessibility purposes.
3097      */
3098     private int mLabelForId = View.NO_ID;
3099 
3100     /**
3101      * Predicate for matching labeled view id with its label for
3102      * accessibility purposes.
3103      */
3104     private MatchLabelForPredicate mMatchLabelForPredicate;
3105 
3106     /**
3107      * Specifies a view before which this one is visited in accessibility traversal.
3108      */
3109     private int mAccessibilityTraversalBeforeId = NO_ID;
3110 
3111     /**
3112      * Specifies a view after which this one is visited in accessibility traversal.
3113      */
3114     private int mAccessibilityTraversalAfterId = NO_ID;
3115 
3116     /**
3117      * Predicate for matching a view by its id.
3118      */
3119     private MatchIdPredicate mMatchIdPredicate;
3120 
3121     /**
3122      * Cache the paddingRight set by the user to append to the scrollbar's size.
3123      *
3124      * @hide
3125      */
3126     @ViewDebug.ExportedProperty(category = "padding")
3127     protected int mUserPaddingRight;
3128 
3129     /**
3130      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3131      *
3132      * @hide
3133      */
3134     @ViewDebug.ExportedProperty(category = "padding")
3135     protected int mUserPaddingBottom;
3136 
3137     /**
3138      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3139      *
3140      * @hide
3141      */
3142     @ViewDebug.ExportedProperty(category = "padding")
3143     protected int mUserPaddingLeft;
3144 
3145     /**
3146      * Cache the paddingStart set by the user to append to the scrollbar's size.
3147      *
3148      */
3149     @ViewDebug.ExportedProperty(category = "padding")
3150     int mUserPaddingStart;
3151 
3152     /**
3153      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3154      *
3155      */
3156     @ViewDebug.ExportedProperty(category = "padding")
3157     int mUserPaddingEnd;
3158 
3159     /**
3160      * Cache initial left padding.
3161      *
3162      * @hide
3163      */
3164     int mUserPaddingLeftInitial;
3165 
3166     /**
3167      * Cache initial right padding.
3168      *
3169      * @hide
3170      */
3171     int mUserPaddingRightInitial;
3172 
3173     /**
3174      * Default undefined padding
3175      */
3176     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3177 
3178     /**
3179      * Cache if a left padding has been defined
3180      */
3181     private boolean mLeftPaddingDefined = false;
3182 
3183     /**
3184      * Cache if a right padding has been defined
3185      */
3186     private boolean mRightPaddingDefined = false;
3187 
3188     /**
3189      * @hide
3190      */
3191     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3192     /**
3193      * @hide
3194      */
3195     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3196 
3197     private LongSparseLongArray mMeasureCache;
3198 
3199     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3200     private Drawable mBackground;
3201     private TintInfo mBackgroundTint;
3202 
3203     /**
3204      * RenderNode used for backgrounds.
3205      * <p>
3206      * When non-null and valid, this is expected to contain an up-to-date copy
3207      * of the background drawable. It is cleared on temporary detach, and reset
3208      * on cleanup.
3209      */
3210     private RenderNode mBackgroundRenderNode;
3211 
3212     private int mBackgroundResource;
3213     private boolean mBackgroundSizeChanged;
3214 
3215     private String mTransitionName;
3216 
3217     private static class TintInfo {
3218         ColorStateList mTintList;
3219         PorterDuff.Mode mTintMode;
3220         boolean mHasTintMode;
3221         boolean mHasTintList;
3222     }
3223 
3224     static class ListenerInfo {
3225         /**
3226          * Listener used to dispatch focus change events.
3227          * This field should be made private, so it is hidden from the SDK.
3228          * {@hide}
3229          */
3230         protected OnFocusChangeListener mOnFocusChangeListener;
3231 
3232         /**
3233          * Listeners for layout change events.
3234          */
3235         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3236 
3237         protected OnScrollChangeListener mOnScrollChangeListener;
3238 
3239         /**
3240          * Listeners for attach events.
3241          */
3242         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3243 
3244         /**
3245          * Listener used to dispatch click events.
3246          * This field should be made private, so it is hidden from the SDK.
3247          * {@hide}
3248          */
3249         public OnClickListener mOnClickListener;
3250 
3251         /**
3252          * Listener used to dispatch long click events.
3253          * This field should be made private, so it is hidden from the SDK.
3254          * {@hide}
3255          */
3256         protected OnLongClickListener mOnLongClickListener;
3257 
3258         /**
3259          * Listener used to build the context menu.
3260          * This field should be made private, so it is hidden from the SDK.
3261          * {@hide}
3262          */
3263         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3264 
3265         private OnKeyListener mOnKeyListener;
3266 
3267         private OnTouchListener mOnTouchListener;
3268 
3269         private OnHoverListener mOnHoverListener;
3270 
3271         private OnGenericMotionListener mOnGenericMotionListener;
3272 
3273         private OnDragListener mOnDragListener;
3274 
3275         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3276 
3277         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3278     }
3279 
3280     ListenerInfo mListenerInfo;
3281 
3282     /**
3283      * The application environment this view lives in.
3284      * This field should be made private, so it is hidden from the SDK.
3285      * {@hide}
3286      */
3287     @ViewDebug.ExportedProperty(deepExport = true)
3288     protected Context mContext;
3289 
3290     private final Resources mResources;
3291 
3292     private ScrollabilityCache mScrollCache;
3293 
3294     private int[] mDrawableState = null;
3295 
3296     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3297 
3298     /**
3299      * Animator that automatically runs based on state changes.
3300      */
3301     private StateListAnimator mStateListAnimator;
3302 
3303     /**
3304      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3305      * the user may specify which view to go to next.
3306      */
3307     private int mNextFocusLeftId = View.NO_ID;
3308 
3309     /**
3310      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3311      * the user may specify which view to go to next.
3312      */
3313     private int mNextFocusRightId = View.NO_ID;
3314 
3315     /**
3316      * When this view has focus and the next focus is {@link #FOCUS_UP},
3317      * the user may specify which view to go to next.
3318      */
3319     private int mNextFocusUpId = View.NO_ID;
3320 
3321     /**
3322      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3323      * the user may specify which view to go to next.
3324      */
3325     private int mNextFocusDownId = View.NO_ID;
3326 
3327     /**
3328      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3329      * the user may specify which view to go to next.
3330      */
3331     int mNextFocusForwardId = View.NO_ID;
3332 
3333     private CheckForLongPress mPendingCheckForLongPress;
3334     private CheckForTap mPendingCheckForTap = null;
3335     private PerformClick mPerformClick;
3336     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3337 
3338     private UnsetPressedState mUnsetPressedState;
3339 
3340     /**
3341      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3342      * up event while a long press is invoked as soon as the long press duration is reached, so
3343      * a long press could be performed before the tap is checked, in which case the tap's action
3344      * should not be invoked.
3345      */
3346     private boolean mHasPerformedLongPress;
3347 
3348     /**
3349      * The minimum height of the view. We'll try our best to have the height
3350      * of this view to at least this amount.
3351      */
3352     @ViewDebug.ExportedProperty(category = "measurement")
3353     private int mMinHeight;
3354 
3355     /**
3356      * The minimum width of the view. We'll try our best to have the width
3357      * of this view to at least this amount.
3358      */
3359     @ViewDebug.ExportedProperty(category = "measurement")
3360     private int mMinWidth;
3361 
3362     /**
3363      * The delegate to handle touch events that are physically in this view
3364      * but should be handled by another view.
3365      */
3366     private TouchDelegate mTouchDelegate = null;
3367 
3368     /**
3369      * Solid color to use as a background when creating the drawing cache. Enables
3370      * the cache to use 16 bit bitmaps instead of 32 bit.
3371      */
3372     private int mDrawingCacheBackgroundColor = 0;
3373 
3374     /**
3375      * Special tree observer used when mAttachInfo is null.
3376      */
3377     private ViewTreeObserver mFloatingTreeObserver;
3378 
3379     /**
3380      * Cache the touch slop from the context that created the view.
3381      */
3382     private int mTouchSlop;
3383 
3384     /**
3385      * Object that handles automatic animation of view properties.
3386      */
3387     private ViewPropertyAnimator mAnimator = null;
3388 
3389     /**
3390      * Flag indicating that a drag can cross window boundaries.  When
3391      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3392      * with this flag set, all visible applications will be able to participate
3393      * in the drag operation and receive the dragged content.
3394      *
3395      * @hide
3396      */
3397     public static final int DRAG_FLAG_GLOBAL = 1;
3398 
3399     /**
3400      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3401      */
3402     private float mVerticalScrollFactor;
3403 
3404     /**
3405      * Position of the vertical scroll bar.
3406      */
3407     private int mVerticalScrollbarPosition;
3408 
3409     /**
3410      * Position the scroll bar at the default position as determined by the system.
3411      */
3412     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3413 
3414     /**
3415      * Position the scroll bar along the left edge.
3416      */
3417     public static final int SCROLLBAR_POSITION_LEFT = 1;
3418 
3419     /**
3420      * Position the scroll bar along the right edge.
3421      */
3422     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3423 
3424     /**
3425      * Indicates that the view does not have a layer.
3426      *
3427      * @see #getLayerType()
3428      * @see #setLayerType(int, android.graphics.Paint)
3429      * @see #LAYER_TYPE_SOFTWARE
3430      * @see #LAYER_TYPE_HARDWARE
3431      */
3432     public static final int LAYER_TYPE_NONE = 0;
3433 
3434     /**
3435      * <p>Indicates that the view has a software layer. A software layer is backed
3436      * by a bitmap and causes the view to be rendered using Android's software
3437      * rendering pipeline, even if hardware acceleration is enabled.</p>
3438      *
3439      * <p>Software layers have various usages:</p>
3440      * <p>When the application is not using hardware acceleration, a software layer
3441      * is useful to apply a specific color filter and/or blending mode and/or
3442      * translucency to a view and all its children.</p>
3443      * <p>When the application is using hardware acceleration, a software layer
3444      * is useful to render drawing primitives not supported by the hardware
3445      * accelerated pipeline. It can also be used to cache a complex view tree
3446      * into a texture and reduce the complexity of drawing operations. For instance,
3447      * when animating a complex view tree with a translation, a software layer can
3448      * be used to render the view tree only once.</p>
3449      * <p>Software layers should be avoided when the affected view tree updates
3450      * often. Every update will require to re-render the software layer, which can
3451      * potentially be slow (particularly when hardware acceleration is turned on
3452      * since the layer will have to be uploaded into a hardware texture after every
3453      * update.)</p>
3454      *
3455      * @see #getLayerType()
3456      * @see #setLayerType(int, android.graphics.Paint)
3457      * @see #LAYER_TYPE_NONE
3458      * @see #LAYER_TYPE_HARDWARE
3459      */
3460     public static final int LAYER_TYPE_SOFTWARE = 1;
3461 
3462     /**
3463      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3464      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3465      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3466      * rendering pipeline, but only if hardware acceleration is turned on for the
3467      * view hierarchy. When hardware acceleration is turned off, hardware layers
3468      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3469      *
3470      * <p>A hardware layer is useful to apply a specific color filter and/or
3471      * blending mode and/or translucency to a view and all its children.</p>
3472      * <p>A hardware layer can be used to cache a complex view tree into a
3473      * texture and reduce the complexity of drawing operations. For instance,
3474      * when animating a complex view tree with a translation, a hardware layer can
3475      * be used to render the view tree only once.</p>
3476      * <p>A hardware layer can also be used to increase the rendering quality when
3477      * rotation transformations are applied on a view. It can also be used to
3478      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3479      *
3480      * @see #getLayerType()
3481      * @see #setLayerType(int, android.graphics.Paint)
3482      * @see #LAYER_TYPE_NONE
3483      * @see #LAYER_TYPE_SOFTWARE
3484      */
3485     public static final int LAYER_TYPE_HARDWARE = 2;
3486 
3487     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3488             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3489             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3490             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3491     })
3492     int mLayerType = LAYER_TYPE_NONE;
3493     Paint mLayerPaint;
3494 
3495     /**
3496      * Set to true when drawing cache is enabled and cannot be created.
3497      *
3498      * @hide
3499      */
3500     public boolean mCachingFailed;
3501     private Bitmap mDrawingCache;
3502     private Bitmap mUnscaledDrawingCache;
3503 
3504     /**
3505      * RenderNode holding View properties, potentially holding a DisplayList of View content.
3506      * <p>
3507      * When non-null and valid, this is expected to contain an up-to-date copy
3508      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3509      * cleanup.
3510      */
3511     final RenderNode mRenderNode;
3512 
3513     /**
3514      * Set to true when the view is sending hover accessibility events because it
3515      * is the innermost hovered view.
3516      */
3517     private boolean mSendingHoverAccessibilityEvents;
3518 
3519     /**
3520      * Delegate for injecting accessibility functionality.
3521      */
3522     AccessibilityDelegate mAccessibilityDelegate;
3523 
3524     /**
3525      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3526      * and add/remove objects to/from the overlay directly through the Overlay methods.
3527      */
3528     ViewOverlay mOverlay;
3529 
3530     /**
3531      * The currently active parent view for receiving delegated nested scrolling events.
3532      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3533      * by {@link #stopNestedScroll()} at the same point where we clear
3534      * requestDisallowInterceptTouchEvent.
3535      */
3536     private ViewParent mNestedScrollingParent;
3537 
3538     /**
3539      * Consistency verifier for debugging purposes.
3540      * @hide
3541      */
3542     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3543             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3544                     new InputEventConsistencyVerifier(this, 0) : null;
3545 
3546     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3547 
3548     private int[] mTempNestedScrollConsumed;
3549 
3550     /**
3551      * An overlay is going to draw this View instead of being drawn as part of this
3552      * View's parent. mGhostView is the View in the Overlay that must be invalidated
3553      * when this view is invalidated.
3554      */
3555     GhostView mGhostView;
3556 
3557     /**
3558      * Holds pairs of adjacent attribute data: attribute name followed by its value.
3559      * @hide
3560      */
3561     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3562     public String[] mAttributes;
3563 
3564     /**
3565      * Maps a Resource id to its name.
3566      */
3567     private static SparseArray<String> mAttributeMap;
3568 
3569     /**
3570      * Simple constructor to use when creating a view from code.
3571      *
3572      * @param context The Context the view is running in, through which it can
3573      *        access the current theme, resources, etc.
3574      */
View(Context context)3575     public View(Context context) {
3576         mContext = context;
3577         mResources = context != null ? context.getResources() : null;
3578         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3579         // Set some flags defaults
3580         mPrivateFlags2 =
3581                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3582                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3583                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3584                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3585                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3586                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3587         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3588         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3589         mUserPaddingStart = UNDEFINED_PADDING;
3590         mUserPaddingEnd = UNDEFINED_PADDING;
3591         mRenderNode = RenderNode.create(getClass().getName(), this);
3592 
3593         if (!sCompatibilityDone && context != null) {
3594             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3595 
3596             // Older apps may need this compatibility hack for measurement.
3597             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3598 
3599             // Older apps expect onMeasure() to always be called on a layout pass, regardless
3600             // of whether a layout was requested on that View.
3601             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3602 
3603             sCompatibilityDone = true;
3604         }
3605     }
3606 
3607     /**
3608      * Constructor that is called when inflating a view from XML. This is called
3609      * when a view is being constructed from an XML file, supplying attributes
3610      * that were specified in the XML file. This version uses a default style of
3611      * 0, so the only attribute values applied are those in the Context's Theme
3612      * and the given AttributeSet.
3613      *
3614      * <p>
3615      * The method onFinishInflate() will be called after all children have been
3616      * added.
3617      *
3618      * @param context The Context the view is running in, through which it can
3619      *        access the current theme, resources, etc.
3620      * @param attrs The attributes of the XML tag that is inflating the view.
3621      * @see #View(Context, AttributeSet, int)
3622      */
3623     public View(Context context, AttributeSet attrs) {
3624         this(context, attrs, 0);
3625     }
3626 
3627     /**
3628      * Perform inflation from XML and apply a class-specific base style from a
3629      * theme attribute. This constructor of View allows subclasses to use their
3630      * own base style when they are inflating. For example, a Button class's
3631      * constructor would call this version of the super class constructor and
3632      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3633      * allows the theme's button style to modify all of the base view attributes
3634      * (in particular its background) as well as the Button class's attributes.
3635      *
3636      * @param context The Context the view is running in, through which it can
3637      *        access the current theme, resources, etc.
3638      * @param attrs The attributes of the XML tag that is inflating the view.
3639      * @param defStyleAttr An attribute in the current theme that contains a
3640      *        reference to a style resource that supplies default values for
3641      *        the view. Can be 0 to not look for defaults.
3642      * @see #View(Context, AttributeSet)
3643      */
3644     public View(Context context, AttributeSet attrs, int defStyleAttr) {
3645         this(context, attrs, defStyleAttr, 0);
3646     }
3647 
3648     /**
3649      * Perform inflation from XML and apply a class-specific base style from a
3650      * theme attribute or style resource. This constructor of View allows
3651      * subclasses to use their own base style when they are inflating.
3652      * <p>
3653      * When determining the final value of a particular attribute, there are
3654      * four inputs that come into play:
3655      * <ol>
3656      * <li>Any attribute values in the given AttributeSet.
3657      * <li>The style resource specified in the AttributeSet (named "style").
3658      * <li>The default style specified by <var>defStyleAttr</var>.
3659      * <li>The default style specified by <var>defStyleRes</var>.
3660      * <li>The base values in this theme.
3661      * </ol>
3662      * <p>
3663      * Each of these inputs is considered in-order, with the first listed taking
3664      * precedence over the following ones. In other words, if in the
3665      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3666      * , then the button's text will <em>always</em> be black, regardless of
3667      * what is specified in any of the styles.
3668      *
3669      * @param context The Context the view is running in, through which it can
3670      *        access the current theme, resources, etc.
3671      * @param attrs The attributes of the XML tag that is inflating the view.
3672      * @param defStyleAttr An attribute in the current theme that contains a
3673      *        reference to a style resource that supplies default values for
3674      *        the view. Can be 0 to not look for defaults.
3675      * @param defStyleRes A resource identifier of a style resource that
3676      *        supplies default values for the view, used only if
3677      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3678      *        to not look for defaults.
3679      * @see #View(Context, AttributeSet, int)
3680      */
3681     public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3682         this(context);
3683 
3684         final TypedArray a = context.obtainStyledAttributes(
3685                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3686 
3687         if (mDebugViewAttributes) {
3688             saveAttributeData(attrs, a);
3689         }
3690 
3691         Drawable background = null;
3692 
3693         int leftPadding = -1;
3694         int topPadding = -1;
3695         int rightPadding = -1;
3696         int bottomPadding = -1;
3697         int startPadding = UNDEFINED_PADDING;
3698         int endPadding = UNDEFINED_PADDING;
3699 
3700         int padding = -1;
3701 
3702         int viewFlagValues = 0;
3703         int viewFlagMasks = 0;
3704 
3705         boolean setScrollContainer = false;
3706 
3707         int x = 0;
3708         int y = 0;
3709 
3710         float tx = 0;
3711         float ty = 0;
3712         float tz = 0;
3713         float elevation = 0;
3714         float rotation = 0;
3715         float rotationX = 0;
3716         float rotationY = 0;
3717         float sx = 1f;
3718         float sy = 1f;
3719         boolean transformSet = false;
3720 
3721         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3722         int overScrollMode = mOverScrollMode;
3723         boolean initializeScrollbars = false;
3724 
3725         boolean startPaddingDefined = false;
3726         boolean endPaddingDefined = false;
3727         boolean leftPaddingDefined = false;
3728         boolean rightPaddingDefined = false;
3729 
3730         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3731 
3732         final int N = a.getIndexCount();
3733         for (int i = 0; i < N; i++) {
3734             int attr = a.getIndex(i);
3735             switch (attr) {
3736                 case com.android.internal.R.styleable.View_background:
3737                     background = a.getDrawable(attr);
3738                     break;
3739                 case com.android.internal.R.styleable.View_padding:
3740                     padding = a.getDimensionPixelSize(attr, -1);
3741                     mUserPaddingLeftInitial = padding;
3742                     mUserPaddingRightInitial = padding;
3743                     leftPaddingDefined = true;
3744                     rightPaddingDefined = true;
3745                     break;
3746                  case com.android.internal.R.styleable.View_paddingLeft:
3747                     leftPadding = a.getDimensionPixelSize(attr, -1);
3748                     mUserPaddingLeftInitial = leftPadding;
3749                     leftPaddingDefined = true;
3750                     break;
3751                 case com.android.internal.R.styleable.View_paddingTop:
3752                     topPadding = a.getDimensionPixelSize(attr, -1);
3753                     break;
3754                 case com.android.internal.R.styleable.View_paddingRight:
3755                     rightPadding = a.getDimensionPixelSize(attr, -1);
3756                     mUserPaddingRightInitial = rightPadding;
3757                     rightPaddingDefined = true;
3758                     break;
3759                 case com.android.internal.R.styleable.View_paddingBottom:
3760                     bottomPadding = a.getDimensionPixelSize(attr, -1);
3761                     break;
3762                 case com.android.internal.R.styleable.View_paddingStart:
3763                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3764                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3765                     break;
3766                 case com.android.internal.R.styleable.View_paddingEnd:
3767                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3768                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3769                     break;
3770                 case com.android.internal.R.styleable.View_scrollX:
3771                     x = a.getDimensionPixelOffset(attr, 0);
3772                     break;
3773                 case com.android.internal.R.styleable.View_scrollY:
3774                     y = a.getDimensionPixelOffset(attr, 0);
3775                     break;
3776                 case com.android.internal.R.styleable.View_alpha:
3777                     setAlpha(a.getFloat(attr, 1f));
3778                     break;
3779                 case com.android.internal.R.styleable.View_transformPivotX:
3780                     setPivotX(a.getDimensionPixelOffset(attr, 0));
3781                     break;
3782                 case com.android.internal.R.styleable.View_transformPivotY:
3783                     setPivotY(a.getDimensionPixelOffset(attr, 0));
3784                     break;
3785                 case com.android.internal.R.styleable.View_translationX:
3786                     tx = a.getDimensionPixelOffset(attr, 0);
3787                     transformSet = true;
3788                     break;
3789                 case com.android.internal.R.styleable.View_translationY:
3790                     ty = a.getDimensionPixelOffset(attr, 0);
3791                     transformSet = true;
3792                     break;
3793                 case com.android.internal.R.styleable.View_translationZ:
3794                     tz = a.getDimensionPixelOffset(attr, 0);
3795                     transformSet = true;
3796                     break;
3797                 case com.android.internal.R.styleable.View_elevation:
3798                     elevation = a.getDimensionPixelOffset(attr, 0);
3799                     transformSet = true;
3800                     break;
3801                 case com.android.internal.R.styleable.View_rotation:
3802                     rotation = a.getFloat(attr, 0);
3803                     transformSet = true;
3804                     break;
3805                 case com.android.internal.R.styleable.View_rotationX:
3806                     rotationX = a.getFloat(attr, 0);
3807                     transformSet = true;
3808                     break;
3809                 case com.android.internal.R.styleable.View_rotationY:
3810                     rotationY = a.getFloat(attr, 0);
3811                     transformSet = true;
3812                     break;
3813                 case com.android.internal.R.styleable.View_scaleX:
3814                     sx = a.getFloat(attr, 1f);
3815                     transformSet = true;
3816                     break;
3817                 case com.android.internal.R.styleable.View_scaleY:
3818                     sy = a.getFloat(attr, 1f);
3819                     transformSet = true;
3820                     break;
3821                 case com.android.internal.R.styleable.View_id:
3822                     mID = a.getResourceId(attr, NO_ID);
3823                     break;
3824                 case com.android.internal.R.styleable.View_tag:
3825                     mTag = a.getText(attr);
3826                     break;
3827                 case com.android.internal.R.styleable.View_fitsSystemWindows:
3828                     if (a.getBoolean(attr, false)) {
3829                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
3830                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3831                     }
3832                     break;
3833                 case com.android.internal.R.styleable.View_focusable:
3834                     if (a.getBoolean(attr, false)) {
3835                         viewFlagValues |= FOCUSABLE;
3836                         viewFlagMasks |= FOCUSABLE_MASK;
3837                     }
3838                     break;
3839                 case com.android.internal.R.styleable.View_focusableInTouchMode:
3840                     if (a.getBoolean(attr, false)) {
3841                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3842                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3843                     }
3844                     break;
3845                 case com.android.internal.R.styleable.View_clickable:
3846                     if (a.getBoolean(attr, false)) {
3847                         viewFlagValues |= CLICKABLE;
3848                         viewFlagMasks |= CLICKABLE;
3849                     }
3850                     break;
3851                 case com.android.internal.R.styleable.View_longClickable:
3852                     if (a.getBoolean(attr, false)) {
3853                         viewFlagValues |= LONG_CLICKABLE;
3854                         viewFlagMasks |= LONG_CLICKABLE;
3855                     }
3856                     break;
3857                 case com.android.internal.R.styleable.View_saveEnabled:
3858                     if (!a.getBoolean(attr, true)) {
3859                         viewFlagValues |= SAVE_DISABLED;
3860                         viewFlagMasks |= SAVE_DISABLED_MASK;
3861                     }
3862                     break;
3863                 case com.android.internal.R.styleable.View_duplicateParentState:
3864                     if (a.getBoolean(attr, false)) {
3865                         viewFlagValues |= DUPLICATE_PARENT_STATE;
3866                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
3867                     }
3868                     break;
3869                 case com.android.internal.R.styleable.View_visibility:
3870                     final int visibility = a.getInt(attr, 0);
3871                     if (visibility != 0) {
3872                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
3873                         viewFlagMasks |= VISIBILITY_MASK;
3874                     }
3875                     break;
3876                 case com.android.internal.R.styleable.View_layoutDirection:
3877                     // Clear any layout direction flags (included resolved bits) already set
3878                     mPrivateFlags2 &=
3879                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3880                     // Set the layout direction flags depending on the value of the attribute
3881                     final int layoutDirection = a.getInt(attr, -1);
3882                     final int value = (layoutDirection != -1) ?
3883                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3884                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3885                     break;
3886                 case com.android.internal.R.styleable.View_drawingCacheQuality:
3887                     final int cacheQuality = a.getInt(attr, 0);
3888                     if (cacheQuality != 0) {
3889                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3890                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3891                     }
3892                     break;
3893                 case com.android.internal.R.styleable.View_contentDescription:
3894                     setContentDescription(a.getString(attr));
3895                     break;
3896                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
3897                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
3898                     break;
3899                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
3900                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
3901                     break;
3902                 case com.android.internal.R.styleable.View_labelFor:
3903                     setLabelFor(a.getResourceId(attr, NO_ID));
3904                     break;
3905                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3906                     if (!a.getBoolean(attr, true)) {
3907                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3908                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3909                     }
3910                     break;
3911                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3912                     if (!a.getBoolean(attr, true)) {
3913                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3914                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3915                     }
3916                     break;
3917                 case R.styleable.View_scrollbars:
3918                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3919                     if (scrollbars != SCROLLBARS_NONE) {
3920                         viewFlagValues |= scrollbars;
3921                         viewFlagMasks |= SCROLLBARS_MASK;
3922                         initializeScrollbars = true;
3923                     }
3924                     break;
3925                 //noinspection deprecation
3926                 case R.styleable.View_fadingEdge:
3927                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3928                         // Ignore the attribute starting with ICS
3929                         break;
3930                     }
3931                     // With builds < ICS, fall through and apply fading edges
3932                 case R.styleable.View_requiresFadingEdge:
3933                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3934                     if (fadingEdge != FADING_EDGE_NONE) {
3935                         viewFlagValues |= fadingEdge;
3936                         viewFlagMasks |= FADING_EDGE_MASK;
3937                         initializeFadingEdgeInternal(a);
3938                     }
3939                     break;
3940                 case R.styleable.View_scrollbarStyle:
3941                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3942                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3943                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3944                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3945                     }
3946                     break;
3947                 case R.styleable.View_isScrollContainer:
3948                     setScrollContainer = true;
3949                     if (a.getBoolean(attr, false)) {
3950                         setScrollContainer(true);
3951                     }
3952                     break;
3953                 case com.android.internal.R.styleable.View_keepScreenOn:
3954                     if (a.getBoolean(attr, false)) {
3955                         viewFlagValues |= KEEP_SCREEN_ON;
3956                         viewFlagMasks |= KEEP_SCREEN_ON;
3957                     }
3958                     break;
3959                 case R.styleable.View_filterTouchesWhenObscured:
3960                     if (a.getBoolean(attr, false)) {
3961                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3962                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3963                     }
3964                     break;
3965                 case R.styleable.View_nextFocusLeft:
3966                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3967                     break;
3968                 case R.styleable.View_nextFocusRight:
3969                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3970                     break;
3971                 case R.styleable.View_nextFocusUp:
3972                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3973                     break;
3974                 case R.styleable.View_nextFocusDown:
3975                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3976                     break;
3977                 case R.styleable.View_nextFocusForward:
3978                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3979                     break;
3980                 case R.styleable.View_minWidth:
3981                     mMinWidth = a.getDimensionPixelSize(attr, 0);
3982                     break;
3983                 case R.styleable.View_minHeight:
3984                     mMinHeight = a.getDimensionPixelSize(attr, 0);
3985                     break;
3986                 case R.styleable.View_onClick:
3987                     if (context.isRestricted()) {
3988                         throw new IllegalStateException("The android:onClick attribute cannot "
3989                                 + "be used within a restricted context");
3990                     }
3991 
3992                     final String handlerName = a.getString(attr);
3993                     if (handlerName != null) {
3994                         setOnClickListener(new OnClickListener() {
3995                             private Method mHandler;
3996 
3997                             public void onClick(View v) {
3998                                 if (mHandler == null) {
3999                                     try {
4000                                         mHandler = getContext().getClass().getMethod(handlerName,
4001                                                 View.class);
4002                                     } catch (NoSuchMethodException e) {
4003                                         int id = getId();
4004                                         String idText = id == NO_ID ? "" : " with id '"
4005                                                 + getContext().getResources().getResourceEntryName(
4006                                                     id) + "'";
4007                                         throw new IllegalStateException("Could not find a method " +
4008                                                 handlerName + "(View) in the activity "
4009                                                 + getContext().getClass() + " for onClick handler"
4010                                                 + " on view " + View.this.getClass() + idText, e);
4011                                     }
4012                                 }
4013 
4014                                 try {
4015                                     mHandler.invoke(getContext(), View.this);
4016                                 } catch (IllegalAccessException e) {
4017                                     throw new IllegalStateException("Could not execute non "
4018                                             + "public method of the activity", e);
4019                                 } catch (InvocationTargetException e) {
4020                                     throw new IllegalStateException("Could not execute "
4021                                             + "method of the activity", e);
4022                                 }
4023                             }
4024                         });
4025                     }
4026                     break;
4027                 case R.styleable.View_overScrollMode:
4028                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4029                     break;
4030                 case R.styleable.View_verticalScrollbarPosition:
4031                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4032                     break;
4033                 case R.styleable.View_layerType:
4034                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4035                     break;
4036                 case R.styleable.View_textDirection:
4037                     // Clear any text direction flag already set
4038                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4039                     // Set the text direction flags depending on the value of the attribute
4040                     final int textDirection = a.getInt(attr, -1);
4041                     if (textDirection != -1) {
4042                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4043                     }
4044                     break;
4045                 case R.styleable.View_textAlignment:
4046                     // Clear any text alignment flag already set
4047                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4048                     // Set the text alignment flag depending on the value of the attribute
4049                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4050                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4051                     break;
4052                 case R.styleable.View_importantForAccessibility:
4053                     setImportantForAccessibility(a.getInt(attr,
4054                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4055                     break;
4056                 case R.styleable.View_accessibilityLiveRegion:
4057                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4058                     break;
4059                 case R.styleable.View_transitionName:
4060                     setTransitionName(a.getString(attr));
4061                     break;
4062                 case R.styleable.View_nestedScrollingEnabled:
4063                     setNestedScrollingEnabled(a.getBoolean(attr, false));
4064                     break;
4065                 case R.styleable.View_stateListAnimator:
4066                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4067                             a.getResourceId(attr, 0)));
4068                     break;
4069                 case R.styleable.View_backgroundTint:
4070                     // This will get applied later during setBackground().
4071                     if (mBackgroundTint == null) {
4072                         mBackgroundTint = new TintInfo();
4073                     }
4074                     mBackgroundTint.mTintList = a.getColorStateList(
4075                             R.styleable.View_backgroundTint);
4076                     mBackgroundTint.mHasTintList = true;
4077                     break;
4078                 case R.styleable.View_backgroundTintMode:
4079                     // This will get applied later during setBackground().
4080                     if (mBackgroundTint == null) {
4081                         mBackgroundTint = new TintInfo();
4082                     }
4083                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4084                             R.styleable.View_backgroundTintMode, -1), null);
4085                     mBackgroundTint.mHasTintMode = true;
4086                     break;
4087                 case R.styleable.View_outlineProvider:
4088                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4089                             PROVIDER_BACKGROUND));
4090                     break;
4091             }
4092         }
4093 
4094         setOverScrollMode(overScrollMode);
4095 
4096         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4097         // the resolved layout direction). Those cached values will be used later during padding
4098         // resolution.
4099         mUserPaddingStart = startPadding;
4100         mUserPaddingEnd = endPadding;
4101 
4102         if (background != null) {
4103             setBackground(background);
4104         }
4105 
4106         // setBackground above will record that padding is currently provided by the background.
4107         // If we have padding specified via xml, record that here instead and use it.
4108         mLeftPaddingDefined = leftPaddingDefined;
4109         mRightPaddingDefined = rightPaddingDefined;
4110 
4111         if (padding >= 0) {
4112             leftPadding = padding;
4113             topPadding = padding;
4114             rightPadding = padding;
4115             bottomPadding = padding;
4116             mUserPaddingLeftInitial = padding;
4117             mUserPaddingRightInitial = padding;
4118         }
4119 
4120         if (isRtlCompatibilityMode()) {
4121             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4122             // left / right padding are used if defined (meaning here nothing to do). If they are not
4123             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4124             // start / end and resolve them as left / right (layout direction is not taken into account).
4125             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4126             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4127             // defined.
4128             if (!mLeftPaddingDefined && startPaddingDefined) {
4129                 leftPadding = startPadding;
4130             }
4131             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4132             if (!mRightPaddingDefined && endPaddingDefined) {
4133                 rightPadding = endPadding;
4134             }
4135             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4136         } else {
4137             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4138             // values defined. Otherwise, left /right values are used.
4139             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4140             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4141             // defined.
4142             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4143 
4144             if (mLeftPaddingDefined && !hasRelativePadding) {
4145                 mUserPaddingLeftInitial = leftPadding;
4146             }
4147             if (mRightPaddingDefined && !hasRelativePadding) {
4148                 mUserPaddingRightInitial = rightPadding;
4149             }
4150         }
4151 
4152         internalSetPadding(
4153                 mUserPaddingLeftInitial,
4154                 topPadding >= 0 ? topPadding : mPaddingTop,
4155                 mUserPaddingRightInitial,
4156                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4157 
4158         if (viewFlagMasks != 0) {
4159             setFlags(viewFlagValues, viewFlagMasks);
4160         }
4161 
4162         if (initializeScrollbars) {
4163             initializeScrollbarsInternal(a);
4164         }
4165 
4166         a.recycle();
4167 
4168         // Needs to be called after mViewFlags is set
4169         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4170             recomputePadding();
4171         }
4172 
4173         if (x != 0 || y != 0) {
4174             scrollTo(x, y);
4175         }
4176 
4177         if (transformSet) {
4178             setTranslationX(tx);
4179             setTranslationY(ty);
4180             setTranslationZ(tz);
4181             setElevation(elevation);
4182             setRotation(rotation);
4183             setRotationX(rotationX);
4184             setRotationY(rotationY);
4185             setScaleX(sx);
4186             setScaleY(sy);
4187         }
4188 
4189         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4190             setScrollContainer(true);
4191         }
4192 
4193         computeOpaqueFlags();
4194     }
4195 
4196     /**
4197      * Non-public constructor for use in testing
4198      */
View()4199     View() {
4200         mResources = null;
4201         mRenderNode = RenderNode.create(getClass().getName(), this);
4202     }
4203 
getAttributeMap()4204     private static SparseArray<String> getAttributeMap() {
4205         if (mAttributeMap == null) {
4206             mAttributeMap = new SparseArray<String>();
4207         }
4208         return mAttributeMap;
4209     }
4210 
saveAttributeData(AttributeSet attrs, TypedArray a)4211     private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4212         int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4213         mAttributes = new String[length];
4214 
4215         int i = 0;
4216         if (attrs != null) {
4217             for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4218                 mAttributes[i] = attrs.getAttributeName(i);
4219                 mAttributes[i + 1] = attrs.getAttributeValue(i);
4220             }
4221 
4222         }
4223 
4224         SparseArray<String> attributeMap = getAttributeMap();
4225         for (int j = 0; j < a.length(); ++j) {
4226             if (a.hasValue(j)) {
4227                 try {
4228                     int resourceId = a.getResourceId(j, 0);
4229                     if (resourceId == 0) {
4230                         continue;
4231                     }
4232 
4233                     String resourceName = attributeMap.get(resourceId);
4234                     if (resourceName == null) {
4235                         resourceName = a.getResources().getResourceName(resourceId);
4236                         attributeMap.put(resourceId, resourceName);
4237                     }
4238 
4239                     mAttributes[i] = resourceName;
4240                     mAttributes[i + 1] = a.getText(j).toString();
4241                     i += 2;
4242                 } catch (Resources.NotFoundException e) {
4243                     // if we can't get the resource name, we just ignore it
4244                 }
4245             }
4246         }
4247     }
4248 
toString()4249     public String toString() {
4250         StringBuilder out = new StringBuilder(128);
4251         out.append(getClass().getName());
4252         out.append('{');
4253         out.append(Integer.toHexString(System.identityHashCode(this)));
4254         out.append(' ');
4255         switch (mViewFlags&VISIBILITY_MASK) {
4256             case VISIBLE: out.append('V'); break;
4257             case INVISIBLE: out.append('I'); break;
4258             case GONE: out.append('G'); break;
4259             default: out.append('.'); break;
4260         }
4261         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4262         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4263         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4264         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4265         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4266         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4267         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4268         out.append(' ');
4269         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4270         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4271         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4272         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4273             out.append('p');
4274         } else {
4275             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4276         }
4277         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4278         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4279         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4280         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4281         out.append(' ');
4282         out.append(mLeft);
4283         out.append(',');
4284         out.append(mTop);
4285         out.append('-');
4286         out.append(mRight);
4287         out.append(',');
4288         out.append(mBottom);
4289         final int id = getId();
4290         if (id != NO_ID) {
4291             out.append(" #");
4292             out.append(Integer.toHexString(id));
4293             final Resources r = mResources;
4294             if (Resources.resourceHasPackage(id) && r != null) {
4295                 try {
4296                     String pkgname;
4297                     switch (id&0xff000000) {
4298                         case 0x7f000000:
4299                             pkgname="app";
4300                             break;
4301                         case 0x01000000:
4302                             pkgname="android";
4303                             break;
4304                         default:
4305                             pkgname = r.getResourcePackageName(id);
4306                             break;
4307                     }
4308                     String typename = r.getResourceTypeName(id);
4309                     String entryname = r.getResourceEntryName(id);
4310                     out.append(" ");
4311                     out.append(pkgname);
4312                     out.append(":");
4313                     out.append(typename);
4314                     out.append("/");
4315                     out.append(entryname);
4316                 } catch (Resources.NotFoundException e) {
4317                 }
4318             }
4319         }
4320         out.append("}");
4321         return out.toString();
4322     }
4323 
4324     /**
4325      * <p>
4326      * Initializes the fading edges from a given set of styled attributes. This
4327      * method should be called by subclasses that need fading edges and when an
4328      * instance of these subclasses is created programmatically rather than
4329      * being inflated from XML. This method is automatically called when the XML
4330      * is inflated.
4331      * </p>
4332      *
4333      * @param a the styled attributes set to initialize the fading edges from
4334      *
4335      * @removed
4336      */
initializeFadingEdge(TypedArray a)4337     protected void initializeFadingEdge(TypedArray a) {
4338         // This method probably shouldn't have been included in the SDK to begin with.
4339         // It relies on 'a' having been initialized using an attribute filter array that is
4340         // not publicly available to the SDK. The old method has been renamed
4341         // to initializeFadingEdgeInternal and hidden for framework use only;
4342         // this one initializes using defaults to make it safe to call for apps.
4343 
4344         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4345 
4346         initializeFadingEdgeInternal(arr);
4347 
4348         arr.recycle();
4349     }
4350 
4351     /**
4352      * <p>
4353      * Initializes the fading edges from a given set of styled attributes. This
4354      * method should be called by subclasses that need fading edges and when an
4355      * instance of these subclasses is created programmatically rather than
4356      * being inflated from XML. This method is automatically called when the XML
4357      * is inflated.
4358      * </p>
4359      *
4360      * @param a the styled attributes set to initialize the fading edges from
4361      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4362      */
initializeFadingEdgeInternal(TypedArray a)4363     protected void initializeFadingEdgeInternal(TypedArray a) {
4364         initScrollCache();
4365 
4366         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4367                 R.styleable.View_fadingEdgeLength,
4368                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4369     }
4370 
4371     /**
4372      * Returns the size of the vertical faded edges used to indicate that more
4373      * content in this view is visible.
4374      *
4375      * @return The size in pixels of the vertical faded edge or 0 if vertical
4376      *         faded edges are not enabled for this view.
4377      * @attr ref android.R.styleable#View_fadingEdgeLength
4378      */
getVerticalFadingEdgeLength()4379     public int getVerticalFadingEdgeLength() {
4380         if (isVerticalFadingEdgeEnabled()) {
4381             ScrollabilityCache cache = mScrollCache;
4382             if (cache != null) {
4383                 return cache.fadingEdgeLength;
4384             }
4385         }
4386         return 0;
4387     }
4388 
4389     /**
4390      * Set the size of the faded edge used to indicate that more content in this
4391      * view is available.  Will not change whether the fading edge is enabled; use
4392      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4393      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4394      * for the vertical or horizontal fading edges.
4395      *
4396      * @param length The size in pixels of the faded edge used to indicate that more
4397      *        content in this view is visible.
4398      */
setFadingEdgeLength(int length)4399     public void setFadingEdgeLength(int length) {
4400         initScrollCache();
4401         mScrollCache.fadingEdgeLength = length;
4402     }
4403 
4404     /**
4405      * Returns the size of the horizontal faded edges used to indicate that more
4406      * content in this view is visible.
4407      *
4408      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4409      *         faded edges are not enabled for this view.
4410      * @attr ref android.R.styleable#View_fadingEdgeLength
4411      */
getHorizontalFadingEdgeLength()4412     public int getHorizontalFadingEdgeLength() {
4413         if (isHorizontalFadingEdgeEnabled()) {
4414             ScrollabilityCache cache = mScrollCache;
4415             if (cache != null) {
4416                 return cache.fadingEdgeLength;
4417             }
4418         }
4419         return 0;
4420     }
4421 
4422     /**
4423      * Returns the width of the vertical scrollbar.
4424      *
4425      * @return The width in pixels of the vertical scrollbar or 0 if there
4426      *         is no vertical scrollbar.
4427      */
getVerticalScrollbarWidth()4428     public int getVerticalScrollbarWidth() {
4429         ScrollabilityCache cache = mScrollCache;
4430         if (cache != null) {
4431             ScrollBarDrawable scrollBar = cache.scrollBar;
4432             if (scrollBar != null) {
4433                 int size = scrollBar.getSize(true);
4434                 if (size <= 0) {
4435                     size = cache.scrollBarSize;
4436                 }
4437                 return size;
4438             }
4439             return 0;
4440         }
4441         return 0;
4442     }
4443 
4444     /**
4445      * Returns the height of the horizontal scrollbar.
4446      *
4447      * @return The height in pixels of the horizontal scrollbar or 0 if
4448      *         there is no horizontal scrollbar.
4449      */
getHorizontalScrollbarHeight()4450     protected int getHorizontalScrollbarHeight() {
4451         ScrollabilityCache cache = mScrollCache;
4452         if (cache != null) {
4453             ScrollBarDrawable scrollBar = cache.scrollBar;
4454             if (scrollBar != null) {
4455                 int size = scrollBar.getSize(false);
4456                 if (size <= 0) {
4457                     size = cache.scrollBarSize;
4458                 }
4459                 return size;
4460             }
4461             return 0;
4462         }
4463         return 0;
4464     }
4465 
4466     /**
4467      * <p>
4468      * Initializes the scrollbars from a given set of styled attributes. This
4469      * method should be called by subclasses that need scrollbars and when an
4470      * instance of these subclasses is created programmatically rather than
4471      * being inflated from XML. This method is automatically called when the XML
4472      * is inflated.
4473      * </p>
4474      *
4475      * @param a the styled attributes set to initialize the scrollbars from
4476      *
4477      * @removed
4478      */
initializeScrollbars(TypedArray a)4479     protected void initializeScrollbars(TypedArray a) {
4480         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4481         // using the View filter array which is not available to the SDK. As such, internal
4482         // framework usage now uses initializeScrollbarsInternal and we grab a default
4483         // TypedArray with the right filter instead here.
4484         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4485 
4486         initializeScrollbarsInternal(arr);
4487 
4488         // We ignored the method parameter. Recycle the one we actually did use.
4489         arr.recycle();
4490     }
4491 
4492     /**
4493      * <p>
4494      * Initializes the scrollbars from a given set of styled attributes. This
4495      * method should be called by subclasses that need scrollbars and when an
4496      * instance of these subclasses is created programmatically rather than
4497      * being inflated from XML. This method is automatically called when the XML
4498      * is inflated.
4499      * </p>
4500      *
4501      * @param a the styled attributes set to initialize the scrollbars from
4502      * @hide
4503      */
initializeScrollbarsInternal(TypedArray a)4504     protected void initializeScrollbarsInternal(TypedArray a) {
4505         initScrollCache();
4506 
4507         final ScrollabilityCache scrollabilityCache = mScrollCache;
4508 
4509         if (scrollabilityCache.scrollBar == null) {
4510             scrollabilityCache.scrollBar = new ScrollBarDrawable();
4511         }
4512 
4513         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4514 
4515         if (!fadeScrollbars) {
4516             scrollabilityCache.state = ScrollabilityCache.ON;
4517         }
4518         scrollabilityCache.fadeScrollBars = fadeScrollbars;
4519 
4520 
4521         scrollabilityCache.scrollBarFadeDuration = a.getInt(
4522                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4523                         .getScrollBarFadeDuration());
4524         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4525                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
4526                 ViewConfiguration.getScrollDefaultDelay());
4527 
4528 
4529         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4530                 com.android.internal.R.styleable.View_scrollbarSize,
4531                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
4532 
4533         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4534         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4535 
4536         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4537         if (thumb != null) {
4538             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4539         }
4540 
4541         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4542                 false);
4543         if (alwaysDraw) {
4544             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4545         }
4546 
4547         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4548         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4549 
4550         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4551         if (thumb != null) {
4552             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4553         }
4554 
4555         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4556                 false);
4557         if (alwaysDraw) {
4558             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4559         }
4560 
4561         // Apply layout direction to the new Drawables if needed
4562         final int layoutDirection = getLayoutDirection();
4563         if (track != null) {
4564             track.setLayoutDirection(layoutDirection);
4565         }
4566         if (thumb != null) {
4567             thumb.setLayoutDirection(layoutDirection);
4568         }
4569 
4570         // Re-apply user/background padding so that scrollbar(s) get added
4571         resolvePadding();
4572     }
4573 
4574     /**
4575      * <p>
4576      * Initalizes the scrollability cache if necessary.
4577      * </p>
4578      */
initScrollCache()4579     private void initScrollCache() {
4580         if (mScrollCache == null) {
4581             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4582         }
4583     }
4584 
getScrollCache()4585     private ScrollabilityCache getScrollCache() {
4586         initScrollCache();
4587         return mScrollCache;
4588     }
4589 
4590     /**
4591      * Set the position of the vertical scroll bar. Should be one of
4592      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4593      * {@link #SCROLLBAR_POSITION_RIGHT}.
4594      *
4595      * @param position Where the vertical scroll bar should be positioned.
4596      */
setVerticalScrollbarPosition(int position)4597     public void setVerticalScrollbarPosition(int position) {
4598         if (mVerticalScrollbarPosition != position) {
4599             mVerticalScrollbarPosition = position;
4600             computeOpaqueFlags();
4601             resolvePadding();
4602         }
4603     }
4604 
4605     /**
4606      * @return The position where the vertical scroll bar will show, if applicable.
4607      * @see #setVerticalScrollbarPosition(int)
4608      */
getVerticalScrollbarPosition()4609     public int getVerticalScrollbarPosition() {
4610         return mVerticalScrollbarPosition;
4611     }
4612 
getListenerInfo()4613     ListenerInfo getListenerInfo() {
4614         if (mListenerInfo != null) {
4615             return mListenerInfo;
4616         }
4617         mListenerInfo = new ListenerInfo();
4618         return mListenerInfo;
4619     }
4620 
4621     /**
4622      * Register a callback to be invoked when the scroll position of this view
4623      * changed.
4624      *
4625      * @param l The callback that will run.
4626      * @hide Only used internally.
4627      */
setOnScrollChangeListener(OnScrollChangeListener l)4628     public void setOnScrollChangeListener(OnScrollChangeListener l) {
4629         getListenerInfo().mOnScrollChangeListener = l;
4630     }
4631 
4632     /**
4633      * Register a callback to be invoked when focus of this view changed.
4634      *
4635      * @param l The callback that will run.
4636      */
setOnFocusChangeListener(OnFocusChangeListener l)4637     public void setOnFocusChangeListener(OnFocusChangeListener l) {
4638         getListenerInfo().mOnFocusChangeListener = l;
4639     }
4640 
4641     /**
4642      * Add a listener that will be called when the bounds of the view change due to
4643      * layout processing.
4644      *
4645      * @param listener The listener that will be called when layout bounds change.
4646      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)4647     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4648         ListenerInfo li = getListenerInfo();
4649         if (li.mOnLayoutChangeListeners == null) {
4650             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4651         }
4652         if (!li.mOnLayoutChangeListeners.contains(listener)) {
4653             li.mOnLayoutChangeListeners.add(listener);
4654         }
4655     }
4656 
4657     /**
4658      * Remove a listener for layout changes.
4659      *
4660      * @param listener The listener for layout bounds change.
4661      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)4662     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4663         ListenerInfo li = mListenerInfo;
4664         if (li == null || li.mOnLayoutChangeListeners == null) {
4665             return;
4666         }
4667         li.mOnLayoutChangeListeners.remove(listener);
4668     }
4669 
4670     /**
4671      * Add a listener for attach state changes.
4672      *
4673      * This listener will be called whenever this view is attached or detached
4674      * from a window. Remove the listener using
4675      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4676      *
4677      * @param listener Listener to attach
4678      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4679      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)4680     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4681         ListenerInfo li = getListenerInfo();
4682         if (li.mOnAttachStateChangeListeners == null) {
4683             li.mOnAttachStateChangeListeners
4684                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4685         }
4686         li.mOnAttachStateChangeListeners.add(listener);
4687     }
4688 
4689     /**
4690      * Remove a listener for attach state changes. The listener will receive no further
4691      * notification of window attach/detach events.
4692      *
4693      * @param listener Listener to remove
4694      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4695      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)4696     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4697         ListenerInfo li = mListenerInfo;
4698         if (li == null || li.mOnAttachStateChangeListeners == null) {
4699             return;
4700         }
4701         li.mOnAttachStateChangeListeners.remove(listener);
4702     }
4703 
4704     /**
4705      * Returns the focus-change callback registered for this view.
4706      *
4707      * @return The callback, or null if one is not registered.
4708      */
getOnFocusChangeListener()4709     public OnFocusChangeListener getOnFocusChangeListener() {
4710         ListenerInfo li = mListenerInfo;
4711         return li != null ? li.mOnFocusChangeListener : null;
4712     }
4713 
4714     /**
4715      * Register a callback to be invoked when this view is clicked. If this view is not
4716      * clickable, it becomes clickable.
4717      *
4718      * @param l The callback that will run
4719      *
4720      * @see #setClickable(boolean)
4721      */
setOnClickListener(OnClickListener l)4722     public void setOnClickListener(OnClickListener l) {
4723         if (!isClickable()) {
4724             setClickable(true);
4725         }
4726         getListenerInfo().mOnClickListener = l;
4727     }
4728 
4729     /**
4730      * Return whether this view has an attached OnClickListener.  Returns
4731      * true if there is a listener, false if there is none.
4732      */
hasOnClickListeners()4733     public boolean hasOnClickListeners() {
4734         ListenerInfo li = mListenerInfo;
4735         return (li != null && li.mOnClickListener != null);
4736     }
4737 
4738     /**
4739      * Register a callback to be invoked when this view is clicked and held. If this view is not
4740      * long clickable, it becomes long clickable.
4741      *
4742      * @param l The callback that will run
4743      *
4744      * @see #setLongClickable(boolean)
4745      */
setOnLongClickListener(OnLongClickListener l)4746     public void setOnLongClickListener(OnLongClickListener l) {
4747         if (!isLongClickable()) {
4748             setLongClickable(true);
4749         }
4750         getListenerInfo().mOnLongClickListener = l;
4751     }
4752 
4753     /**
4754      * Register a callback to be invoked when the context menu for this view is
4755      * being built. If this view is not long clickable, it becomes long clickable.
4756      *
4757      * @param l The callback that will run
4758      *
4759      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)4760     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4761         if (!isLongClickable()) {
4762             setLongClickable(true);
4763         }
4764         getListenerInfo().mOnCreateContextMenuListener = l;
4765     }
4766 
4767     /**
4768      * Call this view's OnClickListener, if it is defined.  Performs all normal
4769      * actions associated with clicking: reporting accessibility event, playing
4770      * a sound, etc.
4771      *
4772      * @return True there was an assigned OnClickListener that was called, false
4773      *         otherwise is returned.
4774      */
performClick()4775     public boolean performClick() {
4776         final boolean result;
4777         final ListenerInfo li = mListenerInfo;
4778         if (li != null && li.mOnClickListener != null) {
4779             playSoundEffect(SoundEffectConstants.CLICK);
4780             li.mOnClickListener.onClick(this);
4781             result = true;
4782         } else {
4783             result = false;
4784         }
4785 
4786         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4787         return result;
4788     }
4789 
4790     /**
4791      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4792      * this only calls the listener, and does not do any associated clicking
4793      * actions like reporting an accessibility event.
4794      *
4795      * @return True there was an assigned OnClickListener that was called, false
4796      *         otherwise is returned.
4797      */
callOnClick()4798     public boolean callOnClick() {
4799         ListenerInfo li = mListenerInfo;
4800         if (li != null && li.mOnClickListener != null) {
4801             li.mOnClickListener.onClick(this);
4802             return true;
4803         }
4804         return false;
4805     }
4806 
4807     /**
4808      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4809      * OnLongClickListener did not consume the event.
4810      *
4811      * @return True if one of the above receivers consumed the event, false otherwise.
4812      */
performLongClick()4813     public boolean performLongClick() {
4814         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4815 
4816         boolean handled = false;
4817         ListenerInfo li = mListenerInfo;
4818         if (li != null && li.mOnLongClickListener != null) {
4819             handled = li.mOnLongClickListener.onLongClick(View.this);
4820         }
4821         if (!handled) {
4822             handled = showContextMenu();
4823         }
4824         if (handled) {
4825             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4826         }
4827         return handled;
4828     }
4829 
4830     /**
4831      * Performs button-related actions during a touch down event.
4832      *
4833      * @param event The event.
4834      * @return True if the down was consumed.
4835      *
4836      * @hide
4837      */
performButtonActionOnTouchDown(MotionEvent event)4838     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4839         if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4840             if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4841                 return true;
4842             }
4843         }
4844         return false;
4845     }
4846 
4847     /**
4848      * Bring up the context menu for this view.
4849      *
4850      * @return Whether a context menu was displayed.
4851      */
showContextMenu()4852     public boolean showContextMenu() {
4853         return getParent().showContextMenuForChild(this);
4854     }
4855 
4856     /**
4857      * Bring up the context menu for this view, referring to the item under the specified point.
4858      *
4859      * @param x The referenced x coordinate.
4860      * @param y The referenced y coordinate.
4861      * @param metaState The keyboard modifiers that were pressed.
4862      * @return Whether a context menu was displayed.
4863      *
4864      * @hide
4865      */
showContextMenu(float x, float y, int metaState)4866     public boolean showContextMenu(float x, float y, int metaState) {
4867         return showContextMenu();
4868     }
4869 
4870     /**
4871      * Start an action mode.
4872      *
4873      * @param callback Callback that will control the lifecycle of the action mode
4874      * @return The new action mode if it is started, null otherwise
4875      *
4876      * @see ActionMode
4877      */
startActionMode(ActionMode.Callback callback)4878     public ActionMode startActionMode(ActionMode.Callback callback) {
4879         ViewParent parent = getParent();
4880         if (parent == null) return null;
4881         return parent.startActionModeForChild(this, callback);
4882     }
4883 
4884     /**
4885      * Register a callback to be invoked when a hardware key is pressed in this view.
4886      * Key presses in software input methods will generally not trigger the methods of
4887      * this listener.
4888      * @param l the key listener to attach to this view
4889      */
setOnKeyListener(OnKeyListener l)4890     public void setOnKeyListener(OnKeyListener l) {
4891         getListenerInfo().mOnKeyListener = l;
4892     }
4893 
4894     /**
4895      * Register a callback to be invoked when a touch event is sent to this view.
4896      * @param l the touch listener to attach to this view
4897      */
setOnTouchListener(OnTouchListener l)4898     public void setOnTouchListener(OnTouchListener l) {
4899         getListenerInfo().mOnTouchListener = l;
4900     }
4901 
4902     /**
4903      * Register a callback to be invoked when a generic motion event is sent to this view.
4904      * @param l the generic motion listener to attach to this view
4905      */
setOnGenericMotionListener(OnGenericMotionListener l)4906     public void setOnGenericMotionListener(OnGenericMotionListener l) {
4907         getListenerInfo().mOnGenericMotionListener = l;
4908     }
4909 
4910     /**
4911      * Register a callback to be invoked when a hover event is sent to this view.
4912      * @param l the hover listener to attach to this view
4913      */
setOnHoverListener(OnHoverListener l)4914     public void setOnHoverListener(OnHoverListener l) {
4915         getListenerInfo().mOnHoverListener = l;
4916     }
4917 
4918     /**
4919      * Register a drag event listener callback object for this View. The parameter is
4920      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4921      * View, the system calls the
4922      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4923      * @param l An implementation of {@link android.view.View.OnDragListener}.
4924      */
setOnDragListener(OnDragListener l)4925     public void setOnDragListener(OnDragListener l) {
4926         getListenerInfo().mOnDragListener = l;
4927     }
4928 
4929     /**
4930      * Give this view focus. This will cause
4931      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4932      *
4933      * Note: this does not check whether this {@link View} should get focus, it just
4934      * gives it focus no matter what.  It should only be called internally by framework
4935      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4936      *
4937      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4938      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4939      *        focus moved when requestFocus() is called. It may not always
4940      *        apply, in which case use the default View.FOCUS_DOWN.
4941      * @param previouslyFocusedRect The rectangle of the view that had focus
4942      *        prior in this View's coordinate system.
4943      */
handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)4944     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4945         if (DBG) {
4946             System.out.println(this + " requestFocus()");
4947         }
4948 
4949         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4950             mPrivateFlags |= PFLAG_FOCUSED;
4951 
4952             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4953 
4954             if (mParent != null) {
4955                 mParent.requestChildFocus(this, this);
4956             }
4957 
4958             if (mAttachInfo != null) {
4959                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4960             }
4961 
4962             onFocusChanged(true, direction, previouslyFocusedRect);
4963             refreshDrawableState();
4964         }
4965     }
4966 
4967     /**
4968      * Populates <code>outRect</code> with the hotspot bounds. By default,
4969      * the hotspot bounds are identical to the screen bounds.
4970      *
4971      * @param outRect rect to populate with hotspot bounds
4972      * @hide Only for internal use by views and widgets.
4973      */
getHotspotBounds(Rect outRect)4974     public void getHotspotBounds(Rect outRect) {
4975         final Drawable background = getBackground();
4976         if (background != null) {
4977             background.getHotspotBounds(outRect);
4978         } else {
4979             getBoundsOnScreen(outRect);
4980         }
4981     }
4982 
4983     /**
4984      * Request that a rectangle of this view be visible on the screen,
4985      * scrolling if necessary just enough.
4986      *
4987      * <p>A View should call this if it maintains some notion of which part
4988      * of its content is interesting.  For example, a text editing view
4989      * should call this when its cursor moves.
4990      *
4991      * @param rectangle The rectangle.
4992      * @return Whether any parent scrolled.
4993      */
requestRectangleOnScreen(Rect rectangle)4994     public boolean requestRectangleOnScreen(Rect rectangle) {
4995         return requestRectangleOnScreen(rectangle, false);
4996     }
4997 
4998     /**
4999      * Request that a rectangle of this view be visible on the screen,
5000      * scrolling if necessary just enough.
5001      *
5002      * <p>A View should call this if it maintains some notion of which part
5003      * of its content is interesting.  For example, a text editing view
5004      * should call this when its cursor moves.
5005      *
5006      * <p>When <code>immediate</code> is set to true, scrolling will not be
5007      * animated.
5008      *
5009      * @param rectangle The rectangle.
5010      * @param immediate True to forbid animated scrolling, false otherwise
5011      * @return Whether any parent scrolled.
5012      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)5013     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5014         if (mParent == null) {
5015             return false;
5016         }
5017 
5018         View child = this;
5019 
5020         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5021         position.set(rectangle);
5022 
5023         ViewParent parent = mParent;
5024         boolean scrolled = false;
5025         while (parent != null) {
5026             rectangle.set((int) position.left, (int) position.top,
5027                     (int) position.right, (int) position.bottom);
5028 
5029             scrolled |= parent.requestChildRectangleOnScreen(child,
5030                     rectangle, immediate);
5031 
5032             if (!child.hasIdentityMatrix()) {
5033                 child.getMatrix().mapRect(position);
5034             }
5035 
5036             position.offset(child.mLeft, child.mTop);
5037 
5038             if (!(parent instanceof View)) {
5039                 break;
5040             }
5041 
5042             View parentView = (View) parent;
5043 
5044             position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5045 
5046             child = parentView;
5047             parent = child.getParent();
5048         }
5049 
5050         return scrolled;
5051     }
5052 
5053     /**
5054      * Called when this view wants to give up focus. If focus is cleared
5055      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5056      * <p>
5057      * <strong>Note:</strong> When a View clears focus the framework is trying
5058      * to give focus to the first focusable View from the top. Hence, if this
5059      * View is the first from the top that can take focus, then all callbacks
5060      * related to clearing focus will be invoked after which the framework will
5061      * give focus to this view.
5062      * </p>
5063      */
clearFocus()5064     public void clearFocus() {
5065         if (DBG) {
5066             System.out.println(this + " clearFocus()");
5067         }
5068 
5069         clearFocusInternal(null, true, true);
5070     }
5071 
5072     /**
5073      * Clears focus from the view, optionally propagating the change up through
5074      * the parent hierarchy and requesting that the root view place new focus.
5075      *
5076      * @param propagate whether to propagate the change up through the parent
5077      *            hierarchy
5078      * @param refocus when propagate is true, specifies whether to request the
5079      *            root view place new focus
5080      */
clearFocusInternal(View focused, boolean propagate, boolean refocus)5081     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5082         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5083             mPrivateFlags &= ~PFLAG_FOCUSED;
5084 
5085             if (propagate && mParent != null) {
5086                 mParent.clearChildFocus(this);
5087             }
5088 
5089             onFocusChanged(false, 0, null);
5090             refreshDrawableState();
5091 
5092             if (propagate && (!refocus || !rootViewRequestFocus())) {
5093                 notifyGlobalFocusCleared(this);
5094             }
5095         }
5096     }
5097 
notifyGlobalFocusCleared(View oldFocus)5098     void notifyGlobalFocusCleared(View oldFocus) {
5099         if (oldFocus != null && mAttachInfo != null) {
5100             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5101         }
5102     }
5103 
rootViewRequestFocus()5104     boolean rootViewRequestFocus() {
5105         final View root = getRootView();
5106         return root != null && root.requestFocus();
5107     }
5108 
5109     /**
5110      * Called internally by the view system when a new view is getting focus.
5111      * This is what clears the old focus.
5112      * <p>
5113      * <b>NOTE:</b> The parent view's focused child must be updated manually
5114      * after calling this method. Otherwise, the view hierarchy may be left in
5115      * an inconstent state.
5116      */
unFocus(View focused)5117     void unFocus(View focused) {
5118         if (DBG) {
5119             System.out.println(this + " unFocus()");
5120         }
5121 
5122         clearFocusInternal(focused, false, false);
5123     }
5124 
5125     /**
5126      * Returns true if this view has focus iteself, or is the ancestor of the
5127      * view that has focus.
5128      *
5129      * @return True if this view has or contains focus, false otherwise.
5130      */
5131     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()5132     public boolean hasFocus() {
5133         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5134     }
5135 
5136     /**
5137      * Returns true if this view is focusable or if it contains a reachable View
5138      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5139      * is a View whose parents do not block descendants focus.
5140      *
5141      * Only {@link #VISIBLE} views are considered focusable.
5142      *
5143      * @return True if the view is focusable or if the view contains a focusable
5144      *         View, false otherwise.
5145      *
5146      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5147      * @see ViewGroup#getTouchscreenBlocksFocus()
5148      */
hasFocusable()5149     public boolean hasFocusable() {
5150         if (!isFocusableInTouchMode()) {
5151             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5152                 final ViewGroup g = (ViewGroup) p;
5153                 if (g.shouldBlockFocusForTouchscreen()) {
5154                     return false;
5155                 }
5156             }
5157         }
5158         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5159     }
5160 
5161     /**
5162      * Called by the view system when the focus state of this view changes.
5163      * When the focus change event is caused by directional navigation, direction
5164      * and previouslyFocusedRect provide insight into where the focus is coming from.
5165      * When overriding, be sure to call up through to the super class so that
5166      * the standard focus handling will occur.
5167      *
5168      * @param gainFocus True if the View has focus; false otherwise.
5169      * @param direction The direction focus has moved when requestFocus()
5170      *                  is called to give this view focus. Values are
5171      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5172      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5173      *                  It may not always apply, in which case use the default.
5174      * @param previouslyFocusedRect The rectangle, in this view's coordinate
5175      *        system, of the previously focused view.  If applicable, this will be
5176      *        passed in as finer grained information about where the focus is coming
5177      *        from (in addition to direction).  Will be <code>null</code> otherwise.
5178      */
onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)5179     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5180             @Nullable Rect previouslyFocusedRect) {
5181         if (gainFocus) {
5182             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5183         } else {
5184             notifyViewAccessibilityStateChangedIfNeeded(
5185                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5186         }
5187 
5188         InputMethodManager imm = InputMethodManager.peekInstance();
5189         if (!gainFocus) {
5190             if (isPressed()) {
5191                 setPressed(false);
5192             }
5193             if (imm != null && mAttachInfo != null
5194                     && mAttachInfo.mHasWindowFocus) {
5195                 imm.focusOut(this);
5196             }
5197             onFocusLost();
5198         } else if (imm != null && mAttachInfo != null
5199                 && mAttachInfo.mHasWindowFocus) {
5200             imm.focusIn(this);
5201         }
5202 
5203         invalidate(true);
5204         ListenerInfo li = mListenerInfo;
5205         if (li != null && li.mOnFocusChangeListener != null) {
5206             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5207         }
5208 
5209         if (mAttachInfo != null) {
5210             mAttachInfo.mKeyDispatchState.reset(this);
5211         }
5212     }
5213 
5214     /**
5215      * Sends an accessibility event of the given type. If accessibility is
5216      * not enabled this method has no effect. The default implementation calls
5217      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5218      * to populate information about the event source (this View), then calls
5219      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5220      * populate the text content of the event source including its descendants,
5221      * and last calls
5222      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5223      * on its parent to resuest sending of the event to interested parties.
5224      * <p>
5225      * If an {@link AccessibilityDelegate} has been specified via calling
5226      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5227      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5228      * responsible for handling this call.
5229      * </p>
5230      *
5231      * @param eventType The type of the event to send, as defined by several types from
5232      * {@link android.view.accessibility.AccessibilityEvent}, such as
5233      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5234      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5235      *
5236      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5237      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5238      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5239      * @see AccessibilityDelegate
5240      */
sendAccessibilityEvent(int eventType)5241     public void sendAccessibilityEvent(int eventType) {
5242         if (mAccessibilityDelegate != null) {
5243             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5244         } else {
5245             sendAccessibilityEventInternal(eventType);
5246         }
5247     }
5248 
5249     /**
5250      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5251      * {@link AccessibilityEvent} to make an announcement which is related to some
5252      * sort of a context change for which none of the events representing UI transitions
5253      * is a good fit. For example, announcing a new page in a book. If accessibility
5254      * is not enabled this method does nothing.
5255      *
5256      * @param text The announcement text.
5257      */
announceForAccessibility(CharSequence text)5258     public void announceForAccessibility(CharSequence text) {
5259         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5260             AccessibilityEvent event = AccessibilityEvent.obtain(
5261                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
5262             onInitializeAccessibilityEvent(event);
5263             event.getText().add(text);
5264             event.setContentDescription(null);
5265             mParent.requestSendAccessibilityEvent(this, event);
5266         }
5267     }
5268 
5269     /**
5270      * @see #sendAccessibilityEvent(int)
5271      *
5272      * Note: Called from the default {@link AccessibilityDelegate}.
5273      */
sendAccessibilityEventInternal(int eventType)5274     void sendAccessibilityEventInternal(int eventType) {
5275         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5276             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5277         }
5278     }
5279 
5280     /**
5281      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5282      * takes as an argument an empty {@link AccessibilityEvent} and does not
5283      * perform a check whether accessibility is enabled.
5284      * <p>
5285      * If an {@link AccessibilityDelegate} has been specified via calling
5286      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5287      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5288      * is responsible for handling this call.
5289      * </p>
5290      *
5291      * @param event The event to send.
5292      *
5293      * @see #sendAccessibilityEvent(int)
5294      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)5295     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5296         if (mAccessibilityDelegate != null) {
5297             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5298         } else {
5299             sendAccessibilityEventUncheckedInternal(event);
5300         }
5301     }
5302 
5303     /**
5304      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5305      *
5306      * Note: Called from the default {@link AccessibilityDelegate}.
5307      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)5308     void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5309         if (!isShown()) {
5310             return;
5311         }
5312         onInitializeAccessibilityEvent(event);
5313         // Only a subset of accessibility events populates text content.
5314         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5315             dispatchPopulateAccessibilityEvent(event);
5316         }
5317         // In the beginning we called #isShown(), so we know that getParent() is not null.
5318         getParent().requestSendAccessibilityEvent(this, event);
5319     }
5320 
5321     /**
5322      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5323      * to its children for adding their text content to the event. Note that the
5324      * event text is populated in a separate dispatch path since we add to the
5325      * event not only the text of the source but also the text of all its descendants.
5326      * A typical implementation will call
5327      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5328      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5329      * on each child. Override this method if custom population of the event text
5330      * content is required.
5331      * <p>
5332      * If an {@link AccessibilityDelegate} has been specified via calling
5333      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5334      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5335      * is responsible for handling this call.
5336      * </p>
5337      * <p>
5338      * <em>Note:</em> Accessibility events of certain types are not dispatched for
5339      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5340      * </p>
5341      *
5342      * @param event The event.
5343      *
5344      * @return True if the event population was completed.
5345      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)5346     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5347         if (mAccessibilityDelegate != null) {
5348             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5349         } else {
5350             return dispatchPopulateAccessibilityEventInternal(event);
5351         }
5352     }
5353 
5354     /**
5355      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5356      *
5357      * Note: Called from the default {@link AccessibilityDelegate}.
5358      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)5359     boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5360         onPopulateAccessibilityEvent(event);
5361         return false;
5362     }
5363 
5364     /**
5365      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5366      * giving a chance to this View to populate the accessibility event with its
5367      * text content. While this method is free to modify event
5368      * attributes other than text content, doing so should normally be performed in
5369      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5370      * <p>
5371      * Example: Adding formatted date string to an accessibility event in addition
5372      *          to the text added by the super implementation:
5373      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5374      *     super.onPopulateAccessibilityEvent(event);
5375      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5376      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5377      *         mCurrentDate.getTimeInMillis(), flags);
5378      *     event.getText().add(selectedDateUtterance);
5379      * }</pre>
5380      * <p>
5381      * If an {@link AccessibilityDelegate} has been specified via calling
5382      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5383      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5384      * is responsible for handling this call.
5385      * </p>
5386      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5387      * information to the event, in case the default implementation has basic information to add.
5388      * </p>
5389      *
5390      * @param event The accessibility event which to populate.
5391      *
5392      * @see #sendAccessibilityEvent(int)
5393      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5394      */
onPopulateAccessibilityEvent(AccessibilityEvent event)5395     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5396         if (mAccessibilityDelegate != null) {
5397             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5398         } else {
5399             onPopulateAccessibilityEventInternal(event);
5400         }
5401     }
5402 
5403     /**
5404      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5405      *
5406      * Note: Called from the default {@link AccessibilityDelegate}.
5407      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)5408     void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5409     }
5410 
5411     /**
5412      * Initializes an {@link AccessibilityEvent} with information about
5413      * this View which is the event source. In other words, the source of
5414      * an accessibility event is the view whose state change triggered firing
5415      * the event.
5416      * <p>
5417      * Example: Setting the password property of an event in addition
5418      *          to properties set by the super implementation:
5419      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5420      *     super.onInitializeAccessibilityEvent(event);
5421      *     event.setPassword(true);
5422      * }</pre>
5423      * <p>
5424      * If an {@link AccessibilityDelegate} has been specified via calling
5425      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5426      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5427      * is responsible for handling this call.
5428      * </p>
5429      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5430      * information to the event, in case the default implementation has basic information to add.
5431      * </p>
5432      * @param event The event to initialize.
5433      *
5434      * @see #sendAccessibilityEvent(int)
5435      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5436      */
onInitializeAccessibilityEvent(AccessibilityEvent event)5437     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5438         if (mAccessibilityDelegate != null) {
5439             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5440         } else {
5441             onInitializeAccessibilityEventInternal(event);
5442         }
5443     }
5444 
5445     /**
5446      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5447      *
5448      * Note: Called from the default {@link AccessibilityDelegate}.
5449      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)5450     void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5451         event.setSource(this);
5452         event.setClassName(View.class.getName());
5453         event.setPackageName(getContext().getPackageName());
5454         event.setEnabled(isEnabled());
5455         event.setContentDescription(mContentDescription);
5456 
5457         switch (event.getEventType()) {
5458             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5459                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
5460                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5461                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5462                 event.setItemCount(focusablesTempList.size());
5463                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5464                 if (mAttachInfo != null) {
5465                     focusablesTempList.clear();
5466                 }
5467             } break;
5468             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5469                 CharSequence text = getIterableTextForAccessibility();
5470                 if (text != null && text.length() > 0) {
5471                     event.setFromIndex(getAccessibilitySelectionStart());
5472                     event.setToIndex(getAccessibilitySelectionEnd());
5473                     event.setItemCount(text.length());
5474                 }
5475             } break;
5476         }
5477     }
5478 
5479     /**
5480      * Returns an {@link AccessibilityNodeInfo} representing this view from the
5481      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5482      * This method is responsible for obtaining an accessibility node info from a
5483      * pool of reusable instances and calling
5484      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5485      * initialize the former.
5486      * <p>
5487      * Note: The client is responsible for recycling the obtained instance by calling
5488      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5489      * </p>
5490      *
5491      * @return A populated {@link AccessibilityNodeInfo}.
5492      *
5493      * @see AccessibilityNodeInfo
5494      */
createAccessibilityNodeInfo()5495     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5496         if (mAccessibilityDelegate != null) {
5497             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5498         } else {
5499             return createAccessibilityNodeInfoInternal();
5500         }
5501     }
5502 
5503     /**
5504      * @see #createAccessibilityNodeInfo()
5505      */
createAccessibilityNodeInfoInternal()5506     AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5507         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5508         if (provider != null) {
5509             return provider.createAccessibilityNodeInfo(View.NO_ID);
5510         } else {
5511             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5512             onInitializeAccessibilityNodeInfo(info);
5513             return info;
5514         }
5515     }
5516 
5517     /**
5518      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5519      * The base implementation sets:
5520      * <ul>
5521      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5522      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5523      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5524      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5525      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5526      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5527      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5528      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5529      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5530      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5531      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5532      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5533      * </ul>
5534      * <p>
5535      * Subclasses should override this method, call the super implementation,
5536      * and set additional attributes.
5537      * </p>
5538      * <p>
5539      * If an {@link AccessibilityDelegate} has been specified via calling
5540      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5541      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5542      * is responsible for handling this call.
5543      * </p>
5544      *
5545      * @param info The instance to initialize.
5546      */
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)5547     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5548         if (mAccessibilityDelegate != null) {
5549             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5550         } else {
5551             onInitializeAccessibilityNodeInfoInternal(info);
5552         }
5553     }
5554 
5555     /**
5556      * Gets the location of this view in screen coordinates.
5557      *
5558      * @param outRect The output location
5559      * @hide
5560      */
getBoundsOnScreen(Rect outRect)5561     public void getBoundsOnScreen(Rect outRect) {
5562         getBoundsOnScreen(outRect, false);
5563     }
5564 
5565     /**
5566      * Gets the location of this view in screen coordinates.
5567      *
5568      * @param outRect The output location
5569      * @param clipToParent Whether to clip child bounds to the parent ones.
5570      * @hide
5571      */
getBoundsOnScreen(Rect outRect, boolean clipToParent)5572     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
5573         if (mAttachInfo == null) {
5574             return;
5575         }
5576 
5577         RectF position = mAttachInfo.mTmpTransformRect;
5578         position.set(0, 0, mRight - mLeft, mBottom - mTop);
5579 
5580         if (!hasIdentityMatrix()) {
5581             getMatrix().mapRect(position);
5582         }
5583 
5584         position.offset(mLeft, mTop);
5585 
5586         ViewParent parent = mParent;
5587         while (parent instanceof View) {
5588             View parentView = (View) parent;
5589 
5590             position.offset(-parentView.mScrollX, -parentView.mScrollY);
5591 
5592             if (clipToParent) {
5593                 position.left = Math.max(position.left, 0);
5594                 position.top = Math.max(position.top, 0);
5595                 position.right = Math.min(position.right, parentView.getWidth());
5596                 position.bottom = Math.min(position.bottom, parentView.getHeight());
5597             }
5598 
5599             if (!parentView.hasIdentityMatrix()) {
5600                 parentView.getMatrix().mapRect(position);
5601             }
5602 
5603             position.offset(parentView.mLeft, parentView.mTop);
5604 
5605             parent = parentView.mParent;
5606         }
5607 
5608         if (parent instanceof ViewRootImpl) {
5609             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5610             position.offset(0, -viewRootImpl.mCurScrollY);
5611         }
5612 
5613         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5614 
5615         outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5616                 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5617     }
5618 
5619     /**
5620      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5621      *
5622      * Note: Called from the default {@link AccessibilityDelegate}.
5623      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)5624     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5625         Rect bounds = mAttachInfo.mTmpInvalRect;
5626 
5627         getDrawingRect(bounds);
5628         info.setBoundsInParent(bounds);
5629 
5630         getBoundsOnScreen(bounds, true);
5631         info.setBoundsInScreen(bounds);
5632 
5633         ViewParent parent = getParentForAccessibility();
5634         if (parent instanceof View) {
5635             info.setParent((View) parent);
5636         }
5637 
5638         if (mID != View.NO_ID) {
5639             View rootView = getRootView();
5640             if (rootView == null) {
5641                 rootView = this;
5642             }
5643 
5644             View label = rootView.findLabelForView(this, mID);
5645             if (label != null) {
5646                 info.setLabeledBy(label);
5647             }
5648 
5649             if ((mAttachInfo.mAccessibilityFetchFlags
5650                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5651                     && Resources.resourceHasPackage(mID)) {
5652                 try {
5653                     String viewId = getResources().getResourceName(mID);
5654                     info.setViewIdResourceName(viewId);
5655                 } catch (Resources.NotFoundException nfe) {
5656                     /* ignore */
5657                 }
5658             }
5659         }
5660 
5661         if (mLabelForId != View.NO_ID) {
5662             View rootView = getRootView();
5663             if (rootView == null) {
5664                 rootView = this;
5665             }
5666             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5667             if (labeled != null) {
5668                 info.setLabelFor(labeled);
5669             }
5670         }
5671 
5672         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
5673             View rootView = getRootView();
5674             if (rootView == null) {
5675                 rootView = this;
5676             }
5677             View next = rootView.findViewInsideOutShouldExist(this,
5678                     mAccessibilityTraversalBeforeId);
5679             if (next != null) {
5680                 info.setTraversalBefore(next);
5681             }
5682         }
5683 
5684         if (mAccessibilityTraversalAfterId != View.NO_ID) {
5685             View rootView = getRootView();
5686             if (rootView == null) {
5687                 rootView = this;
5688             }
5689             View next = rootView.findViewInsideOutShouldExist(this,
5690                     mAccessibilityTraversalAfterId);
5691             if (next != null) {
5692                 info.setTraversalAfter(next);
5693             }
5694         }
5695 
5696         info.setVisibleToUser(isVisibleToUser());
5697 
5698         info.setPackageName(mContext.getPackageName());
5699         info.setClassName(View.class.getName());
5700         info.setContentDescription(getContentDescription());
5701 
5702         info.setEnabled(isEnabled());
5703         info.setClickable(isClickable());
5704         info.setFocusable(isFocusable());
5705         info.setFocused(isFocused());
5706         info.setAccessibilityFocused(isAccessibilityFocused());
5707         info.setSelected(isSelected());
5708         info.setLongClickable(isLongClickable());
5709         info.setLiveRegion(getAccessibilityLiveRegion());
5710 
5711         // TODO: These make sense only if we are in an AdapterView but all
5712         // views can be selected. Maybe from accessibility perspective
5713         // we should report as selectable view in an AdapterView.
5714         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5715         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5716 
5717         if (isFocusable()) {
5718             if (isFocused()) {
5719                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5720             } else {
5721                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5722             }
5723         }
5724 
5725         if (!isAccessibilityFocused()) {
5726             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5727         } else {
5728             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5729         }
5730 
5731         if (isClickable() && isEnabled()) {
5732             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5733         }
5734 
5735         if (isLongClickable() && isEnabled()) {
5736             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5737         }
5738 
5739         CharSequence text = getIterableTextForAccessibility();
5740         if (text != null && text.length() > 0) {
5741             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5742 
5743             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5744             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5745             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5746             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5747                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5748                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5749         }
5750     }
5751 
findLabelForView(View view, int labeledId)5752     private View findLabelForView(View view, int labeledId) {
5753         if (mMatchLabelForPredicate == null) {
5754             mMatchLabelForPredicate = new MatchLabelForPredicate();
5755         }
5756         mMatchLabelForPredicate.mLabeledId = labeledId;
5757         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5758     }
5759 
5760     /**
5761      * Computes whether this view is visible to the user. Such a view is
5762      * attached, visible, all its predecessors are visible, it is not clipped
5763      * entirely by its predecessors, and has an alpha greater than zero.
5764      *
5765      * @return Whether the view is visible on the screen.
5766      *
5767      * @hide
5768      */
isVisibleToUser()5769     protected boolean isVisibleToUser() {
5770         return isVisibleToUser(null);
5771     }
5772 
5773     /**
5774      * Computes whether the given portion of this view is visible to the user.
5775      * Such a view is attached, visible, all its predecessors are visible,
5776      * has an alpha greater than zero, and the specified portion is not
5777      * clipped entirely by its predecessors.
5778      *
5779      * @param boundInView the portion of the view to test; coordinates should be relative; may be
5780      *                    <code>null</code>, and the entire view will be tested in this case.
5781      *                    When <code>true</code> is returned by the function, the actual visible
5782      *                    region will be stored in this parameter; that is, if boundInView is fully
5783      *                    contained within the view, no modification will be made, otherwise regions
5784      *                    outside of the visible area of the view will be clipped.
5785      *
5786      * @return Whether the specified portion of the view is visible on the screen.
5787      *
5788      * @hide
5789      */
isVisibleToUser(Rect boundInView)5790     protected boolean isVisibleToUser(Rect boundInView) {
5791         if (mAttachInfo != null) {
5792             // Attached to invisible window means this view is not visible.
5793             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5794                 return false;
5795             }
5796             // An invisible predecessor or one with alpha zero means
5797             // that this view is not visible to the user.
5798             Object current = this;
5799             while (current instanceof View) {
5800                 View view = (View) current;
5801                 // We have attach info so this view is attached and there is no
5802                 // need to check whether we reach to ViewRootImpl on the way up.
5803                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
5804                         view.getVisibility() != VISIBLE) {
5805                     return false;
5806                 }
5807                 current = view.mParent;
5808             }
5809             // Check if the view is entirely covered by its predecessors.
5810             Rect visibleRect = mAttachInfo.mTmpInvalRect;
5811             Point offset = mAttachInfo.mPoint;
5812             if (!getGlobalVisibleRect(visibleRect, offset)) {
5813                 return false;
5814             }
5815             // Check if the visible portion intersects the rectangle of interest.
5816             if (boundInView != null) {
5817                 visibleRect.offset(-offset.x, -offset.y);
5818                 return boundInView.intersect(visibleRect);
5819             }
5820             return true;
5821         }
5822         return false;
5823     }
5824 
5825     /**
5826      * Returns the delegate for implementing accessibility support via
5827      * composition. For more details see {@link AccessibilityDelegate}.
5828      *
5829      * @return The delegate, or null if none set.
5830      *
5831      * @hide
5832      */
getAccessibilityDelegate()5833     public AccessibilityDelegate getAccessibilityDelegate() {
5834         return mAccessibilityDelegate;
5835     }
5836 
5837     /**
5838      * Sets a delegate for implementing accessibility support via composition as
5839      * opposed to inheritance. The delegate's primary use is for implementing
5840      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5841      *
5842      * @param delegate The delegate instance.
5843      *
5844      * @see AccessibilityDelegate
5845      */
setAccessibilityDelegate(AccessibilityDelegate delegate)5846     public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5847         mAccessibilityDelegate = delegate;
5848     }
5849 
5850     /**
5851      * Gets the provider for managing a virtual view hierarchy rooted at this View
5852      * and reported to {@link android.accessibilityservice.AccessibilityService}s
5853      * that explore the window content.
5854      * <p>
5855      * If this method returns an instance, this instance is responsible for managing
5856      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5857      * View including the one representing the View itself. Similarly the returned
5858      * instance is responsible for performing accessibility actions on any virtual
5859      * view or the root view itself.
5860      * </p>
5861      * <p>
5862      * If an {@link AccessibilityDelegate} has been specified via calling
5863      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5864      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5865      * is responsible for handling this call.
5866      * </p>
5867      *
5868      * @return The provider.
5869      *
5870      * @see AccessibilityNodeProvider
5871      */
getAccessibilityNodeProvider()5872     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5873         if (mAccessibilityDelegate != null) {
5874             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5875         } else {
5876             return null;
5877         }
5878     }
5879 
5880     /**
5881      * Gets the unique identifier of this view on the screen for accessibility purposes.
5882      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5883      *
5884      * @return The view accessibility id.
5885      *
5886      * @hide
5887      */
getAccessibilityViewId()5888     public int getAccessibilityViewId() {
5889         if (mAccessibilityViewId == NO_ID) {
5890             mAccessibilityViewId = sNextAccessibilityViewId++;
5891         }
5892         return mAccessibilityViewId;
5893     }
5894 
5895     /**
5896      * Gets the unique identifier of the window in which this View reseides.
5897      *
5898      * @return The window accessibility id.
5899      *
5900      * @hide
5901      */
getAccessibilityWindowId()5902     public int getAccessibilityWindowId() {
5903         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
5904                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
5905     }
5906 
5907     /**
5908      * Gets the {@link View} description. It briefly describes the view and is
5909      * primarily used for accessibility support. Set this property to enable
5910      * better accessibility support for your application. This is especially
5911      * true for views that do not have textual representation (For example,
5912      * ImageButton).
5913      *
5914      * @return The content description.
5915      *
5916      * @attr ref android.R.styleable#View_contentDescription
5917      */
5918     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()5919     public CharSequence getContentDescription() {
5920         return mContentDescription;
5921     }
5922 
5923     /**
5924      * Sets the {@link View} description. It briefly describes the view and is
5925      * primarily used for accessibility support. Set this property to enable
5926      * better accessibility support for your application. This is especially
5927      * true for views that do not have textual representation (For example,
5928      * ImageButton).
5929      *
5930      * @param contentDescription The content description.
5931      *
5932      * @attr ref android.R.styleable#View_contentDescription
5933      */
5934     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)5935     public void setContentDescription(CharSequence contentDescription) {
5936         if (mContentDescription == null) {
5937             if (contentDescription == null) {
5938                 return;
5939             }
5940         } else if (mContentDescription.equals(contentDescription)) {
5941             return;
5942         }
5943         mContentDescription = contentDescription;
5944         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5945         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5946             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5947             notifySubtreeAccessibilityStateChangedIfNeeded();
5948         } else {
5949             notifyViewAccessibilityStateChangedIfNeeded(
5950                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
5951         }
5952     }
5953 
5954     /**
5955      * Sets the id of a view before which this one is visited in accessibility traversal.
5956      * A screen-reader must visit the content of this view before the content of the one
5957      * it precedes. For example, if view B is set to be before view A, then a screen-reader
5958      * will traverse the entire content of B before traversing the entire content of A,
5959      * regardles of what traversal strategy it is using.
5960      * <p>
5961      * Views that do not have specified before/after relationships are traversed in order
5962      * determined by the screen-reader.
5963      * </p>
5964      * <p>
5965      * Setting that this view is before a view that is not important for accessibility
5966      * or if this view is not important for accessibility will have no effect as the
5967      * screen-reader is not aware of unimportant views.
5968      * </p>
5969      *
5970      * @param beforeId The id of a view this one precedes in accessibility traversal.
5971      *
5972      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
5973      *
5974      * @see #setImportantForAccessibility(int)
5975      */
5976     @RemotableViewMethod
setAccessibilityTraversalBefore(int beforeId)5977     public void setAccessibilityTraversalBefore(int beforeId) {
5978         if (mAccessibilityTraversalBeforeId == beforeId) {
5979             return;
5980         }
5981         mAccessibilityTraversalBeforeId = beforeId;
5982         notifyViewAccessibilityStateChangedIfNeeded(
5983                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5984     }
5985 
5986     /**
5987      * Gets the id of a view before which this one is visited in accessibility traversal.
5988      *
5989      * @return The id of a view this one precedes in accessibility traversal if
5990      *         specified, otherwise {@link #NO_ID}.
5991      *
5992      * @see #setAccessibilityTraversalBefore(int)
5993      */
getAccessibilityTraversalBefore()5994     public int getAccessibilityTraversalBefore() {
5995         return mAccessibilityTraversalBeforeId;
5996     }
5997 
5998     /**
5999      * Sets the id of a view after which this one is visited in accessibility traversal.
6000      * A screen-reader must visit the content of the other view before the content of this
6001      * one. For example, if view B is set to be after view A, then a screen-reader
6002      * will traverse the entire content of A before traversing the entire content of B,
6003      * regardles of what traversal strategy it is using.
6004      * <p>
6005      * Views that do not have specified before/after relationships are traversed in order
6006      * determined by the screen-reader.
6007      * </p>
6008      * <p>
6009      * Setting that this view is after a view that is not important for accessibility
6010      * or if this view is not important for accessibility will have no effect as the
6011      * screen-reader is not aware of unimportant views.
6012      * </p>
6013      *
6014      * @param afterId The id of a view this one succedees in accessibility traversal.
6015      *
6016      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6017      *
6018      * @see #setImportantForAccessibility(int)
6019      */
6020     @RemotableViewMethod
setAccessibilityTraversalAfter(int afterId)6021     public void setAccessibilityTraversalAfter(int afterId) {
6022         if (mAccessibilityTraversalAfterId == afterId) {
6023             return;
6024         }
6025         mAccessibilityTraversalAfterId = afterId;
6026         notifyViewAccessibilityStateChangedIfNeeded(
6027                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6028     }
6029 
6030     /**
6031      * Gets the id of a view after which this one is visited in accessibility traversal.
6032      *
6033      * @return The id of a view this one succeedes in accessibility traversal if
6034      *         specified, otherwise {@link #NO_ID}.
6035      *
6036      * @see #setAccessibilityTraversalAfter(int)
6037      */
getAccessibilityTraversalAfter()6038     public int getAccessibilityTraversalAfter() {
6039         return mAccessibilityTraversalAfterId;
6040     }
6041 
6042     /**
6043      * Gets the id of a view for which this view serves as a label for
6044      * accessibility purposes.
6045      *
6046      * @return The labeled view id.
6047      */
6048     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()6049     public int getLabelFor() {
6050         return mLabelForId;
6051     }
6052 
6053     /**
6054      * Sets the id of a view for which this view serves as a label for
6055      * accessibility purposes.
6056      *
6057      * @param id The labeled view id.
6058      */
6059     @RemotableViewMethod
setLabelFor(int id)6060     public void setLabelFor(int id) {
6061         if (mLabelForId == id) {
6062             return;
6063         }
6064         mLabelForId = id;
6065         if (mLabelForId != View.NO_ID
6066                 && mID == View.NO_ID) {
6067             mID = generateViewId();
6068         }
6069         notifyViewAccessibilityStateChangedIfNeeded(
6070                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6071     }
6072 
6073     /**
6074      * Invoked whenever this view loses focus, either by losing window focus or by losing
6075      * focus within its window. This method can be used to clear any state tied to the
6076      * focus. For instance, if a button is held pressed with the trackball and the window
6077      * loses focus, this method can be used to cancel the press.
6078      *
6079      * Subclasses of View overriding this method should always call super.onFocusLost().
6080      *
6081      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6082      * @see #onWindowFocusChanged(boolean)
6083      *
6084      * @hide pending API council approval
6085      */
onFocusLost()6086     protected void onFocusLost() {
6087         resetPressedState();
6088     }
6089 
resetPressedState()6090     private void resetPressedState() {
6091         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6092             return;
6093         }
6094 
6095         if (isPressed()) {
6096             setPressed(false);
6097 
6098             if (!mHasPerformedLongPress) {
6099                 removeLongPressCallback();
6100             }
6101         }
6102     }
6103 
6104     /**
6105      * Returns true if this view has focus
6106      *
6107      * @return True if this view has focus, false otherwise.
6108      */
6109     @ViewDebug.ExportedProperty(category = "focus")
isFocused()6110     public boolean isFocused() {
6111         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6112     }
6113 
6114     /**
6115      * Find the view in the hierarchy rooted at this view that currently has
6116      * focus.
6117      *
6118      * @return The view that currently has focus, or null if no focused view can
6119      *         be found.
6120      */
findFocus()6121     public View findFocus() {
6122         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6123     }
6124 
6125     /**
6126      * Indicates whether this view is one of the set of scrollable containers in
6127      * its window.
6128      *
6129      * @return whether this view is one of the set of scrollable containers in
6130      * its window
6131      *
6132      * @attr ref android.R.styleable#View_isScrollContainer
6133      */
isScrollContainer()6134     public boolean isScrollContainer() {
6135         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6136     }
6137 
6138     /**
6139      * Change whether this view is one of the set of scrollable containers in
6140      * its window.  This will be used to determine whether the window can
6141      * resize or must pan when a soft input area is open -- scrollable
6142      * containers allow the window to use resize mode since the container
6143      * will appropriately shrink.
6144      *
6145      * @attr ref android.R.styleable#View_isScrollContainer
6146      */
setScrollContainer(boolean isScrollContainer)6147     public void setScrollContainer(boolean isScrollContainer) {
6148         if (isScrollContainer) {
6149             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6150                 mAttachInfo.mScrollContainers.add(this);
6151                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6152             }
6153             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6154         } else {
6155             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6156                 mAttachInfo.mScrollContainers.remove(this);
6157             }
6158             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6159         }
6160     }
6161 
6162     /**
6163      * Returns the quality of the drawing cache.
6164      *
6165      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6166      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6167      *
6168      * @see #setDrawingCacheQuality(int)
6169      * @see #setDrawingCacheEnabled(boolean)
6170      * @see #isDrawingCacheEnabled()
6171      *
6172      * @attr ref android.R.styleable#View_drawingCacheQuality
6173      */
6174     @DrawingCacheQuality
getDrawingCacheQuality()6175     public int getDrawingCacheQuality() {
6176         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6177     }
6178 
6179     /**
6180      * Set the drawing cache quality of this view. This value is used only when the
6181      * drawing cache is enabled
6182      *
6183      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6184      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6185      *
6186      * @see #getDrawingCacheQuality()
6187      * @see #setDrawingCacheEnabled(boolean)
6188      * @see #isDrawingCacheEnabled()
6189      *
6190      * @attr ref android.R.styleable#View_drawingCacheQuality
6191      */
setDrawingCacheQuality(@rawingCacheQuality int quality)6192     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6193         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6194     }
6195 
6196     /**
6197      * Returns whether the screen should remain on, corresponding to the current
6198      * value of {@link #KEEP_SCREEN_ON}.
6199      *
6200      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6201      *
6202      * @see #setKeepScreenOn(boolean)
6203      *
6204      * @attr ref android.R.styleable#View_keepScreenOn
6205      */
getKeepScreenOn()6206     public boolean getKeepScreenOn() {
6207         return (mViewFlags & KEEP_SCREEN_ON) != 0;
6208     }
6209 
6210     /**
6211      * Controls whether the screen should remain on, modifying the
6212      * value of {@link #KEEP_SCREEN_ON}.
6213      *
6214      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6215      *
6216      * @see #getKeepScreenOn()
6217      *
6218      * @attr ref android.R.styleable#View_keepScreenOn
6219      */
setKeepScreenOn(boolean keepScreenOn)6220     public void setKeepScreenOn(boolean keepScreenOn) {
6221         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6222     }
6223 
6224     /**
6225      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6226      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6227      *
6228      * @attr ref android.R.styleable#View_nextFocusLeft
6229      */
getNextFocusLeftId()6230     public int getNextFocusLeftId() {
6231         return mNextFocusLeftId;
6232     }
6233 
6234     /**
6235      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6236      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6237      * decide automatically.
6238      *
6239      * @attr ref android.R.styleable#View_nextFocusLeft
6240      */
setNextFocusLeftId(int nextFocusLeftId)6241     public void setNextFocusLeftId(int nextFocusLeftId) {
6242         mNextFocusLeftId = nextFocusLeftId;
6243     }
6244 
6245     /**
6246      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6247      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6248      *
6249      * @attr ref android.R.styleable#View_nextFocusRight
6250      */
getNextFocusRightId()6251     public int getNextFocusRightId() {
6252         return mNextFocusRightId;
6253     }
6254 
6255     /**
6256      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6257      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6258      * decide automatically.
6259      *
6260      * @attr ref android.R.styleable#View_nextFocusRight
6261      */
setNextFocusRightId(int nextFocusRightId)6262     public void setNextFocusRightId(int nextFocusRightId) {
6263         mNextFocusRightId = nextFocusRightId;
6264     }
6265 
6266     /**
6267      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6268      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6269      *
6270      * @attr ref android.R.styleable#View_nextFocusUp
6271      */
getNextFocusUpId()6272     public int getNextFocusUpId() {
6273         return mNextFocusUpId;
6274     }
6275 
6276     /**
6277      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6278      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6279      * decide automatically.
6280      *
6281      * @attr ref android.R.styleable#View_nextFocusUp
6282      */
setNextFocusUpId(int nextFocusUpId)6283     public void setNextFocusUpId(int nextFocusUpId) {
6284         mNextFocusUpId = nextFocusUpId;
6285     }
6286 
6287     /**
6288      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6289      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6290      *
6291      * @attr ref android.R.styleable#View_nextFocusDown
6292      */
getNextFocusDownId()6293     public int getNextFocusDownId() {
6294         return mNextFocusDownId;
6295     }
6296 
6297     /**
6298      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6299      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6300      * decide automatically.
6301      *
6302      * @attr ref android.R.styleable#View_nextFocusDown
6303      */
setNextFocusDownId(int nextFocusDownId)6304     public void setNextFocusDownId(int nextFocusDownId) {
6305         mNextFocusDownId = nextFocusDownId;
6306     }
6307 
6308     /**
6309      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6310      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6311      *
6312      * @attr ref android.R.styleable#View_nextFocusForward
6313      */
getNextFocusForwardId()6314     public int getNextFocusForwardId() {
6315         return mNextFocusForwardId;
6316     }
6317 
6318     /**
6319      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6320      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6321      * decide automatically.
6322      *
6323      * @attr ref android.R.styleable#View_nextFocusForward
6324      */
setNextFocusForwardId(int nextFocusForwardId)6325     public void setNextFocusForwardId(int nextFocusForwardId) {
6326         mNextFocusForwardId = nextFocusForwardId;
6327     }
6328 
6329     /**
6330      * Returns the visibility of this view and all of its ancestors
6331      *
6332      * @return True if this view and all of its ancestors are {@link #VISIBLE}
6333      */
isShown()6334     public boolean isShown() {
6335         View current = this;
6336         //noinspection ConstantConditions
6337         do {
6338             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6339                 return false;
6340             }
6341             ViewParent parent = current.mParent;
6342             if (parent == null) {
6343                 return false; // We are not attached to the view root
6344             }
6345             if (!(parent instanceof View)) {
6346                 return true;
6347             }
6348             current = (View) parent;
6349         } while (current != null);
6350 
6351         return false;
6352     }
6353 
6354     /**
6355      * Called by the view hierarchy when the content insets for a window have
6356      * changed, to allow it to adjust its content to fit within those windows.
6357      * The content insets tell you the space that the status bar, input method,
6358      * and other system windows infringe on the application's window.
6359      *
6360      * <p>You do not normally need to deal with this function, since the default
6361      * window decoration given to applications takes care of applying it to the
6362      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6363      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6364      * and your content can be placed under those system elements.  You can then
6365      * use this method within your view hierarchy if you have parts of your UI
6366      * which you would like to ensure are not being covered.
6367      *
6368      * <p>The default implementation of this method simply applies the content
6369      * insets to the view's padding, consuming that content (modifying the
6370      * insets to be 0), and returning true.  This behavior is off by default, but can
6371      * be enabled through {@link #setFitsSystemWindows(boolean)}.
6372      *
6373      * <p>This function's traversal down the hierarchy is depth-first.  The same content
6374      * insets object is propagated down the hierarchy, so any changes made to it will
6375      * be seen by all following views (including potentially ones above in
6376      * the hierarchy since this is a depth-first traversal).  The first view
6377      * that returns true will abort the entire traversal.
6378      *
6379      * <p>The default implementation works well for a situation where it is
6380      * used with a container that covers the entire window, allowing it to
6381      * apply the appropriate insets to its content on all edges.  If you need
6382      * a more complicated layout (such as two different views fitting system
6383      * windows, one on the top of the window, and one on the bottom),
6384      * you can override the method and handle the insets however you would like.
6385      * Note that the insets provided by the framework are always relative to the
6386      * far edges of the window, not accounting for the location of the called view
6387      * within that window.  (In fact when this method is called you do not yet know
6388      * where the layout will place the view, as it is done before layout happens.)
6389      *
6390      * <p>Note: unlike many View methods, there is no dispatch phase to this
6391      * call.  If you are overriding it in a ViewGroup and want to allow the
6392      * call to continue to your children, you must be sure to call the super
6393      * implementation.
6394      *
6395      * <p>Here is a sample layout that makes use of fitting system windows
6396      * to have controls for a video view placed inside of the window decorations
6397      * that it hides and shows.  This can be used with code like the second
6398      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6399      *
6400      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6401      *
6402      * @param insets Current content insets of the window.  Prior to
6403      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6404      * the insets or else you and Android will be unhappy.
6405      *
6406      * @return {@code true} if this view applied the insets and it should not
6407      * continue propagating further down the hierarchy, {@code false} otherwise.
6408      * @see #getFitsSystemWindows()
6409      * @see #setFitsSystemWindows(boolean)
6410      * @see #setSystemUiVisibility(int)
6411      *
6412      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6413      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6414      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6415      * to implement handling their own insets.
6416      */
fitSystemWindows(Rect insets)6417     protected boolean fitSystemWindows(Rect insets) {
6418         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6419             if (insets == null) {
6420                 // Null insets by definition have already been consumed.
6421                 // This call cannot apply insets since there are none to apply,
6422                 // so return false.
6423                 return false;
6424             }
6425             // If we're not in the process of dispatching the newer apply insets call,
6426             // that means we're not in the compatibility path. Dispatch into the newer
6427             // apply insets path and take things from there.
6428             try {
6429                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6430                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6431             } finally {
6432                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6433             }
6434         } else {
6435             // We're being called from the newer apply insets path.
6436             // Perform the standard fallback behavior.
6437             return fitSystemWindowsInt(insets);
6438         }
6439     }
6440 
fitSystemWindowsInt(Rect insets)6441     private boolean fitSystemWindowsInt(Rect insets) {
6442         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6443             mUserPaddingStart = UNDEFINED_PADDING;
6444             mUserPaddingEnd = UNDEFINED_PADDING;
6445             Rect localInsets = sThreadLocal.get();
6446             if (localInsets == null) {
6447                 localInsets = new Rect();
6448                 sThreadLocal.set(localInsets);
6449             }
6450             boolean res = computeFitSystemWindows(insets, localInsets);
6451             mUserPaddingLeftInitial = localInsets.left;
6452             mUserPaddingRightInitial = localInsets.right;
6453             internalSetPadding(localInsets.left, localInsets.top,
6454                     localInsets.right, localInsets.bottom);
6455             return res;
6456         }
6457         return false;
6458     }
6459 
6460     /**
6461      * Called when the view should apply {@link WindowInsets} according to its internal policy.
6462      *
6463      * <p>This method should be overridden by views that wish to apply a policy different from or
6464      * in addition to the default behavior. Clients that wish to force a view subtree
6465      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6466      *
6467      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6468      * it will be called during dispatch instead of this method. The listener may optionally
6469      * call this method from its own implementation if it wishes to apply the view's default
6470      * insets policy in addition to its own.</p>
6471      *
6472      * <p>Implementations of this method should either return the insets parameter unchanged
6473      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6474      * that this view applied itself. This allows new inset types added in future platform
6475      * versions to pass through existing implementations unchanged without being erroneously
6476      * consumed.</p>
6477      *
6478      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6479      * property is set then the view will consume the system window insets and apply them
6480      * as padding for the view.</p>
6481      *
6482      * @param insets Insets to apply
6483      * @return The supplied insets with any applied insets consumed
6484      */
onApplyWindowInsets(WindowInsets insets)6485     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6486         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6487             // We weren't called from within a direct call to fitSystemWindows,
6488             // call into it as a fallback in case we're in a class that overrides it
6489             // and has logic to perform.
6490             if (fitSystemWindows(insets.getSystemWindowInsets())) {
6491                 return insets.consumeSystemWindowInsets();
6492             }
6493         } else {
6494             // We were called from within a direct call to fitSystemWindows.
6495             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6496                 return insets.consumeSystemWindowInsets();
6497             }
6498         }
6499         return insets;
6500     }
6501 
6502     /**
6503      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6504      * window insets to this view. The listener's
6505      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6506      * method will be called instead of the view's
6507      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6508      *
6509      * @param listener Listener to set
6510      *
6511      * @see #onApplyWindowInsets(WindowInsets)
6512      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)6513     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6514         getListenerInfo().mOnApplyWindowInsetsListener = listener;
6515     }
6516 
6517     /**
6518      * Request to apply the given window insets to this view or another view in its subtree.
6519      *
6520      * <p>This method should be called by clients wishing to apply insets corresponding to areas
6521      * obscured by window decorations or overlays. This can include the status and navigation bars,
6522      * action bars, input methods and more. New inset categories may be added in the future.
6523      * The method returns the insets provided minus any that were applied by this view or its
6524      * children.</p>
6525      *
6526      * <p>Clients wishing to provide custom behavior should override the
6527      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6528      * {@link OnApplyWindowInsetsListener} via the
6529      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6530      * method.</p>
6531      *
6532      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6533      * </p>
6534      *
6535      * @param insets Insets to apply
6536      * @return The provided insets minus the insets that were consumed
6537      */
dispatchApplyWindowInsets(WindowInsets insets)6538     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6539         try {
6540             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6541             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6542                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6543             } else {
6544                 return onApplyWindowInsets(insets);
6545             }
6546         } finally {
6547             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6548         }
6549     }
6550 
6551     /**
6552      * @hide Compute the insets that should be consumed by this view and the ones
6553      * that should propagate to those under it.
6554      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)6555     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6556         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6557                 || mAttachInfo == null
6558                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6559                         && !mAttachInfo.mOverscanRequested)) {
6560             outLocalInsets.set(inoutInsets);
6561             inoutInsets.set(0, 0, 0, 0);
6562             return true;
6563         } else {
6564             // The application wants to take care of fitting system window for
6565             // the content...  however we still need to take care of any overscan here.
6566             final Rect overscan = mAttachInfo.mOverscanInsets;
6567             outLocalInsets.set(overscan);
6568             inoutInsets.left -= overscan.left;
6569             inoutInsets.top -= overscan.top;
6570             inoutInsets.right -= overscan.right;
6571             inoutInsets.bottom -= overscan.bottom;
6572             return false;
6573         }
6574     }
6575 
6576     /**
6577      * Compute insets that should be consumed by this view and the ones that should propagate
6578      * to those under it.
6579      *
6580      * @param in Insets currently being processed by this View, likely received as a parameter
6581      *           to {@link #onApplyWindowInsets(WindowInsets)}.
6582      * @param outLocalInsets A Rect that will receive the insets that should be consumed
6583      *                       by this view
6584      * @return Insets that should be passed along to views under this one
6585      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)6586     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
6587         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6588                 || mAttachInfo == null
6589                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
6590             outLocalInsets.set(in.getSystemWindowInsets());
6591             return in.consumeSystemWindowInsets();
6592         } else {
6593             outLocalInsets.set(0, 0, 0, 0);
6594             return in;
6595         }
6596     }
6597 
6598     /**
6599      * Sets whether or not this view should account for system screen decorations
6600      * such as the status bar and inset its content; that is, controlling whether
6601      * the default implementation of {@link #fitSystemWindows(Rect)} will be
6602      * executed.  See that method for more details.
6603      *
6604      * <p>Note that if you are providing your own implementation of
6605      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6606      * flag to true -- your implementation will be overriding the default
6607      * implementation that checks this flag.
6608      *
6609      * @param fitSystemWindows If true, then the default implementation of
6610      * {@link #fitSystemWindows(Rect)} will be executed.
6611      *
6612      * @attr ref android.R.styleable#View_fitsSystemWindows
6613      * @see #getFitsSystemWindows()
6614      * @see #fitSystemWindows(Rect)
6615      * @see #setSystemUiVisibility(int)
6616      */
setFitsSystemWindows(boolean fitSystemWindows)6617     public void setFitsSystemWindows(boolean fitSystemWindows) {
6618         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6619     }
6620 
6621     /**
6622      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6623      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6624      * will be executed.
6625      *
6626      * @return {@code true} if the default implementation of
6627      * {@link #fitSystemWindows(Rect)} will be executed.
6628      *
6629      * @attr ref android.R.styleable#View_fitsSystemWindows
6630      * @see #setFitsSystemWindows(boolean)
6631      * @see #fitSystemWindows(Rect)
6632      * @see #setSystemUiVisibility(int)
6633      */
6634     @ViewDebug.ExportedProperty
getFitsSystemWindows()6635     public boolean getFitsSystemWindows() {
6636         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6637     }
6638 
6639     /** @hide */
fitsSystemWindows()6640     public boolean fitsSystemWindows() {
6641         return getFitsSystemWindows();
6642     }
6643 
6644     /**
6645      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6646      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6647      */
requestFitSystemWindows()6648     public void requestFitSystemWindows() {
6649         if (mParent != null) {
6650             mParent.requestFitSystemWindows();
6651         }
6652     }
6653 
6654     /**
6655      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6656      */
requestApplyInsets()6657     public void requestApplyInsets() {
6658         requestFitSystemWindows();
6659     }
6660 
6661     /**
6662      * For use by PhoneWindow to make its own system window fitting optional.
6663      * @hide
6664      */
makeOptionalFitsSystemWindows()6665     public void makeOptionalFitsSystemWindows() {
6666         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6667     }
6668 
6669     /**
6670      * Returns the visibility status for this view.
6671      *
6672      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6673      * @attr ref android.R.styleable#View_visibility
6674      */
6675     @ViewDebug.ExportedProperty(mapping = {
6676         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
6677         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6678         @ViewDebug.IntToString(from = GONE,      to = "GONE")
6679     })
6680     @Visibility
getVisibility()6681     public int getVisibility() {
6682         return mViewFlags & VISIBILITY_MASK;
6683     }
6684 
6685     /**
6686      * Set the enabled state of this view.
6687      *
6688      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6689      * @attr ref android.R.styleable#View_visibility
6690      */
6691     @RemotableViewMethod
setVisibility(@isibility int visibility)6692     public void setVisibility(@Visibility int visibility) {
6693         setFlags(visibility, VISIBILITY_MASK);
6694         if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
6695     }
6696 
6697     /**
6698      * Returns the enabled status for this view. The interpretation of the
6699      * enabled state varies by subclass.
6700      *
6701      * @return True if this view is enabled, false otherwise.
6702      */
6703     @ViewDebug.ExportedProperty
isEnabled()6704     public boolean isEnabled() {
6705         return (mViewFlags & ENABLED_MASK) == ENABLED;
6706     }
6707 
6708     /**
6709      * Set the enabled state of this view. The interpretation of the enabled
6710      * state varies by subclass.
6711      *
6712      * @param enabled True if this view is enabled, false otherwise.
6713      */
6714     @RemotableViewMethod
setEnabled(boolean enabled)6715     public void setEnabled(boolean enabled) {
6716         if (enabled == isEnabled()) return;
6717 
6718         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6719 
6720         /*
6721          * The View most likely has to change its appearance, so refresh
6722          * the drawable state.
6723          */
6724         refreshDrawableState();
6725 
6726         // Invalidate too, since the default behavior for views is to be
6727         // be drawn at 50% alpha rather than to change the drawable.
6728         invalidate(true);
6729 
6730         if (!enabled) {
6731             cancelPendingInputEvents();
6732         }
6733     }
6734 
6735     /**
6736      * Set whether this view can receive the focus.
6737      *
6738      * Setting this to false will also ensure that this view is not focusable
6739      * in touch mode.
6740      *
6741      * @param focusable If true, this view can receive the focus.
6742      *
6743      * @see #setFocusableInTouchMode(boolean)
6744      * @attr ref android.R.styleable#View_focusable
6745      */
setFocusable(boolean focusable)6746     public void setFocusable(boolean focusable) {
6747         if (!focusable) {
6748             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6749         }
6750         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6751     }
6752 
6753     /**
6754      * Set whether this view can receive focus while in touch mode.
6755      *
6756      * Setting this to true will also ensure that this view is focusable.
6757      *
6758      * @param focusableInTouchMode If true, this view can receive the focus while
6759      *   in touch mode.
6760      *
6761      * @see #setFocusable(boolean)
6762      * @attr ref android.R.styleable#View_focusableInTouchMode
6763      */
setFocusableInTouchMode(boolean focusableInTouchMode)6764     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6765         // Focusable in touch mode should always be set before the focusable flag
6766         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6767         // which, in touch mode, will not successfully request focus on this view
6768         // because the focusable in touch mode flag is not set
6769         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6770         if (focusableInTouchMode) {
6771             setFlags(FOCUSABLE, FOCUSABLE_MASK);
6772         }
6773     }
6774 
6775     /**
6776      * Set whether this view should have sound effects enabled for events such as
6777      * clicking and touching.
6778      *
6779      * <p>You may wish to disable sound effects for a view if you already play sounds,
6780      * for instance, a dial key that plays dtmf tones.
6781      *
6782      * @param soundEffectsEnabled whether sound effects are enabled for this view.
6783      * @see #isSoundEffectsEnabled()
6784      * @see #playSoundEffect(int)
6785      * @attr ref android.R.styleable#View_soundEffectsEnabled
6786      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)6787     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
6788         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
6789     }
6790 
6791     /**
6792      * @return whether this view should have sound effects enabled for events such as
6793      *     clicking and touching.
6794      *
6795      * @see #setSoundEffectsEnabled(boolean)
6796      * @see #playSoundEffect(int)
6797      * @attr ref android.R.styleable#View_soundEffectsEnabled
6798      */
6799     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()6800     public boolean isSoundEffectsEnabled() {
6801         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
6802     }
6803 
6804     /**
6805      * Set whether this view should have haptic feedback for events such as
6806      * long presses.
6807      *
6808      * <p>You may wish to disable haptic feedback if your view already controls
6809      * its own haptic feedback.
6810      *
6811      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
6812      * @see #isHapticFeedbackEnabled()
6813      * @see #performHapticFeedback(int)
6814      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6815      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)6816     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
6817         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
6818     }
6819 
6820     /**
6821      * @return whether this view should have haptic feedback enabled for events
6822      * long presses.
6823      *
6824      * @see #setHapticFeedbackEnabled(boolean)
6825      * @see #performHapticFeedback(int)
6826      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6827      */
6828     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()6829     public boolean isHapticFeedbackEnabled() {
6830         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
6831     }
6832 
6833     /**
6834      * Returns the layout direction for this view.
6835      *
6836      * @return One of {@link #LAYOUT_DIRECTION_LTR},
6837      *   {@link #LAYOUT_DIRECTION_RTL},
6838      *   {@link #LAYOUT_DIRECTION_INHERIT} or
6839      *   {@link #LAYOUT_DIRECTION_LOCALE}.
6840      *
6841      * @attr ref android.R.styleable#View_layoutDirection
6842      *
6843      * @hide
6844      */
6845     @ViewDebug.ExportedProperty(category = "layout", mapping = {
6846         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
6847         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
6848         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
6849         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
6850     })
6851     @LayoutDir
getRawLayoutDirection()6852     public int getRawLayoutDirection() {
6853         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
6854     }
6855 
6856     /**
6857      * Set the layout direction for this view. This will propagate a reset of layout direction
6858      * resolution to the view's children and resolve layout direction for this view.
6859      *
6860      * @param layoutDirection the layout direction to set. Should be one of:
6861      *
6862      * {@link #LAYOUT_DIRECTION_LTR},
6863      * {@link #LAYOUT_DIRECTION_RTL},
6864      * {@link #LAYOUT_DIRECTION_INHERIT},
6865      * {@link #LAYOUT_DIRECTION_LOCALE}.
6866      *
6867      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6868      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6869      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6870      *
6871      * @attr ref android.R.styleable#View_layoutDirection
6872      */
6873     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)6874     public void setLayoutDirection(@LayoutDir int layoutDirection) {
6875         if (getRawLayoutDirection() != layoutDirection) {
6876             // Reset the current layout direction and the resolved one
6877             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6878             resetRtlProperties();
6879             // Set the new layout direction (filtered)
6880             mPrivateFlags2 |=
6881                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6882             // We need to resolve all RTL properties as they all depend on layout direction
6883             resolveRtlPropertiesIfNeeded();
6884             requestLayout();
6885             invalidate(true);
6886         }
6887     }
6888 
6889     /**
6890      * Returns the resolved layout direction for this view.
6891      *
6892      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6893      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6894      *
6895      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6896      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6897      *
6898      * @attr ref android.R.styleable#View_layoutDirection
6899      */
6900     @ViewDebug.ExportedProperty(category = "layout", mapping = {
6901         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6902         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6903     })
6904     @ResolvedLayoutDir
getLayoutDirection()6905     public int getLayoutDirection() {
6906         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6907         if (targetSdkVersion < JELLY_BEAN_MR1) {
6908             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6909             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6910         }
6911         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6912                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6913     }
6914 
6915     /**
6916      * Indicates whether or not this view's layout is right-to-left. This is resolved from
6917      * layout attribute and/or the inherited value from the parent
6918      *
6919      * @return true if the layout is right-to-left.
6920      *
6921      * @hide
6922      */
6923     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()6924     public boolean isLayoutRtl() {
6925         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6926     }
6927 
6928     /**
6929      * Indicates whether the view is currently tracking transient state that the
6930      * app should not need to concern itself with saving and restoring, but that
6931      * the framework should take special note to preserve when possible.
6932      *
6933      * <p>A view with transient state cannot be trivially rebound from an external
6934      * data source, such as an adapter binding item views in a list. This may be
6935      * because the view is performing an animation, tracking user selection
6936      * of content, or similar.</p>
6937      *
6938      * @return true if the view has transient state
6939      */
6940     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()6941     public boolean hasTransientState() {
6942         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6943     }
6944 
6945     /**
6946      * Set whether this view is currently tracking transient state that the
6947      * framework should attempt to preserve when possible. This flag is reference counted,
6948      * so every call to setHasTransientState(true) should be paired with a later call
6949      * to setHasTransientState(false).
6950      *
6951      * <p>A view with transient state cannot be trivially rebound from an external
6952      * data source, such as an adapter binding item views in a list. This may be
6953      * because the view is performing an animation, tracking user selection
6954      * of content, or similar.</p>
6955      *
6956      * @param hasTransientState true if this view has transient state
6957      */
setHasTransientState(boolean hasTransientState)6958     public void setHasTransientState(boolean hasTransientState) {
6959         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6960                 mTransientStateCount - 1;
6961         if (mTransientStateCount < 0) {
6962             mTransientStateCount = 0;
6963             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6964                     "unmatched pair of setHasTransientState calls");
6965         } else if ((hasTransientState && mTransientStateCount == 1) ||
6966                 (!hasTransientState && mTransientStateCount == 0)) {
6967             // update flag if we've just incremented up from 0 or decremented down to 0
6968             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6969                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6970             if (mParent != null) {
6971                 try {
6972                     mParent.childHasTransientStateChanged(this, hasTransientState);
6973                 } catch (AbstractMethodError e) {
6974                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6975                             " does not fully implement ViewParent", e);
6976                 }
6977             }
6978         }
6979     }
6980 
6981     /**
6982      * Returns true if this view is currently attached to a window.
6983      */
isAttachedToWindow()6984     public boolean isAttachedToWindow() {
6985         return mAttachInfo != null;
6986     }
6987 
6988     /**
6989      * Returns true if this view has been through at least one layout since it
6990      * was last attached to or detached from a window.
6991      */
isLaidOut()6992     public boolean isLaidOut() {
6993         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
6994     }
6995 
6996     /**
6997      * If this view doesn't do any drawing on its own, set this flag to
6998      * allow further optimizations. By default, this flag is not set on
6999      * View, but could be set on some View subclasses such as ViewGroup.
7000      *
7001      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7002      * you should clear this flag.
7003      *
7004      * @param willNotDraw whether or not this View draw on its own
7005      */
setWillNotDraw(boolean willNotDraw)7006     public void setWillNotDraw(boolean willNotDraw) {
7007         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7008     }
7009 
7010     /**
7011      * Returns whether or not this View draws on its own.
7012      *
7013      * @return true if this view has nothing to draw, false otherwise
7014      */
7015     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()7016     public boolean willNotDraw() {
7017         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7018     }
7019 
7020     /**
7021      * When a View's drawing cache is enabled, drawing is redirected to an
7022      * offscreen bitmap. Some views, like an ImageView, must be able to
7023      * bypass this mechanism if they already draw a single bitmap, to avoid
7024      * unnecessary usage of the memory.
7025      *
7026      * @param willNotCacheDrawing true if this view does not cache its
7027      *        drawing, false otherwise
7028      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)7029     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7030         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7031     }
7032 
7033     /**
7034      * Returns whether or not this View can cache its drawing or not.
7035      *
7036      * @return true if this view does not cache its drawing, false otherwise
7037      */
7038     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()7039     public boolean willNotCacheDrawing() {
7040         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7041     }
7042 
7043     /**
7044      * Indicates whether this view reacts to click events or not.
7045      *
7046      * @return true if the view is clickable, false otherwise
7047      *
7048      * @see #setClickable(boolean)
7049      * @attr ref android.R.styleable#View_clickable
7050      */
7051     @ViewDebug.ExportedProperty
isClickable()7052     public boolean isClickable() {
7053         return (mViewFlags & CLICKABLE) == CLICKABLE;
7054     }
7055 
7056     /**
7057      * Enables or disables click events for this view. When a view
7058      * is clickable it will change its state to "pressed" on every click.
7059      * Subclasses should set the view clickable to visually react to
7060      * user's clicks.
7061      *
7062      * @param clickable true to make the view clickable, false otherwise
7063      *
7064      * @see #isClickable()
7065      * @attr ref android.R.styleable#View_clickable
7066      */
setClickable(boolean clickable)7067     public void setClickable(boolean clickable) {
7068         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7069     }
7070 
7071     /**
7072      * Indicates whether this view reacts to long click events or not.
7073      *
7074      * @return true if the view is long clickable, false otherwise
7075      *
7076      * @see #setLongClickable(boolean)
7077      * @attr ref android.R.styleable#View_longClickable
7078      */
isLongClickable()7079     public boolean isLongClickable() {
7080         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7081     }
7082 
7083     /**
7084      * Enables or disables long click events for this view. When a view is long
7085      * clickable it reacts to the user holding down the button for a longer
7086      * duration than a tap. This event can either launch the listener or a
7087      * context menu.
7088      *
7089      * @param longClickable true to make the view long clickable, false otherwise
7090      * @see #isLongClickable()
7091      * @attr ref android.R.styleable#View_longClickable
7092      */
setLongClickable(boolean longClickable)7093     public void setLongClickable(boolean longClickable) {
7094         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7095     }
7096 
7097     /**
7098      * Sets the pressed state for this view and provides a touch coordinate for
7099      * animation hinting.
7100      *
7101      * @param pressed Pass true to set the View's internal state to "pressed",
7102      *            or false to reverts the View's internal state from a
7103      *            previously set "pressed" state.
7104      * @param x The x coordinate of the touch that caused the press
7105      * @param y The y coordinate of the touch that caused the press
7106      */
setPressed(boolean pressed, float x, float y)7107     private void setPressed(boolean pressed, float x, float y) {
7108         if (pressed) {
7109             drawableHotspotChanged(x, y);
7110         }
7111 
7112         setPressed(pressed);
7113     }
7114 
7115     /**
7116      * Sets the pressed state for this view.
7117      *
7118      * @see #isClickable()
7119      * @see #setClickable(boolean)
7120      *
7121      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7122      *        the View's internal state from a previously set "pressed" state.
7123      */
setPressed(boolean pressed)7124     public void setPressed(boolean pressed) {
7125         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7126 
7127         if (pressed) {
7128             mPrivateFlags |= PFLAG_PRESSED;
7129         } else {
7130             mPrivateFlags &= ~PFLAG_PRESSED;
7131         }
7132 
7133         if (needsRefresh) {
7134             refreshDrawableState();
7135         }
7136         dispatchSetPressed(pressed);
7137     }
7138 
7139     /**
7140      * Dispatch setPressed to all of this View's children.
7141      *
7142      * @see #setPressed(boolean)
7143      *
7144      * @param pressed The new pressed state
7145      */
dispatchSetPressed(boolean pressed)7146     protected void dispatchSetPressed(boolean pressed) {
7147     }
7148 
7149     /**
7150      * Indicates whether the view is currently in pressed state. Unless
7151      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7152      * the pressed state.
7153      *
7154      * @see #setPressed(boolean)
7155      * @see #isClickable()
7156      * @see #setClickable(boolean)
7157      *
7158      * @return true if the view is currently pressed, false otherwise
7159      */
7160     @ViewDebug.ExportedProperty
isPressed()7161     public boolean isPressed() {
7162         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7163     }
7164 
7165     /**
7166      * Indicates whether this view will save its state (that is,
7167      * whether its {@link #onSaveInstanceState} method will be called).
7168      *
7169      * @return Returns true if the view state saving is enabled, else false.
7170      *
7171      * @see #setSaveEnabled(boolean)
7172      * @attr ref android.R.styleable#View_saveEnabled
7173      */
isSaveEnabled()7174     public boolean isSaveEnabled() {
7175         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7176     }
7177 
7178     /**
7179      * Controls whether the saving of this view's state is
7180      * enabled (that is, whether its {@link #onSaveInstanceState} method
7181      * will be called).  Note that even if freezing is enabled, the
7182      * view still must have an id assigned to it (via {@link #setId(int)})
7183      * for its state to be saved.  This flag can only disable the
7184      * saving of this view; any child views may still have their state saved.
7185      *
7186      * @param enabled Set to false to <em>disable</em> state saving, or true
7187      * (the default) to allow it.
7188      *
7189      * @see #isSaveEnabled()
7190      * @see #setId(int)
7191      * @see #onSaveInstanceState()
7192      * @attr ref android.R.styleable#View_saveEnabled
7193      */
setSaveEnabled(boolean enabled)7194     public void setSaveEnabled(boolean enabled) {
7195         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7196     }
7197 
7198     /**
7199      * Gets whether the framework should discard touches when the view's
7200      * window is obscured by another visible window.
7201      * Refer to the {@link View} security documentation for more details.
7202      *
7203      * @return True if touch filtering is enabled.
7204      *
7205      * @see #setFilterTouchesWhenObscured(boolean)
7206      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7207      */
7208     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()7209     public boolean getFilterTouchesWhenObscured() {
7210         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7211     }
7212 
7213     /**
7214      * Sets whether the framework should discard touches when the view's
7215      * window is obscured by another visible window.
7216      * Refer to the {@link View} security documentation for more details.
7217      *
7218      * @param enabled True if touch filtering should be enabled.
7219      *
7220      * @see #getFilterTouchesWhenObscured
7221      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7222      */
setFilterTouchesWhenObscured(boolean enabled)7223     public void setFilterTouchesWhenObscured(boolean enabled) {
7224         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7225                 FILTER_TOUCHES_WHEN_OBSCURED);
7226     }
7227 
7228     /**
7229      * Indicates whether the entire hierarchy under this view will save its
7230      * state when a state saving traversal occurs from its parent.  The default
7231      * is true; if false, these views will not be saved unless
7232      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7233      *
7234      * @return Returns true if the view state saving from parent is enabled, else false.
7235      *
7236      * @see #setSaveFromParentEnabled(boolean)
7237      */
isSaveFromParentEnabled()7238     public boolean isSaveFromParentEnabled() {
7239         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7240     }
7241 
7242     /**
7243      * Controls whether the entire hierarchy under this view will save its
7244      * state when a state saving traversal occurs from its parent.  The default
7245      * is true; if false, these views will not be saved unless
7246      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7247      *
7248      * @param enabled Set to false to <em>disable</em> state saving, or true
7249      * (the default) to allow it.
7250      *
7251      * @see #isSaveFromParentEnabled()
7252      * @see #setId(int)
7253      * @see #onSaveInstanceState()
7254      */
setSaveFromParentEnabled(boolean enabled)7255     public void setSaveFromParentEnabled(boolean enabled) {
7256         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7257     }
7258 
7259 
7260     /**
7261      * Returns whether this View is able to take focus.
7262      *
7263      * @return True if this view can take focus, or false otherwise.
7264      * @attr ref android.R.styleable#View_focusable
7265      */
7266     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()7267     public final boolean isFocusable() {
7268         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7269     }
7270 
7271     /**
7272      * When a view is focusable, it may not want to take focus when in touch mode.
7273      * For example, a button would like focus when the user is navigating via a D-pad
7274      * so that the user can click on it, but once the user starts touching the screen,
7275      * the button shouldn't take focus
7276      * @return Whether the view is focusable in touch mode.
7277      * @attr ref android.R.styleable#View_focusableInTouchMode
7278      */
7279     @ViewDebug.ExportedProperty
isFocusableInTouchMode()7280     public final boolean isFocusableInTouchMode() {
7281         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7282     }
7283 
7284     /**
7285      * Find the nearest view in the specified direction that can take focus.
7286      * This does not actually give focus to that view.
7287      *
7288      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7289      *
7290      * @return The nearest focusable in the specified direction, or null if none
7291      *         can be found.
7292      */
focusSearch(@ocusRealDirection int direction)7293     public View focusSearch(@FocusRealDirection int direction) {
7294         if (mParent != null) {
7295             return mParent.focusSearch(this, direction);
7296         } else {
7297             return null;
7298         }
7299     }
7300 
7301     /**
7302      * This method is the last chance for the focused view and its ancestors to
7303      * respond to an arrow key. This is called when the focused view did not
7304      * consume the key internally, nor could the view system find a new view in
7305      * the requested direction to give focus to.
7306      *
7307      * @param focused The currently focused view.
7308      * @param direction The direction focus wants to move. One of FOCUS_UP,
7309      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7310      * @return True if the this view consumed this unhandled move.
7311      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)7312     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7313         return false;
7314     }
7315 
7316     /**
7317      * If a user manually specified the next view id for a particular direction,
7318      * use the root to look up the view.
7319      * @param root The root view of the hierarchy containing this view.
7320      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7321      * or FOCUS_BACKWARD.
7322      * @return The user specified next view, or null if there is none.
7323      */
findUserSetNextFocus(View root, @FocusDirection int direction)7324     View findUserSetNextFocus(View root, @FocusDirection int direction) {
7325         switch (direction) {
7326             case FOCUS_LEFT:
7327                 if (mNextFocusLeftId == View.NO_ID) return null;
7328                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7329             case FOCUS_RIGHT:
7330                 if (mNextFocusRightId == View.NO_ID) return null;
7331                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
7332             case FOCUS_UP:
7333                 if (mNextFocusUpId == View.NO_ID) return null;
7334                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
7335             case FOCUS_DOWN:
7336                 if (mNextFocusDownId == View.NO_ID) return null;
7337                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
7338             case FOCUS_FORWARD:
7339                 if (mNextFocusForwardId == View.NO_ID) return null;
7340                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7341             case FOCUS_BACKWARD: {
7342                 if (mID == View.NO_ID) return null;
7343                 final int id = mID;
7344                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7345                     @Override
7346                     public boolean apply(View t) {
7347                         return t.mNextFocusForwardId == id;
7348                     }
7349                 });
7350             }
7351         }
7352         return null;
7353     }
7354 
7355     private View findViewInsideOutShouldExist(View root, int id) {
7356         if (mMatchIdPredicate == null) {
7357             mMatchIdPredicate = new MatchIdPredicate();
7358         }
7359         mMatchIdPredicate.mId = id;
7360         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7361         if (result == null) {
7362             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7363         }
7364         return result;
7365     }
7366 
7367     /**
7368      * Find and return all focusable views that are descendants of this view,
7369      * possibly including this view if it is focusable itself.
7370      *
7371      * @param direction The direction of the focus
7372      * @return A list of focusable views
7373      */
7374     public ArrayList<View> getFocusables(@FocusDirection int direction) {
7375         ArrayList<View> result = new ArrayList<View>(24);
7376         addFocusables(result, direction);
7377         return result;
7378     }
7379 
7380     /**
7381      * Add any focusable views that are descendants of this view (possibly
7382      * including this view if it is focusable itself) to views.  If we are in touch mode,
7383      * only add views that are also focusable in touch mode.
7384      *
7385      * @param views Focusable views found so far
7386      * @param direction The direction of the focus
7387      */
7388     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7389         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7390     }
7391 
7392     /**
7393      * Adds any focusable views that are descendants of this view (possibly
7394      * including this view if it is focusable itself) to views. This method
7395      * adds all focusable views regardless if we are in touch mode or
7396      * only views focusable in touch mode if we are in touch mode or
7397      * only views that can take accessibility focus if accessibility is enabeld
7398      * depending on the focusable mode paramater.
7399      *
7400      * @param views Focusable views found so far or null if all we are interested is
7401      *        the number of focusables.
7402      * @param direction The direction of the focus.
7403      * @param focusableMode The type of focusables to be added.
7404      *
7405      * @see #FOCUSABLES_ALL
7406      * @see #FOCUSABLES_TOUCH_MODE
7407      */
7408     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7409             @FocusableMode int focusableMode) {
7410         if (views == null) {
7411             return;
7412         }
7413         if (!isFocusable()) {
7414             return;
7415         }
7416         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7417                 && isInTouchMode() && !isFocusableInTouchMode()) {
7418             return;
7419         }
7420         views.add(this);
7421     }
7422 
7423     /**
7424      * Finds the Views that contain given text. The containment is case insensitive.
7425      * The search is performed by either the text that the View renders or the content
7426      * description that describes the view for accessibility purposes and the view does
7427      * not render or both. Clients can specify how the search is to be performed via
7428      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7429      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7430      *
7431      * @param outViews The output list of matching Views.
7432      * @param searched The text to match against.
7433      *
7434      * @see #FIND_VIEWS_WITH_TEXT
7435      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7436      * @see #setContentDescription(CharSequence)
7437      */
7438     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7439             @FindViewFlags int flags) {
7440         if (getAccessibilityNodeProvider() != null) {
7441             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7442                 outViews.add(this);
7443             }
7444         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7445                 && (searched != null && searched.length() > 0)
7446                 && (mContentDescription != null && mContentDescription.length() > 0)) {
7447             String searchedLowerCase = searched.toString().toLowerCase();
7448             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7449             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7450                 outViews.add(this);
7451             }
7452         }
7453     }
7454 
7455     /**
7456      * Find and return all touchable views that are descendants of this view,
7457      * possibly including this view if it is touchable itself.
7458      *
7459      * @return A list of touchable views
7460      */
7461     public ArrayList<View> getTouchables() {
7462         ArrayList<View> result = new ArrayList<View>();
7463         addTouchables(result);
7464         return result;
7465     }
7466 
7467     /**
7468      * Add any touchable views that are descendants of this view (possibly
7469      * including this view if it is touchable itself) to views.
7470      *
7471      * @param views Touchable views found so far
7472      */
7473     public void addTouchables(ArrayList<View> views) {
7474         final int viewFlags = mViewFlags;
7475 
7476         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7477                 && (viewFlags & ENABLED_MASK) == ENABLED) {
7478             views.add(this);
7479         }
7480     }
7481 
7482     /**
7483      * Returns whether this View is accessibility focused.
7484      *
7485      * @return True if this View is accessibility focused.
7486      */
7487     public boolean isAccessibilityFocused() {
7488         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7489     }
7490 
7491     /**
7492      * Call this to try to give accessibility focus to this view.
7493      *
7494      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7495      * returns false or the view is no visible or the view already has accessibility
7496      * focus.
7497      *
7498      * See also {@link #focusSearch(int)}, which is what you call to say that you
7499      * have focus, and you want your parent to look for the next one.
7500      *
7501      * @return Whether this view actually took accessibility focus.
7502      *
7503      * @hide
7504      */
7505     public boolean requestAccessibilityFocus() {
7506         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7507         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7508             return false;
7509         }
7510         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7511             return false;
7512         }
7513         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7514             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7515             ViewRootImpl viewRootImpl = getViewRootImpl();
7516             if (viewRootImpl != null) {
7517                 viewRootImpl.setAccessibilityFocus(this, null);
7518             }
7519             invalidate();
7520             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7521             return true;
7522         }
7523         return false;
7524     }
7525 
7526     /**
7527      * Call this to try to clear accessibility focus of this view.
7528      *
7529      * See also {@link #focusSearch(int)}, which is what you call to say that you
7530      * have focus, and you want your parent to look for the next one.
7531      *
7532      * @hide
7533      */
7534     public void clearAccessibilityFocus() {
7535         clearAccessibilityFocusNoCallbacks();
7536         // Clear the global reference of accessibility focus if this
7537         // view or any of its descendants had accessibility focus.
7538         ViewRootImpl viewRootImpl = getViewRootImpl();
7539         if (viewRootImpl != null) {
7540             View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7541             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7542                 viewRootImpl.setAccessibilityFocus(null, null);
7543             }
7544         }
7545     }
7546 
7547     private void sendAccessibilityHoverEvent(int eventType) {
7548         // Since we are not delivering to a client accessibility events from not
7549         // important views (unless the clinet request that) we need to fire the
7550         // event from the deepest view exposed to the client. As a consequence if
7551         // the user crosses a not exposed view the client will see enter and exit
7552         // of the exposed predecessor followed by and enter and exit of that same
7553         // predecessor when entering and exiting the not exposed descendant. This
7554         // is fine since the client has a clear idea which view is hovered at the
7555         // price of a couple more events being sent. This is a simple and
7556         // working solution.
7557         View source = this;
7558         while (true) {
7559             if (source.includeForAccessibility()) {
7560                 source.sendAccessibilityEvent(eventType);
7561                 return;
7562             }
7563             ViewParent parent = source.getParent();
7564             if (parent instanceof View) {
7565                 source = (View) parent;
7566             } else {
7567                 return;
7568             }
7569         }
7570     }
7571 
7572     /**
7573      * Clears accessibility focus without calling any callback methods
7574      * normally invoked in {@link #clearAccessibilityFocus()}. This method
7575      * is used for clearing accessibility focus when giving this focus to
7576      * another view.
7577      */
7578     void clearAccessibilityFocusNoCallbacks() {
7579         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7580             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7581             invalidate();
7582             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7583         }
7584     }
7585 
7586     /**
7587      * Call this to try to give focus to a specific view or to one of its
7588      * descendants.
7589      *
7590      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7591      * false), or if it is focusable and it is not focusable in touch mode
7592      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7593      *
7594      * See also {@link #focusSearch(int)}, which is what you call to say that you
7595      * have focus, and you want your parent to look for the next one.
7596      *
7597      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7598      * {@link #FOCUS_DOWN} and <code>null</code>.
7599      *
7600      * @return Whether this view or one of its descendants actually took focus.
7601      */
7602     public final boolean requestFocus() {
7603         return requestFocus(View.FOCUS_DOWN);
7604     }
7605 
7606     /**
7607      * Call this to try to give focus to a specific view or to one of its
7608      * descendants and give it a hint about what direction focus is heading.
7609      *
7610      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7611      * false), or if it is focusable and it is not focusable in touch mode
7612      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7613      *
7614      * See also {@link #focusSearch(int)}, which is what you call to say that you
7615      * have focus, and you want your parent to look for the next one.
7616      *
7617      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7618      * <code>null</code> set for the previously focused rectangle.
7619      *
7620      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7621      * @return Whether this view or one of its descendants actually took focus.
7622      */
7623     public final boolean requestFocus(int direction) {
7624         return requestFocus(direction, null);
7625     }
7626 
7627     /**
7628      * Call this to try to give focus to a specific view or to one of its descendants
7629      * and give it hints about the direction and a specific rectangle that the focus
7630      * is coming from.  The rectangle can help give larger views a finer grained hint
7631      * about where focus is coming from, and therefore, where to show selection, or
7632      * forward focus change internally.
7633      *
7634      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7635      * false), or if it is focusable and it is not focusable in touch mode
7636      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7637      *
7638      * A View will not take focus if it is not visible.
7639      *
7640      * A View will not take focus if one of its parents has
7641      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7642      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7643      *
7644      * See also {@link #focusSearch(int)}, which is what you call to say that you
7645      * have focus, and you want your parent to look for the next one.
7646      *
7647      * You may wish to override this method if your custom {@link View} has an internal
7648      * {@link View} that it wishes to forward the request to.
7649      *
7650      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7651      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7652      *        to give a finer grained hint about where focus is coming from.  May be null
7653      *        if there is no hint.
7654      * @return Whether this view or one of its descendants actually took focus.
7655      */
7656     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7657         return requestFocusNoSearch(direction, previouslyFocusedRect);
7658     }
7659 
7660     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7661         // need to be focusable
7662         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7663                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7664             return false;
7665         }
7666 
7667         // need to be focusable in touch mode if in touch mode
7668         if (isInTouchMode() &&
7669             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7670                return false;
7671         }
7672 
7673         // need to not have any parents blocking us
7674         if (hasAncestorThatBlocksDescendantFocus()) {
7675             return false;
7676         }
7677 
7678         handleFocusGainInternal(direction, previouslyFocusedRect);
7679         return true;
7680     }
7681 
7682     /**
7683      * Call this to try to give focus to a specific view or to one of its descendants. This is a
7684      * special variant of {@link #requestFocus() } that will allow views that are not focuable in
7685      * touch mode to request focus when they are touched.
7686      *
7687      * @return Whether this view or one of its descendants actually took focus.
7688      *
7689      * @see #isInTouchMode()
7690      *
7691      */
7692     public final boolean requestFocusFromTouch() {
7693         // Leave touch mode if we need to
7694         if (isInTouchMode()) {
7695             ViewRootImpl viewRoot = getViewRootImpl();
7696             if (viewRoot != null) {
7697                 viewRoot.ensureTouchMode(false);
7698             }
7699         }
7700         return requestFocus(View.FOCUS_DOWN);
7701     }
7702 
7703     /**
7704      * @return Whether any ancestor of this view blocks descendant focus.
7705      */
7706     private boolean hasAncestorThatBlocksDescendantFocus() {
7707         final boolean focusableInTouchMode = isFocusableInTouchMode();
7708         ViewParent ancestor = mParent;
7709         while (ancestor instanceof ViewGroup) {
7710             final ViewGroup vgAncestor = (ViewGroup) ancestor;
7711             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
7712                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
7713                 return true;
7714             } else {
7715                 ancestor = vgAncestor.getParent();
7716             }
7717         }
7718         return false;
7719     }
7720 
7721     /**
7722      * Gets the mode for determining whether this View is important for accessibility
7723      * which is if it fires accessibility events and if it is reported to
7724      * accessibility services that query the screen.
7725      *
7726      * @return The mode for determining whether a View is important for accessibility.
7727      *
7728      * @attr ref android.R.styleable#View_importantForAccessibility
7729      *
7730      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7731      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7732      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7733      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7734      */
7735     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7736             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7737             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7738             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7739             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7740                     to = "noHideDescendants")
7741         })
7742     public int getImportantForAccessibility() {
7743         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7744                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7745     }
7746 
7747     /**
7748      * Sets the live region mode for this view. This indicates to accessibility
7749      * services whether they should automatically notify the user about changes
7750      * to the view's content description or text, or to the content descriptions
7751      * or text of the view's children (where applicable).
7752      * <p>
7753      * For example, in a login screen with a TextView that displays an "incorrect
7754      * password" notification, that view should be marked as a live region with
7755      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7756      * <p>
7757      * To disable change notifications for this view, use
7758      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7759      * mode for most views.
7760      * <p>
7761      * To indicate that the user should be notified of changes, use
7762      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7763      * <p>
7764      * If the view's changes should interrupt ongoing speech and notify the user
7765      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7766      *
7767      * @param mode The live region mode for this view, one of:
7768      *        <ul>
7769      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7770      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7771      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7772      *        </ul>
7773      * @attr ref android.R.styleable#View_accessibilityLiveRegion
7774      */
7775     public void setAccessibilityLiveRegion(int mode) {
7776         if (mode != getAccessibilityLiveRegion()) {
7777             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7778             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7779                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7780             notifyViewAccessibilityStateChangedIfNeeded(
7781                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7782         }
7783     }
7784 
7785     /**
7786      * Gets the live region mode for this View.
7787      *
7788      * @return The live region mode for the view.
7789      *
7790      * @attr ref android.R.styleable#View_accessibilityLiveRegion
7791      *
7792      * @see #setAccessibilityLiveRegion(int)
7793      */
7794     public int getAccessibilityLiveRegion() {
7795         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
7796                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
7797     }
7798 
7799     /**
7800      * Sets how to determine whether this view is important for accessibility
7801      * which is if it fires accessibility events and if it is reported to
7802      * accessibility services that query the screen.
7803      *
7804      * @param mode How to determine whether this view is important for accessibility.
7805      *
7806      * @attr ref android.R.styleable#View_importantForAccessibility
7807      *
7808      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7809      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7810      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7811      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7812      */
7813     public void setImportantForAccessibility(int mode) {
7814         final int oldMode = getImportantForAccessibility();
7815         if (mode != oldMode) {
7816             // If we're moving between AUTO and another state, we might not need
7817             // to send a subtree changed notification. We'll store the computed
7818             // importance, since we'll need to check it later to make sure.
7819             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
7820                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
7821             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
7822             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7823             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
7824                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7825             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
7826                 notifySubtreeAccessibilityStateChangedIfNeeded();
7827             } else {
7828                 notifyViewAccessibilityStateChangedIfNeeded(
7829                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7830             }
7831         }
7832     }
7833 
7834     /**
7835      * Computes whether this view should be exposed for accessibility. In
7836      * general, views that are interactive or provide information are exposed
7837      * while views that serve only as containers are hidden.
7838      * <p>
7839      * If an ancestor of this view has importance
7840      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
7841      * returns <code>false</code>.
7842      * <p>
7843      * Otherwise, the value is computed according to the view's
7844      * {@link #getImportantForAccessibility()} value:
7845      * <ol>
7846      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
7847      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
7848      * </code>
7849      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
7850      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
7851      * view satisfies any of the following:
7852      * <ul>
7853      * <li>Is actionable, e.g. {@link #isClickable()},
7854      * {@link #isLongClickable()}, or {@link #isFocusable()}
7855      * <li>Has an {@link AccessibilityDelegate}
7856      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
7857      * {@link OnKeyListener}, etc.
7858      * <li>Is an accessibility live region, e.g.
7859      * {@link #getAccessibilityLiveRegion()} is not
7860      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
7861      * </ul>
7862      * </ol>
7863      *
7864      * @return Whether the view is exposed for accessibility.
7865      * @see #setImportantForAccessibility(int)
7866      * @see #getImportantForAccessibility()
7867      */
7868     public boolean isImportantForAccessibility() {
7869         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7870                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7871         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
7872                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7873             return false;
7874         }
7875 
7876         // Check parent mode to ensure we're not hidden.
7877         ViewParent parent = mParent;
7878         while (parent instanceof View) {
7879             if (((View) parent).getImportantForAccessibility()
7880                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7881                 return false;
7882             }
7883             parent = parent.getParent();
7884         }
7885 
7886         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
7887                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
7888                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
7889     }
7890 
7891     /**
7892      * Gets the parent for accessibility purposes. Note that the parent for
7893      * accessibility is not necessary the immediate parent. It is the first
7894      * predecessor that is important for accessibility.
7895      *
7896      * @return The parent for accessibility purposes.
7897      */
7898     public ViewParent getParentForAccessibility() {
7899         if (mParent instanceof View) {
7900             View parentView = (View) mParent;
7901             if (parentView.includeForAccessibility()) {
7902                 return mParent;
7903             } else {
7904                 return mParent.getParentForAccessibility();
7905             }
7906         }
7907         return null;
7908     }
7909 
7910     /**
7911      * Adds the children of a given View for accessibility. Since some Views are
7912      * not important for accessibility the children for accessibility are not
7913      * necessarily direct children of the view, rather they are the first level of
7914      * descendants important for accessibility.
7915      *
7916      * @param children The list of children for accessibility.
7917      */
7918     public void addChildrenForAccessibility(ArrayList<View> children) {
7919 
7920     }
7921 
7922     /**
7923      * Whether to regard this view for accessibility. A view is regarded for
7924      * accessibility if it is important for accessibility or the querying
7925      * accessibility service has explicitly requested that view not
7926      * important for accessibility are regarded.
7927      *
7928      * @return Whether to regard the view for accessibility.
7929      *
7930      * @hide
7931      */
7932     public boolean includeForAccessibility() {
7933         if (mAttachInfo != null) {
7934             return (mAttachInfo.mAccessibilityFetchFlags
7935                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
7936                     || isImportantForAccessibility();
7937         }
7938         return false;
7939     }
7940 
7941     /**
7942      * Returns whether the View is considered actionable from
7943      * accessibility perspective. Such view are important for
7944      * accessibility.
7945      *
7946      * @return True if the view is actionable for accessibility.
7947      *
7948      * @hide
7949      */
7950     public boolean isActionableForAccessibility() {
7951         return (isClickable() || isLongClickable() || isFocusable());
7952     }
7953 
7954     /**
7955      * Returns whether the View has registered callbacks which makes it
7956      * important for accessibility.
7957      *
7958      * @return True if the view is actionable for accessibility.
7959      */
7960     private boolean hasListenersForAccessibility() {
7961         ListenerInfo info = getListenerInfo();
7962         return mTouchDelegate != null || info.mOnKeyListener != null
7963                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
7964                 || info.mOnHoverListener != null || info.mOnDragListener != null;
7965     }
7966 
7967     /**
7968      * Notifies that the accessibility state of this view changed. The change
7969      * is local to this view and does not represent structural changes such
7970      * as children and parent. For example, the view became focusable. The
7971      * notification is at at most once every
7972      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7973      * to avoid unnecessary load to the system. Also once a view has a pending
7974      * notification this method is a NOP until the notification has been sent.
7975      *
7976      * @hide
7977      */
7978     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
7979         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7980             return;
7981         }
7982         if (mSendViewStateChangedAccessibilityEvent == null) {
7983             mSendViewStateChangedAccessibilityEvent =
7984                     new SendViewStateChangedAccessibilityEvent();
7985         }
7986         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
7987     }
7988 
7989     /**
7990      * Notifies that the accessibility state of this view changed. The change
7991      * is *not* local to this view and does represent structural changes such
7992      * as children and parent. For example, the view size changed. The
7993      * notification is at at most once every
7994      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7995      * to avoid unnecessary load to the system. Also once a view has a pending
7996      * notification this method is a NOP until the notification has been sent.
7997      *
7998      * @hide
7999      */
8000     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8001         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8002             return;
8003         }
8004         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8005             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8006             if (mParent != null) {
8007                 try {
8008                     mParent.notifySubtreeAccessibilityStateChanged(
8009                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8010                 } catch (AbstractMethodError e) {
8011                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8012                             " does not fully implement ViewParent", e);
8013                 }
8014             }
8015         }
8016     }
8017 
8018     /**
8019      * Reset the flag indicating the accessibility state of the subtree rooted
8020      * at this view changed.
8021      */
8022     void resetSubtreeAccessibilityStateChanged() {
8023         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8024     }
8025 
8026     /**
8027      * Report an accessibility action to this view's parents for delegated processing.
8028      *
8029      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8030      * call this method to delegate an accessibility action to a supporting parent. If the parent
8031      * returns true from its
8032      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8033      * method this method will return true to signify that the action was consumed.</p>
8034      *
8035      * <p>This method is useful for implementing nested scrolling child views. If
8036      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8037      * a custom view implementation may invoke this method to allow a parent to consume the
8038      * scroll first. If this method returns true the custom view should skip its own scrolling
8039      * behavior.</p>
8040      *
8041      * @param action Accessibility action to delegate
8042      * @param arguments Optional action arguments
8043      * @return true if the action was consumed by a parent
8044      */
8045     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8046         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8047             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8048                 return true;
8049             }
8050         }
8051         return false;
8052     }
8053 
8054     /**
8055      * Performs the specified accessibility action on the view. For
8056      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8057      * <p>
8058      * If an {@link AccessibilityDelegate} has been specified via calling
8059      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8060      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8061      * is responsible for handling this call.
8062      * </p>
8063      *
8064      * <p>The default implementation will delegate
8065      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8066      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8067      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8068      *
8069      * @param action The action to perform.
8070      * @param arguments Optional action arguments.
8071      * @return Whether the action was performed.
8072      */
8073     public boolean performAccessibilityAction(int action, Bundle arguments) {
8074       if (mAccessibilityDelegate != null) {
8075           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8076       } else {
8077           return performAccessibilityActionInternal(action, arguments);
8078       }
8079     }
8080 
8081    /**
8082     * @see #performAccessibilityAction(int, Bundle)
8083     *
8084     * Note: Called from the default {@link AccessibilityDelegate}.
8085     *
8086     * @hide Until we've refactored all accessibility delegation methods.
8087     */
8088     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8089         if (isNestedScrollingEnabled()
8090                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8091                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
8092             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8093                 return true;
8094             }
8095         }
8096 
8097         switch (action) {
8098             case AccessibilityNodeInfo.ACTION_CLICK: {
8099                 if (isClickable()) {
8100                     performClick();
8101                     return true;
8102                 }
8103             } break;
8104             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8105                 if (isLongClickable()) {
8106                     performLongClick();
8107                     return true;
8108                 }
8109             } break;
8110             case AccessibilityNodeInfo.ACTION_FOCUS: {
8111                 if (!hasFocus()) {
8112                     // Get out of touch mode since accessibility
8113                     // wants to move focus around.
8114                     getViewRootImpl().ensureTouchMode(false);
8115                     return requestFocus();
8116                 }
8117             } break;
8118             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8119                 if (hasFocus()) {
8120                     clearFocus();
8121                     return !isFocused();
8122                 }
8123             } break;
8124             case AccessibilityNodeInfo.ACTION_SELECT: {
8125                 if (!isSelected()) {
8126                     setSelected(true);
8127                     return isSelected();
8128                 }
8129             } break;
8130             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8131                 if (isSelected()) {
8132                     setSelected(false);
8133                     return !isSelected();
8134                 }
8135             } break;
8136             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8137                 if (!isAccessibilityFocused()) {
8138                     return requestAccessibilityFocus();
8139                 }
8140             } break;
8141             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8142                 if (isAccessibilityFocused()) {
8143                     clearAccessibilityFocus();
8144                     return true;
8145                 }
8146             } break;
8147             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8148                 if (arguments != null) {
8149                     final int granularity = arguments.getInt(
8150                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8151                     final boolean extendSelection = arguments.getBoolean(
8152                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8153                     return traverseAtGranularity(granularity, true, extendSelection);
8154                 }
8155             } break;
8156             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8157                 if (arguments != null) {
8158                     final int granularity = arguments.getInt(
8159                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8160                     final boolean extendSelection = arguments.getBoolean(
8161                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8162                     return traverseAtGranularity(granularity, false, extendSelection);
8163                 }
8164             } break;
8165             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8166                 CharSequence text = getIterableTextForAccessibility();
8167                 if (text == null) {
8168                     return false;
8169                 }
8170                 final int start = (arguments != null) ? arguments.getInt(
8171                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8172                 final int end = (arguments != null) ? arguments.getInt(
8173                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8174                 // Only cursor position can be specified (selection length == 0)
8175                 if ((getAccessibilitySelectionStart() != start
8176                         || getAccessibilitySelectionEnd() != end)
8177                         && (start == end)) {
8178                     setAccessibilitySelection(start, end);
8179                     notifyViewAccessibilityStateChangedIfNeeded(
8180                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8181                     return true;
8182                 }
8183             } break;
8184         }
8185         return false;
8186     }
8187 
8188     private boolean traverseAtGranularity(int granularity, boolean forward,
8189             boolean extendSelection) {
8190         CharSequence text = getIterableTextForAccessibility();
8191         if (text == null || text.length() == 0) {
8192             return false;
8193         }
8194         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8195         if (iterator == null) {
8196             return false;
8197         }
8198         int current = getAccessibilitySelectionEnd();
8199         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8200             current = forward ? 0 : text.length();
8201         }
8202         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8203         if (range == null) {
8204             return false;
8205         }
8206         final int segmentStart = range[0];
8207         final int segmentEnd = range[1];
8208         int selectionStart;
8209         int selectionEnd;
8210         if (extendSelection && isAccessibilitySelectionExtendable()) {
8211             selectionStart = getAccessibilitySelectionStart();
8212             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8213                 selectionStart = forward ? segmentStart : segmentEnd;
8214             }
8215             selectionEnd = forward ? segmentEnd : segmentStart;
8216         } else {
8217             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8218         }
8219         setAccessibilitySelection(selectionStart, selectionEnd);
8220         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8221                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8222         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8223         return true;
8224     }
8225 
8226     /**
8227      * Gets the text reported for accessibility purposes.
8228      *
8229      * @return The accessibility text.
8230      *
8231      * @hide
8232      */
8233     public CharSequence getIterableTextForAccessibility() {
8234         return getContentDescription();
8235     }
8236 
8237     /**
8238      * Gets whether accessibility selection can be extended.
8239      *
8240      * @return If selection is extensible.
8241      *
8242      * @hide
8243      */
8244     public boolean isAccessibilitySelectionExtendable() {
8245         return false;
8246     }
8247 
8248     /**
8249      * @hide
8250      */
8251     public int getAccessibilitySelectionStart() {
8252         return mAccessibilityCursorPosition;
8253     }
8254 
8255     /**
8256      * @hide
8257      */
8258     public int getAccessibilitySelectionEnd() {
8259         return getAccessibilitySelectionStart();
8260     }
8261 
8262     /**
8263      * @hide
8264      */
8265     public void setAccessibilitySelection(int start, int end) {
8266         if (start ==  end && end == mAccessibilityCursorPosition) {
8267             return;
8268         }
8269         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8270             mAccessibilityCursorPosition = start;
8271         } else {
8272             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8273         }
8274         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8275     }
8276 
8277     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8278             int fromIndex, int toIndex) {
8279         if (mParent == null) {
8280             return;
8281         }
8282         AccessibilityEvent event = AccessibilityEvent.obtain(
8283                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8284         onInitializeAccessibilityEvent(event);
8285         onPopulateAccessibilityEvent(event);
8286         event.setFromIndex(fromIndex);
8287         event.setToIndex(toIndex);
8288         event.setAction(action);
8289         event.setMovementGranularity(granularity);
8290         mParent.requestSendAccessibilityEvent(this, event);
8291     }
8292 
8293     /**
8294      * @hide
8295      */
8296     public TextSegmentIterator getIteratorForGranularity(int granularity) {
8297         switch (granularity) {
8298             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8299                 CharSequence text = getIterableTextForAccessibility();
8300                 if (text != null && text.length() > 0) {
8301                     CharacterTextSegmentIterator iterator =
8302                         CharacterTextSegmentIterator.getInstance(
8303                                 mContext.getResources().getConfiguration().locale);
8304                     iterator.initialize(text.toString());
8305                     return iterator;
8306                 }
8307             } break;
8308             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8309                 CharSequence text = getIterableTextForAccessibility();
8310                 if (text != null && text.length() > 0) {
8311                     WordTextSegmentIterator iterator =
8312                         WordTextSegmentIterator.getInstance(
8313                                 mContext.getResources().getConfiguration().locale);
8314                     iterator.initialize(text.toString());
8315                     return iterator;
8316                 }
8317             } break;
8318             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8319                 CharSequence text = getIterableTextForAccessibility();
8320                 if (text != null && text.length() > 0) {
8321                     ParagraphTextSegmentIterator iterator =
8322                         ParagraphTextSegmentIterator.getInstance();
8323                     iterator.initialize(text.toString());
8324                     return iterator;
8325                 }
8326             } break;
8327         }
8328         return null;
8329     }
8330 
8331     /**
8332      * @hide
8333      */
8334     public void dispatchStartTemporaryDetach() {
8335         onStartTemporaryDetach();
8336     }
8337 
8338     /**
8339      * This is called when a container is going to temporarily detach a child, with
8340      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8341      * It will either be followed by {@link #onFinishTemporaryDetach()} or
8342      * {@link #onDetachedFromWindow()} when the container is done.
8343      */
8344     public void onStartTemporaryDetach() {
8345         removeUnsetPressCallback();
8346         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8347     }
8348 
8349     /**
8350      * @hide
8351      */
8352     public void dispatchFinishTemporaryDetach() {
8353         onFinishTemporaryDetach();
8354     }
8355 
8356     /**
8357      * Called after {@link #onStartTemporaryDetach} when the container is done
8358      * changing the view.
8359      */
8360     public void onFinishTemporaryDetach() {
8361     }
8362 
8363     /**
8364      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8365      * for this view's window.  Returns null if the view is not currently attached
8366      * to the window.  Normally you will not need to use this directly, but
8367      * just use the standard high-level event callbacks like
8368      * {@link #onKeyDown(int, KeyEvent)}.
8369      */
8370     public KeyEvent.DispatcherState getKeyDispatcherState() {
8371         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8372     }
8373 
8374     /**
8375      * Dispatch a key event before it is processed by any input method
8376      * associated with the view hierarchy.  This can be used to intercept
8377      * key events in special situations before the IME consumes them; a
8378      * typical example would be handling the BACK key to update the application's
8379      * UI instead of allowing the IME to see it and close itself.
8380      *
8381      * @param event The key event to be dispatched.
8382      * @return True if the event was handled, false otherwise.
8383      */
8384     public boolean dispatchKeyEventPreIme(KeyEvent event) {
8385         return onKeyPreIme(event.getKeyCode(), event);
8386     }
8387 
8388     /**
8389      * Dispatch a key event to the next view on the focus path. This path runs
8390      * from the top of the view tree down to the currently focused view. If this
8391      * view has focus, it will dispatch to itself. Otherwise it will dispatch
8392      * the next node down the focus path. This method also fires any key
8393      * listeners.
8394      *
8395      * @param event The key event to be dispatched.
8396      * @return True if the event was handled, false otherwise.
8397      */
8398     public boolean dispatchKeyEvent(KeyEvent event) {
8399         if (mInputEventConsistencyVerifier != null) {
8400             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8401         }
8402 
8403         // Give any attached key listener a first crack at the event.
8404         //noinspection SimplifiableIfStatement
8405         ListenerInfo li = mListenerInfo;
8406         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8407                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8408             return true;
8409         }
8410 
8411         if (event.dispatch(this, mAttachInfo != null
8412                 ? mAttachInfo.mKeyDispatchState : null, this)) {
8413             return true;
8414         }
8415 
8416         if (mInputEventConsistencyVerifier != null) {
8417             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8418         }
8419         return false;
8420     }
8421 
8422     /**
8423      * Dispatches a key shortcut event.
8424      *
8425      * @param event The key event to be dispatched.
8426      * @return True if the event was handled by the view, false otherwise.
8427      */
8428     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8429         return onKeyShortcut(event.getKeyCode(), event);
8430     }
8431 
8432     /**
8433      * Pass the touch screen motion event down to the target view, or this
8434      * view if it is the target.
8435      *
8436      * @param event The motion event to be dispatched.
8437      * @return True if the event was handled by the view, false otherwise.
8438      */
8439     public boolean dispatchTouchEvent(MotionEvent event) {
8440         // If the event should be handled by accessibility focus first.
8441         if (event.isTargetAccessibilityFocus()) {
8442             // We don't have focus or no virtual descendant has it, do not handle the event.
8443             if (!isAccessibilityFocusedViewOrHost()) {
8444                 return false;
8445             }
8446             // We have focus and got the event, then use normal event dispatch.
8447             event.setTargetAccessibilityFocus(false);
8448         }
8449 
8450         boolean result = false;
8451 
8452         if (mInputEventConsistencyVerifier != null) {
8453             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8454         }
8455 
8456         final int actionMasked = event.getActionMasked();
8457         if (actionMasked == MotionEvent.ACTION_DOWN) {
8458             // Defensive cleanup for new gesture
8459             stopNestedScroll();
8460         }
8461 
8462         if (onFilterTouchEventForSecurity(event)) {
8463             //noinspection SimplifiableIfStatement
8464             ListenerInfo li = mListenerInfo;
8465             if (li != null && li.mOnTouchListener != null
8466                     && (mViewFlags & ENABLED_MASK) == ENABLED
8467                     && li.mOnTouchListener.onTouch(this, event)) {
8468                 result = true;
8469             }
8470 
8471             if (!result && onTouchEvent(event)) {
8472                 result = true;
8473             }
8474         }
8475 
8476         if (!result && mInputEventConsistencyVerifier != null) {
8477             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8478         }
8479 
8480         // Clean up after nested scrolls if this is the end of a gesture;
8481         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8482         // of the gesture.
8483         if (actionMasked == MotionEvent.ACTION_UP ||
8484                 actionMasked == MotionEvent.ACTION_CANCEL ||
8485                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8486             stopNestedScroll();
8487         }
8488 
8489         return result;
8490     }
8491 
8492     boolean isAccessibilityFocusedViewOrHost() {
8493         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
8494                 .getAccessibilityFocusedHost() == this);
8495     }
8496 
8497     /**
8498      * Filter the touch event to apply security policies.
8499      *
8500      * @param event The motion event to be filtered.
8501      * @return True if the event should be dispatched, false if the event should be dropped.
8502      *
8503      * @see #getFilterTouchesWhenObscured
8504      */
8505     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8506         //noinspection RedundantIfStatement
8507         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8508                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8509             // Window is obscured, drop this touch.
8510             return false;
8511         }
8512         return true;
8513     }
8514 
8515     /**
8516      * Pass a trackball motion event down to the focused view.
8517      *
8518      * @param event The motion event to be dispatched.
8519      * @return True if the event was handled by the view, false otherwise.
8520      */
8521     public boolean dispatchTrackballEvent(MotionEvent event) {
8522         if (mInputEventConsistencyVerifier != null) {
8523             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8524         }
8525 
8526         return onTrackballEvent(event);
8527     }
8528 
8529     /**
8530      * Dispatch a generic motion event.
8531      * <p>
8532      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8533      * are delivered to the view under the pointer.  All other generic motion events are
8534      * delivered to the focused view.  Hover events are handled specially and are delivered
8535      * to {@link #onHoverEvent(MotionEvent)}.
8536      * </p>
8537      *
8538      * @param event The motion event to be dispatched.
8539      * @return True if the event was handled by the view, false otherwise.
8540      */
8541     public boolean dispatchGenericMotionEvent(MotionEvent event) {
8542         if (mInputEventConsistencyVerifier != null) {
8543             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8544         }
8545 
8546         final int source = event.getSource();
8547         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8548             final int action = event.getAction();
8549             if (action == MotionEvent.ACTION_HOVER_ENTER
8550                     || action == MotionEvent.ACTION_HOVER_MOVE
8551                     || action == MotionEvent.ACTION_HOVER_EXIT) {
8552                 if (dispatchHoverEvent(event)) {
8553                     return true;
8554                 }
8555             } else if (dispatchGenericPointerEvent(event)) {
8556                 return true;
8557             }
8558         } else if (dispatchGenericFocusedEvent(event)) {
8559             return true;
8560         }
8561 
8562         if (dispatchGenericMotionEventInternal(event)) {
8563             return true;
8564         }
8565 
8566         if (mInputEventConsistencyVerifier != null) {
8567             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8568         }
8569         return false;
8570     }
8571 
8572     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8573         //noinspection SimplifiableIfStatement
8574         ListenerInfo li = mListenerInfo;
8575         if (li != null && li.mOnGenericMotionListener != null
8576                 && (mViewFlags & ENABLED_MASK) == ENABLED
8577                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8578             return true;
8579         }
8580 
8581         if (onGenericMotionEvent(event)) {
8582             return true;
8583         }
8584 
8585         if (mInputEventConsistencyVerifier != null) {
8586             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8587         }
8588         return false;
8589     }
8590 
8591     /**
8592      * Dispatch a hover event.
8593      * <p>
8594      * Do not call this method directly.
8595      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8596      * </p>
8597      *
8598      * @param event The motion event to be dispatched.
8599      * @return True if the event was handled by the view, false otherwise.
8600      */
8601     protected boolean dispatchHoverEvent(MotionEvent event) {
8602         ListenerInfo li = mListenerInfo;
8603         //noinspection SimplifiableIfStatement
8604         if (li != null && li.mOnHoverListener != null
8605                 && (mViewFlags & ENABLED_MASK) == ENABLED
8606                 && li.mOnHoverListener.onHover(this, event)) {
8607             return true;
8608         }
8609 
8610         return onHoverEvent(event);
8611     }
8612 
8613     /**
8614      * Returns true if the view has a child to which it has recently sent
8615      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
8616      * it does not have a hovered child, then it must be the innermost hovered view.
8617      * @hide
8618      */
8619     protected boolean hasHoveredChild() {
8620         return false;
8621     }
8622 
8623     /**
8624      * Dispatch a generic motion event to the view under the first pointer.
8625      * <p>
8626      * Do not call this method directly.
8627      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8628      * </p>
8629      *
8630      * @param event The motion event to be dispatched.
8631      * @return True if the event was handled by the view, false otherwise.
8632      */
8633     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8634         return false;
8635     }
8636 
8637     /**
8638      * Dispatch a generic motion event to the currently focused view.
8639      * <p>
8640      * Do not call this method directly.
8641      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8642      * </p>
8643      *
8644      * @param event The motion event to be dispatched.
8645      * @return True if the event was handled by the view, false otherwise.
8646      */
8647     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8648         return false;
8649     }
8650 
8651     /**
8652      * Dispatch a pointer event.
8653      * <p>
8654      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8655      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
8656      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8657      * and should not be expected to handle other pointing device features.
8658      * </p>
8659      *
8660      * @param event The motion event to be dispatched.
8661      * @return True if the event was handled by the view, false otherwise.
8662      * @hide
8663      */
8664     public final boolean dispatchPointerEvent(MotionEvent event) {
8665         if (event.isTouchEvent()) {
8666             return dispatchTouchEvent(event);
8667         } else {
8668             return dispatchGenericMotionEvent(event);
8669         }
8670     }
8671 
8672     /**
8673      * Called when the window containing this view gains or loses window focus.
8674      * ViewGroups should override to route to their children.
8675      *
8676      * @param hasFocus True if the window containing this view now has focus,
8677      *        false otherwise.
8678      */
8679     public void dispatchWindowFocusChanged(boolean hasFocus) {
8680         onWindowFocusChanged(hasFocus);
8681     }
8682 
8683     /**
8684      * Called when the window containing this view gains or loses focus.  Note
8685      * that this is separate from view focus: to receive key events, both
8686      * your view and its window must have focus.  If a window is displayed
8687      * on top of yours that takes input focus, then your own window will lose
8688      * focus but the view focus will remain unchanged.
8689      *
8690      * @param hasWindowFocus True if the window containing this view now has
8691      *        focus, false otherwise.
8692      */
8693     public void onWindowFocusChanged(boolean hasWindowFocus) {
8694         InputMethodManager imm = InputMethodManager.peekInstance();
8695         if (!hasWindowFocus) {
8696             if (isPressed()) {
8697                 setPressed(false);
8698             }
8699             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8700                 imm.focusOut(this);
8701             }
8702             removeLongPressCallback();
8703             removeTapCallback();
8704             onFocusLost();
8705         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8706             imm.focusIn(this);
8707         }
8708         refreshDrawableState();
8709     }
8710 
8711     /**
8712      * Returns true if this view is in a window that currently has window focus.
8713      * Note that this is not the same as the view itself having focus.
8714      *
8715      * @return True if this view is in a window that currently has window focus.
8716      */
8717     public boolean hasWindowFocus() {
8718         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8719     }
8720 
8721     /**
8722      * Dispatch a view visibility change down the view hierarchy.
8723      * ViewGroups should override to route to their children.
8724      * @param changedView The view whose visibility changed. Could be 'this' or
8725      * an ancestor view.
8726      * @param visibility The new visibility of changedView: {@link #VISIBLE},
8727      * {@link #INVISIBLE} or {@link #GONE}.
8728      */
8729     protected void dispatchVisibilityChanged(@NonNull View changedView,
8730             @Visibility int visibility) {
8731         onVisibilityChanged(changedView, visibility);
8732     }
8733 
8734     /**
8735      * Called when the visibility of the view or an ancestor of the view is changed.
8736      * @param changedView The view whose visibility changed. Could be 'this' or
8737      * an ancestor view.
8738      * @param visibility The new visibility of changedView: {@link #VISIBLE},
8739      * {@link #INVISIBLE} or {@link #GONE}.
8740      */
8741     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8742         if (visibility == VISIBLE) {
8743             if (mAttachInfo != null) {
8744                 initialAwakenScrollBars();
8745             } else {
8746                 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8747             }
8748         }
8749     }
8750 
8751     /**
8752      * Dispatch a hint about whether this view is displayed. For instance, when
8753      * a View moves out of the screen, it might receives a display hint indicating
8754      * the view is not displayed. Applications should not <em>rely</em> on this hint
8755      * as there is no guarantee that they will receive one.
8756      *
8757      * @param hint A hint about whether or not this view is displayed:
8758      * {@link #VISIBLE} or {@link #INVISIBLE}.
8759      */
8760     public void dispatchDisplayHint(@Visibility int hint) {
8761         onDisplayHint(hint);
8762     }
8763 
8764     /**
8765      * Gives this view a hint about whether is displayed or not. For instance, when
8766      * a View moves out of the screen, it might receives a display hint indicating
8767      * the view is not displayed. Applications should not <em>rely</em> on this hint
8768      * as there is no guarantee that they will receive one.
8769      *
8770      * @param hint A hint about whether or not this view is displayed:
8771      * {@link #VISIBLE} or {@link #INVISIBLE}.
8772      */
8773     protected void onDisplayHint(@Visibility int hint) {
8774     }
8775 
8776     /**
8777      * Dispatch a window visibility change down the view hierarchy.
8778      * ViewGroups should override to route to their children.
8779      *
8780      * @param visibility The new visibility of the window.
8781      *
8782      * @see #onWindowVisibilityChanged(int)
8783      */
8784     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
8785         onWindowVisibilityChanged(visibility);
8786     }
8787 
8788     /**
8789      * Called when the window containing has change its visibility
8790      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
8791      * that this tells you whether or not your window is being made visible
8792      * to the window manager; this does <em>not</em> tell you whether or not
8793      * your window is obscured by other windows on the screen, even if it
8794      * is itself visible.
8795      *
8796      * @param visibility The new visibility of the window.
8797      */
8798     protected void onWindowVisibilityChanged(@Visibility int visibility) {
8799         if (visibility == VISIBLE) {
8800             initialAwakenScrollBars();
8801         }
8802     }
8803 
8804     /**
8805      * Returns the current visibility of the window this view is attached to
8806      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
8807      *
8808      * @return Returns the current visibility of the view's window.
8809      */
8810     @Visibility
8811     public int getWindowVisibility() {
8812         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
8813     }
8814 
8815     /**
8816      * Retrieve the overall visible display size in which the window this view is
8817      * attached to has been positioned in.  This takes into account screen
8818      * decorations above the window, for both cases where the window itself
8819      * is being position inside of them or the window is being placed under
8820      * then and covered insets are used for the window to position its content
8821      * inside.  In effect, this tells you the available area where content can
8822      * be placed and remain visible to users.
8823      *
8824      * <p>This function requires an IPC back to the window manager to retrieve
8825      * the requested information, so should not be used in performance critical
8826      * code like drawing.
8827      *
8828      * @param outRect Filled in with the visible display frame.  If the view
8829      * is not attached to a window, this is simply the raw display size.
8830      */
8831     public void getWindowVisibleDisplayFrame(Rect outRect) {
8832         if (mAttachInfo != null) {
8833             try {
8834                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
8835             } catch (RemoteException e) {
8836                 return;
8837             }
8838             // XXX This is really broken, and probably all needs to be done
8839             // in the window manager, and we need to know more about whether
8840             // we want the area behind or in front of the IME.
8841             final Rect insets = mAttachInfo.mVisibleInsets;
8842             outRect.left += insets.left;
8843             outRect.top += insets.top;
8844             outRect.right -= insets.right;
8845             outRect.bottom -= insets.bottom;
8846             return;
8847         }
8848         // The view is not attached to a display so we don't have a context.
8849         // Make a best guess about the display size.
8850         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
8851         d.getRectSize(outRect);
8852     }
8853 
8854     /**
8855      * Dispatch a notification about a resource configuration change down
8856      * the view hierarchy.
8857      * ViewGroups should override to route to their children.
8858      *
8859      * @param newConfig The new resource configuration.
8860      *
8861      * @see #onConfigurationChanged(android.content.res.Configuration)
8862      */
8863     public void dispatchConfigurationChanged(Configuration newConfig) {
8864         onConfigurationChanged(newConfig);
8865     }
8866 
8867     /**
8868      * Called when the current configuration of the resources being used
8869      * by the application have changed.  You can use this to decide when
8870      * to reload resources that can changed based on orientation and other
8871      * configuration characterstics.  You only need to use this if you are
8872      * not relying on the normal {@link android.app.Activity} mechanism of
8873      * recreating the activity instance upon a configuration change.
8874      *
8875      * @param newConfig The new resource configuration.
8876      */
8877     protected void onConfigurationChanged(Configuration newConfig) {
8878     }
8879 
8880     /**
8881      * Private function to aggregate all per-view attributes in to the view
8882      * root.
8883      */
8884     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8885         performCollectViewAttributes(attachInfo, visibility);
8886     }
8887 
8888     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8889         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
8890             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
8891                 attachInfo.mKeepScreenOn = true;
8892             }
8893             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
8894             ListenerInfo li = mListenerInfo;
8895             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
8896                 attachInfo.mHasSystemUiListeners = true;
8897             }
8898         }
8899     }
8900 
8901     void needGlobalAttributesUpdate(boolean force) {
8902         final AttachInfo ai = mAttachInfo;
8903         if (ai != null && !ai.mRecomputeGlobalAttributes) {
8904             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
8905                     || ai.mHasSystemUiListeners) {
8906                 ai.mRecomputeGlobalAttributes = true;
8907             }
8908         }
8909     }
8910 
8911     /**
8912      * Returns whether the device is currently in touch mode.  Touch mode is entered
8913      * once the user begins interacting with the device by touch, and affects various
8914      * things like whether focus is always visible to the user.
8915      *
8916      * @return Whether the device is in touch mode.
8917      */
8918     @ViewDebug.ExportedProperty
8919     public boolean isInTouchMode() {
8920         if (mAttachInfo != null) {
8921             return mAttachInfo.mInTouchMode;
8922         } else {
8923             return ViewRootImpl.isInTouchMode();
8924         }
8925     }
8926 
8927     /**
8928      * Returns the context the view is running in, through which it can
8929      * access the current theme, resources, etc.
8930      *
8931      * @return The view's Context.
8932      */
8933     @ViewDebug.CapturedViewProperty
8934     public final Context getContext() {
8935         return mContext;
8936     }
8937 
8938     /**
8939      * Handle a key event before it is processed by any input method
8940      * associated with the view hierarchy.  This can be used to intercept
8941      * key events in special situations before the IME consumes them; a
8942      * typical example would be handling the BACK key to update the application's
8943      * UI instead of allowing the IME to see it and close itself.
8944      *
8945      * @param keyCode The value in event.getKeyCode().
8946      * @param event Description of the key event.
8947      * @return If you handled the event, return true. If you want to allow the
8948      *         event to be handled by the next receiver, return false.
8949      */
8950     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
8951         return false;
8952     }
8953 
8954     /**
8955      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
8956      * KeyEvent.Callback.onKeyDown()}: perform press of the view
8957      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
8958      * is released, if the view is enabled and clickable.
8959      *
8960      * <p>Key presses in software keyboards will generally NOT trigger this listener,
8961      * although some may elect to do so in some situations. Do not rely on this to
8962      * catch software key presses.
8963      *
8964      * @param keyCode A key code that represents the button pressed, from
8965      *                {@link android.view.KeyEvent}.
8966      * @param event   The KeyEvent object that defines the button action.
8967      */
8968     public boolean onKeyDown(int keyCode, KeyEvent event) {
8969         boolean result = false;
8970 
8971         if (KeyEvent.isConfirmKey(keyCode)) {
8972             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8973                 return true;
8974             }
8975             // Long clickable items don't necessarily have to be clickable
8976             if (((mViewFlags & CLICKABLE) == CLICKABLE ||
8977                     (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
8978                     (event.getRepeatCount() == 0)) {
8979                 setPressed(true);
8980                 checkForLongClick(0);
8981                 return true;
8982             }
8983         }
8984         return result;
8985     }
8986 
8987     /**
8988      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
8989      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
8990      * the event).
8991      * <p>Key presses in software keyboards will generally NOT trigger this listener,
8992      * although some may elect to do so in some situations. Do not rely on this to
8993      * catch software key presses.
8994      */
8995     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
8996         return false;
8997     }
8998 
8999     /**
9000      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9001      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9002      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9003      * {@link KeyEvent#KEYCODE_ENTER} is released.
9004      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9005      * although some may elect to do so in some situations. Do not rely on this to
9006      * catch software key presses.
9007      *
9008      * @param keyCode A key code that represents the button pressed, from
9009      *                {@link android.view.KeyEvent}.
9010      * @param event   The KeyEvent object that defines the button action.
9011      */
9012     public boolean onKeyUp(int keyCode, KeyEvent event) {
9013         if (KeyEvent.isConfirmKey(keyCode)) {
9014             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9015                 return true;
9016             }
9017             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9018                 setPressed(false);
9019 
9020                 if (!mHasPerformedLongPress) {
9021                     // This is a tap, so remove the longpress check
9022                     removeLongPressCallback();
9023                     return performClick();
9024                 }
9025             }
9026         }
9027         return false;
9028     }
9029 
9030     /**
9031      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9032      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9033      * the event).
9034      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9035      * although some may elect to do so in some situations. Do not rely on this to
9036      * catch software key presses.
9037      *
9038      * @param keyCode     A key code that represents the button pressed, from
9039      *                    {@link android.view.KeyEvent}.
9040      * @param repeatCount The number of times the action was made.
9041      * @param event       The KeyEvent object that defines the button action.
9042      */
9043     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9044         return false;
9045     }
9046 
9047     /**
9048      * Called on the focused view when a key shortcut event is not handled.
9049      * Override this method to implement local key shortcuts for the View.
9050      * Key shortcuts can also be implemented by setting the
9051      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9052      *
9053      * @param keyCode The value in event.getKeyCode().
9054      * @param event Description of the key event.
9055      * @return If you handled the event, return true. If you want to allow the
9056      *         event to be handled by the next receiver, return false.
9057      */
9058     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9059         return false;
9060     }
9061 
9062     /**
9063      * Check whether the called view is a text editor, in which case it
9064      * would make sense to automatically display a soft input window for
9065      * it.  Subclasses should override this if they implement
9066      * {@link #onCreateInputConnection(EditorInfo)} to return true if
9067      * a call on that method would return a non-null InputConnection, and
9068      * they are really a first-class editor that the user would normally
9069      * start typing on when the go into a window containing your view.
9070      *
9071      * <p>The default implementation always returns false.  This does
9072      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9073      * will not be called or the user can not otherwise perform edits on your
9074      * view; it is just a hint to the system that this is not the primary
9075      * purpose of this view.
9076      *
9077      * @return Returns true if this view is a text editor, else false.
9078      */
9079     public boolean onCheckIsTextEditor() {
9080         return false;
9081     }
9082 
9083     /**
9084      * Create a new InputConnection for an InputMethod to interact
9085      * with the view.  The default implementation returns null, since it doesn't
9086      * support input methods.  You can override this to implement such support.
9087      * This is only needed for views that take focus and text input.
9088      *
9089      * <p>When implementing this, you probably also want to implement
9090      * {@link #onCheckIsTextEditor()} to indicate you will return a
9091      * non-null InputConnection.</p>
9092      *
9093      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9094      * object correctly and in its entirety, so that the connected IME can rely
9095      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9096      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9097      * must be filled in with the correct cursor position for IMEs to work correctly
9098      * with your application.</p>
9099      *
9100      * @param outAttrs Fill in with attribute information about the connection.
9101      */
9102     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9103         return null;
9104     }
9105 
9106     /**
9107      * Called by the {@link android.view.inputmethod.InputMethodManager}
9108      * when a view who is not the current
9109      * input connection target is trying to make a call on the manager.  The
9110      * default implementation returns false; you can override this to return
9111      * true for certain views if you are performing InputConnection proxying
9112      * to them.
9113      * @param view The View that is making the InputMethodManager call.
9114      * @return Return true to allow the call, false to reject.
9115      */
9116     public boolean checkInputConnectionProxy(View view) {
9117         return false;
9118     }
9119 
9120     /**
9121      * Show the context menu for this view. It is not safe to hold on to the
9122      * menu after returning from this method.
9123      *
9124      * You should normally not overload this method. Overload
9125      * {@link #onCreateContextMenu(ContextMenu)} or define an
9126      * {@link OnCreateContextMenuListener} to add items to the context menu.
9127      *
9128      * @param menu The context menu to populate
9129      */
9130     public void createContextMenu(ContextMenu menu) {
9131         ContextMenuInfo menuInfo = getContextMenuInfo();
9132 
9133         // Sets the current menu info so all items added to menu will have
9134         // my extra info set.
9135         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9136 
9137         onCreateContextMenu(menu);
9138         ListenerInfo li = mListenerInfo;
9139         if (li != null && li.mOnCreateContextMenuListener != null) {
9140             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9141         }
9142 
9143         // Clear the extra information so subsequent items that aren't mine don't
9144         // have my extra info.
9145         ((MenuBuilder)menu).setCurrentMenuInfo(null);
9146 
9147         if (mParent != null) {
9148             mParent.createContextMenu(menu);
9149         }
9150     }
9151 
9152     /**
9153      * Views should implement this if they have extra information to associate
9154      * with the context menu. The return result is supplied as a parameter to
9155      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9156      * callback.
9157      *
9158      * @return Extra information about the item for which the context menu
9159      *         should be shown. This information will vary across different
9160      *         subclasses of View.
9161      */
9162     protected ContextMenuInfo getContextMenuInfo() {
9163         return null;
9164     }
9165 
9166     /**
9167      * Views should implement this if the view itself is going to add items to
9168      * the context menu.
9169      *
9170      * @param menu the context menu to populate
9171      */
9172     protected void onCreateContextMenu(ContextMenu menu) {
9173     }
9174 
9175     /**
9176      * Implement this method to handle trackball motion events.  The
9177      * <em>relative</em> movement of the trackball since the last event
9178      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9179      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
9180      * that a movement of 1 corresponds to the user pressing one DPAD key (so
9181      * they will often be fractional values, representing the more fine-grained
9182      * movement information available from a trackball).
9183      *
9184      * @param event The motion event.
9185      * @return True if the event was handled, false otherwise.
9186      */
9187     public boolean onTrackballEvent(MotionEvent event) {
9188         return false;
9189     }
9190 
9191     /**
9192      * Implement this method to handle generic motion events.
9193      * <p>
9194      * Generic motion events describe joystick movements, mouse hovers, track pad
9195      * touches, scroll wheel movements and other input events.  The
9196      * {@link MotionEvent#getSource() source} of the motion event specifies
9197      * the class of input that was received.  Implementations of this method
9198      * must examine the bits in the source before processing the event.
9199      * The following code example shows how this is done.
9200      * </p><p>
9201      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9202      * are delivered to the view under the pointer.  All other generic motion events are
9203      * delivered to the focused view.
9204      * </p>
9205      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9206      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9207      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
9208      *             // process the joystick movement...
9209      *             return true;
9210      *         }
9211      *     }
9212      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9213      *         switch (event.getAction()) {
9214      *             case MotionEvent.ACTION_HOVER_MOVE:
9215      *                 // process the mouse hover movement...
9216      *                 return true;
9217      *             case MotionEvent.ACTION_SCROLL:
9218      *                 // process the scroll wheel movement...
9219      *                 return true;
9220      *         }
9221      *     }
9222      *     return super.onGenericMotionEvent(event);
9223      * }</pre>
9224      *
9225      * @param event The generic motion event being processed.
9226      * @return True if the event was handled, false otherwise.
9227      */
9228     public boolean onGenericMotionEvent(MotionEvent event) {
9229         return false;
9230     }
9231 
9232     /**
9233      * Implement this method to handle hover events.
9234      * <p>
9235      * This method is called whenever a pointer is hovering into, over, or out of the
9236      * bounds of a view and the view is not currently being touched.
9237      * Hover events are represented as pointer events with action
9238      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9239      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9240      * </p>
9241      * <ul>
9242      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9243      * when the pointer enters the bounds of the view.</li>
9244      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9245      * when the pointer has already entered the bounds of the view and has moved.</li>
9246      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9247      * when the pointer has exited the bounds of the view or when the pointer is
9248      * about to go down due to a button click, tap, or similar user action that
9249      * causes the view to be touched.</li>
9250      * </ul>
9251      * <p>
9252      * The view should implement this method to return true to indicate that it is
9253      * handling the hover event, such as by changing its drawable state.
9254      * </p><p>
9255      * The default implementation calls {@link #setHovered} to update the hovered state
9256      * of the view when a hover enter or hover exit event is received, if the view
9257      * is enabled and is clickable.  The default implementation also sends hover
9258      * accessibility events.
9259      * </p>
9260      *
9261      * @param event The motion event that describes the hover.
9262      * @return True if the view handled the hover event.
9263      *
9264      * @see #isHovered
9265      * @see #setHovered
9266      * @see #onHoverChanged
9267      */
9268     public boolean onHoverEvent(MotionEvent event) {
9269         // The root view may receive hover (or touch) events that are outside the bounds of
9270         // the window.  This code ensures that we only send accessibility events for
9271         // hovers that are actually within the bounds of the root view.
9272         final int action = event.getActionMasked();
9273         if (!mSendingHoverAccessibilityEvents) {
9274             if ((action == MotionEvent.ACTION_HOVER_ENTER
9275                     || action == MotionEvent.ACTION_HOVER_MOVE)
9276                     && !hasHoveredChild()
9277                     && pointInView(event.getX(), event.getY())) {
9278                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9279                 mSendingHoverAccessibilityEvents = true;
9280             }
9281         } else {
9282             if (action == MotionEvent.ACTION_HOVER_EXIT
9283                     || (action == MotionEvent.ACTION_MOVE
9284                             && !pointInView(event.getX(), event.getY()))) {
9285                 mSendingHoverAccessibilityEvents = false;
9286                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9287             }
9288         }
9289 
9290         if (isHoverable()) {
9291             switch (action) {
9292                 case MotionEvent.ACTION_HOVER_ENTER:
9293                     setHovered(true);
9294                     break;
9295                 case MotionEvent.ACTION_HOVER_EXIT:
9296                     setHovered(false);
9297                     break;
9298             }
9299 
9300             // Dispatch the event to onGenericMotionEvent before returning true.
9301             // This is to provide compatibility with existing applications that
9302             // handled HOVER_MOVE events in onGenericMotionEvent and that would
9303             // break because of the new default handling for hoverable views
9304             // in onHoverEvent.
9305             // Note that onGenericMotionEvent will be called by default when
9306             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9307             dispatchGenericMotionEventInternal(event);
9308             // The event was already handled by calling setHovered(), so always
9309             // return true.
9310             return true;
9311         }
9312 
9313         return false;
9314     }
9315 
9316     /**
9317      * Returns true if the view should handle {@link #onHoverEvent}
9318      * by calling {@link #setHovered} to change its hovered state.
9319      *
9320      * @return True if the view is hoverable.
9321      */
9322     private boolean isHoverable() {
9323         final int viewFlags = mViewFlags;
9324         if ((viewFlags & ENABLED_MASK) == DISABLED) {
9325             return false;
9326         }
9327 
9328         return (viewFlags & CLICKABLE) == CLICKABLE
9329                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9330     }
9331 
9332     /**
9333      * Returns true if the view is currently hovered.
9334      *
9335      * @return True if the view is currently hovered.
9336      *
9337      * @see #setHovered
9338      * @see #onHoverChanged
9339      */
9340     @ViewDebug.ExportedProperty
9341     public boolean isHovered() {
9342         return (mPrivateFlags & PFLAG_HOVERED) != 0;
9343     }
9344 
9345     /**
9346      * Sets whether the view is currently hovered.
9347      * <p>
9348      * Calling this method also changes the drawable state of the view.  This
9349      * enables the view to react to hover by using different drawable resources
9350      * to change its appearance.
9351      * </p><p>
9352      * The {@link #onHoverChanged} method is called when the hovered state changes.
9353      * </p>
9354      *
9355      * @param hovered True if the view is hovered.
9356      *
9357      * @see #isHovered
9358      * @see #onHoverChanged
9359      */
9360     public void setHovered(boolean hovered) {
9361         if (hovered) {
9362             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9363                 mPrivateFlags |= PFLAG_HOVERED;
9364                 refreshDrawableState();
9365                 onHoverChanged(true);
9366             }
9367         } else {
9368             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9369                 mPrivateFlags &= ~PFLAG_HOVERED;
9370                 refreshDrawableState();
9371                 onHoverChanged(false);
9372             }
9373         }
9374     }
9375 
9376     /**
9377      * Implement this method to handle hover state changes.
9378      * <p>
9379      * This method is called whenever the hover state changes as a result of a
9380      * call to {@link #setHovered}.
9381      * </p>
9382      *
9383      * @param hovered The current hover state, as returned by {@link #isHovered}.
9384      *
9385      * @see #isHovered
9386      * @see #setHovered
9387      */
9388     public void onHoverChanged(boolean hovered) {
9389     }
9390 
9391     /**
9392      * Implement this method to handle touch screen motion events.
9393      * <p>
9394      * If this method is used to detect click actions, it is recommended that
9395      * the actions be performed by implementing and calling
9396      * {@link #performClick()}. This will ensure consistent system behavior,
9397      * including:
9398      * <ul>
9399      * <li>obeying click sound preferences
9400      * <li>dispatching OnClickListener calls
9401      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9402      * accessibility features are enabled
9403      * </ul>
9404      *
9405      * @param event The motion event.
9406      * @return True if the event was handled, false otherwise.
9407      */
9408     public boolean onTouchEvent(MotionEvent event) {
9409         final float x = event.getX();
9410         final float y = event.getY();
9411         final int viewFlags = mViewFlags;
9412 
9413         if ((viewFlags & ENABLED_MASK) == DISABLED) {
9414             if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9415                 setPressed(false);
9416             }
9417             // A disabled view that is clickable still consumes the touch
9418             // events, it just doesn't respond to them.
9419             return (((viewFlags & CLICKABLE) == CLICKABLE ||
9420                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9421         }
9422 
9423         if (mTouchDelegate != null) {
9424             if (mTouchDelegate.onTouchEvent(event)) {
9425                 return true;
9426             }
9427         }
9428 
9429         if (((viewFlags & CLICKABLE) == CLICKABLE ||
9430                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9431             switch (event.getAction()) {
9432                 case MotionEvent.ACTION_UP:
9433                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9434                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9435                         // take focus if we don't have it already and we should in
9436                         // touch mode.
9437                         boolean focusTaken = false;
9438                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9439                             focusTaken = requestFocus();
9440                         }
9441 
9442                         if (prepressed) {
9443                             // The button is being released before we actually
9444                             // showed it as pressed.  Make it show the pressed
9445                             // state now (before scheduling the click) to ensure
9446                             // the user sees it.
9447                             setPressed(true, x, y);
9448                        }
9449 
9450                         if (!mHasPerformedLongPress) {
9451                             // This is a tap, so remove the longpress check
9452                             removeLongPressCallback();
9453 
9454                             // Only perform take click actions if we were in the pressed state
9455                             if (!focusTaken) {
9456                                 // Use a Runnable and post this rather than calling
9457                                 // performClick directly. This lets other visual state
9458                                 // of the view update before click actions start.
9459                                 if (mPerformClick == null) {
9460                                     mPerformClick = new PerformClick();
9461                                 }
9462                                 if (!post(mPerformClick)) {
9463                                     performClick();
9464                                 }
9465                             }
9466                         }
9467 
9468                         if (mUnsetPressedState == null) {
9469                             mUnsetPressedState = new UnsetPressedState();
9470                         }
9471 
9472                         if (prepressed) {
9473                             postDelayed(mUnsetPressedState,
9474                                     ViewConfiguration.getPressedStateDuration());
9475                         } else if (!post(mUnsetPressedState)) {
9476                             // If the post failed, unpress right now
9477                             mUnsetPressedState.run();
9478                         }
9479 
9480                         removeTapCallback();
9481                     }
9482                     break;
9483 
9484                 case MotionEvent.ACTION_DOWN:
9485                     mHasPerformedLongPress = false;
9486 
9487                     if (performButtonActionOnTouchDown(event)) {
9488                         break;
9489                     }
9490 
9491                     // Walk up the hierarchy to determine if we're inside a scrolling container.
9492                     boolean isInScrollingContainer = isInScrollingContainer();
9493 
9494                     // For views inside a scrolling container, delay the pressed feedback for
9495                     // a short period in case this is a scroll.
9496                     if (isInScrollingContainer) {
9497                         mPrivateFlags |= PFLAG_PREPRESSED;
9498                         if (mPendingCheckForTap == null) {
9499                             mPendingCheckForTap = new CheckForTap();
9500                         }
9501                         mPendingCheckForTap.x = event.getX();
9502                         mPendingCheckForTap.y = event.getY();
9503                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9504                     } else {
9505                         // Not inside a scrolling container, so show the feedback right away
9506                         setPressed(true, x, y);
9507                         checkForLongClick(0);
9508                     }
9509                     break;
9510 
9511                 case MotionEvent.ACTION_CANCEL:
9512                     setPressed(false);
9513                     removeTapCallback();
9514                     removeLongPressCallback();
9515                     break;
9516 
9517                 case MotionEvent.ACTION_MOVE:
9518                     drawableHotspotChanged(x, y);
9519 
9520                     // Be lenient about moving outside of buttons
9521                     if (!pointInView(x, y, mTouchSlop)) {
9522                         // Outside button
9523                         removeTapCallback();
9524                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9525                             // Remove any future long press/tap checks
9526                             removeLongPressCallback();
9527 
9528                             setPressed(false);
9529                         }
9530                     }
9531                     break;
9532             }
9533 
9534             return true;
9535         }
9536 
9537         return false;
9538     }
9539 
9540     /**
9541      * @hide
9542      */
9543     public boolean isInScrollingContainer() {
9544         ViewParent p = getParent();
9545         while (p != null && p instanceof ViewGroup) {
9546             if (((ViewGroup) p).shouldDelayChildPressedState()) {
9547                 return true;
9548             }
9549             p = p.getParent();
9550         }
9551         return false;
9552     }
9553 
9554     /**
9555      * Remove the longpress detection timer.
9556      */
9557     private void removeLongPressCallback() {
9558         if (mPendingCheckForLongPress != null) {
9559           removeCallbacks(mPendingCheckForLongPress);
9560         }
9561     }
9562 
9563     /**
9564      * Remove the pending click action
9565      */
9566     private void removePerformClickCallback() {
9567         if (mPerformClick != null) {
9568             removeCallbacks(mPerformClick);
9569         }
9570     }
9571 
9572     /**
9573      * Remove the prepress detection timer.
9574      */
9575     private void removeUnsetPressCallback() {
9576         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9577             setPressed(false);
9578             removeCallbacks(mUnsetPressedState);
9579         }
9580     }
9581 
9582     /**
9583      * Remove the tap detection timer.
9584      */
9585     private void removeTapCallback() {
9586         if (mPendingCheckForTap != null) {
9587             mPrivateFlags &= ~PFLAG_PREPRESSED;
9588             removeCallbacks(mPendingCheckForTap);
9589         }
9590     }
9591 
9592     /**
9593      * Cancels a pending long press.  Your subclass can use this if you
9594      * want the context menu to come up if the user presses and holds
9595      * at the same place, but you don't want it to come up if they press
9596      * and then move around enough to cause scrolling.
9597      */
9598     public void cancelLongPress() {
9599         removeLongPressCallback();
9600 
9601         /*
9602          * The prepressed state handled by the tap callback is a display
9603          * construct, but the tap callback will post a long press callback
9604          * less its own timeout. Remove it here.
9605          */
9606         removeTapCallback();
9607     }
9608 
9609     /**
9610      * Remove the pending callback for sending a
9611      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9612      */
9613     private void removeSendViewScrolledAccessibilityEventCallback() {
9614         if (mSendViewScrolledAccessibilityEvent != null) {
9615             removeCallbacks(mSendViewScrolledAccessibilityEvent);
9616             mSendViewScrolledAccessibilityEvent.mIsPending = false;
9617         }
9618     }
9619 
9620     /**
9621      * Sets the TouchDelegate for this View.
9622      */
9623     public void setTouchDelegate(TouchDelegate delegate) {
9624         mTouchDelegate = delegate;
9625     }
9626 
9627     /**
9628      * Gets the TouchDelegate for this View.
9629      */
9630     public TouchDelegate getTouchDelegate() {
9631         return mTouchDelegate;
9632     }
9633 
9634     /**
9635      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
9636      *
9637      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
9638      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
9639      * available. This method should only be called for touch events.
9640      *
9641      * <p class="note">This api is not intended for most applications. Buffered dispatch
9642      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
9643      * streams will not improve your input latency. Side effects include: increased latency,
9644      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
9645      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
9646      * you.</p>
9647      */
9648     public final void requestUnbufferedDispatch(MotionEvent event) {
9649         final int action = event.getAction();
9650         if (mAttachInfo == null
9651                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
9652                 || !event.isTouchEvent()) {
9653             return;
9654         }
9655         mAttachInfo.mUnbufferedDispatchRequested = true;
9656     }
9657 
9658     /**
9659      * Set flags controlling behavior of this view.
9660      *
9661      * @param flags Constant indicating the value which should be set
9662      * @param mask Constant indicating the bit range that should be changed
9663      */
9664     void setFlags(int flags, int mask) {
9665         final boolean accessibilityEnabled =
9666                 AccessibilityManager.getInstance(mContext).isEnabled();
9667         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9668 
9669         int old = mViewFlags;
9670         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9671 
9672         int changed = mViewFlags ^ old;
9673         if (changed == 0) {
9674             return;
9675         }
9676         int privateFlags = mPrivateFlags;
9677 
9678         /* Check if the FOCUSABLE bit has changed */
9679         if (((changed & FOCUSABLE_MASK) != 0) &&
9680                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9681             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9682                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9683                 /* Give up focus if we are no longer focusable */
9684                 clearFocus();
9685             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9686                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9687                 /*
9688                  * Tell the view system that we are now available to take focus
9689                  * if no one else already has it.
9690                  */
9691                 if (mParent != null) mParent.focusableViewAvailable(this);
9692             }
9693         }
9694 
9695         final int newVisibility = flags & VISIBILITY_MASK;
9696         if (newVisibility == VISIBLE) {
9697             if ((changed & VISIBILITY_MASK) != 0) {
9698                 /*
9699                  * If this view is becoming visible, invalidate it in case it changed while
9700                  * it was not visible. Marking it drawn ensures that the invalidation will
9701                  * go through.
9702                  */
9703                 mPrivateFlags |= PFLAG_DRAWN;
9704                 invalidate(true);
9705 
9706                 needGlobalAttributesUpdate(true);
9707 
9708                 // a view becoming visible is worth notifying the parent
9709                 // about in case nothing has focus.  even if this specific view
9710                 // isn't focusable, it may contain something that is, so let
9711                 // the root view try to give this focus if nothing else does.
9712                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9713                     mParent.focusableViewAvailable(this);
9714                 }
9715             }
9716         }
9717 
9718         /* Check if the GONE bit has changed */
9719         if ((changed & GONE) != 0) {
9720             needGlobalAttributesUpdate(false);
9721             requestLayout();
9722 
9723             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9724                 if (hasFocus()) clearFocus();
9725                 clearAccessibilityFocus();
9726                 destroyDrawingCache();
9727                 if (mParent instanceof View) {
9728                     // GONE views noop invalidation, so invalidate the parent
9729                     ((View) mParent).invalidate(true);
9730                 }
9731                 // Mark the view drawn to ensure that it gets invalidated properly the next
9732                 // time it is visible and gets invalidated
9733                 mPrivateFlags |= PFLAG_DRAWN;
9734             }
9735             if (mAttachInfo != null) {
9736                 mAttachInfo.mViewVisibilityChanged = true;
9737             }
9738         }
9739 
9740         /* Check if the VISIBLE bit has changed */
9741         if ((changed & INVISIBLE) != 0) {
9742             needGlobalAttributesUpdate(false);
9743             /*
9744              * If this view is becoming invisible, set the DRAWN flag so that
9745              * the next invalidate() will not be skipped.
9746              */
9747             mPrivateFlags |= PFLAG_DRAWN;
9748 
9749             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9750                 // root view becoming invisible shouldn't clear focus and accessibility focus
9751                 if (getRootView() != this) {
9752                     if (hasFocus()) clearFocus();
9753                     clearAccessibilityFocus();
9754                 }
9755             }
9756             if (mAttachInfo != null) {
9757                 mAttachInfo.mViewVisibilityChanged = true;
9758             }
9759         }
9760 
9761         if ((changed & VISIBILITY_MASK) != 0) {
9762             // If the view is invisible, cleanup its display list to free up resources
9763             if (newVisibility != VISIBLE && mAttachInfo != null) {
9764                 cleanupDraw();
9765             }
9766 
9767             if (mParent instanceof ViewGroup) {
9768                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
9769                         (changed & VISIBILITY_MASK), newVisibility);
9770                 ((View) mParent).invalidate(true);
9771             } else if (mParent != null) {
9772                 mParent.invalidateChild(this, null);
9773             }
9774             dispatchVisibilityChanged(this, newVisibility);
9775 
9776             notifySubtreeAccessibilityStateChangedIfNeeded();
9777         }
9778 
9779         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
9780             destroyDrawingCache();
9781         }
9782 
9783         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
9784             destroyDrawingCache();
9785             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9786             invalidateParentCaches();
9787         }
9788 
9789         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
9790             destroyDrawingCache();
9791             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9792         }
9793 
9794         if ((changed & DRAW_MASK) != 0) {
9795             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
9796                 if (mBackground != null) {
9797                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9798                     mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
9799                 } else {
9800                     mPrivateFlags |= PFLAG_SKIP_DRAW;
9801                 }
9802             } else {
9803                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9804             }
9805             requestLayout();
9806             invalidate(true);
9807         }
9808 
9809         if ((changed & KEEP_SCREEN_ON) != 0) {
9810             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
9811                 mParent.recomputeViewAttributes(this);
9812             }
9813         }
9814 
9815         if (accessibilityEnabled) {
9816             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
9817                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
9818                 if (oldIncludeForAccessibility != includeForAccessibility()) {
9819                     notifySubtreeAccessibilityStateChangedIfNeeded();
9820                 } else {
9821                     notifyViewAccessibilityStateChangedIfNeeded(
9822                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9823                 }
9824             } else if ((changed & ENABLED_MASK) != 0) {
9825                 notifyViewAccessibilityStateChangedIfNeeded(
9826                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9827             }
9828         }
9829     }
9830 
9831     /**
9832      * Change the view's z order in the tree, so it's on top of other sibling
9833      * views. This ordering change may affect layout, if the parent container
9834      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
9835      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
9836      * method should be followed by calls to {@link #requestLayout()} and
9837      * {@link View#invalidate()} on the view's parent to force the parent to redraw
9838      * with the new child ordering.
9839      *
9840      * @see ViewGroup#bringChildToFront(View)
9841      */
9842     public void bringToFront() {
9843         if (mParent != null) {
9844             mParent.bringChildToFront(this);
9845         }
9846     }
9847 
9848     /**
9849      * This is called in response to an internal scroll in this view (i.e., the
9850      * view scrolled its own contents). This is typically as a result of
9851      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
9852      * called.
9853      *
9854      * @param l Current horizontal scroll origin.
9855      * @param t Current vertical scroll origin.
9856      * @param oldl Previous horizontal scroll origin.
9857      * @param oldt Previous vertical scroll origin.
9858      */
9859     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
9860         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9861             postSendViewScrolledAccessibilityEventCallback();
9862         }
9863 
9864         mBackgroundSizeChanged = true;
9865 
9866         final AttachInfo ai = mAttachInfo;
9867         if (ai != null) {
9868             ai.mViewScrollChanged = true;
9869         }
9870 
9871         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
9872             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
9873         }
9874     }
9875 
9876     /**
9877      * Interface definition for a callback to be invoked when the scroll
9878      * position of a view changes.
9879      *
9880      * @hide Only used internally.
9881      */
9882     public interface OnScrollChangeListener {
9883         /**
9884          * Called when the scroll position of a view changes.
9885          *
9886          * @param v The view whose scroll position has changed.
9887          * @param scrollX Current horizontal scroll origin.
9888          * @param scrollY Current vertical scroll origin.
9889          * @param oldScrollX Previous horizontal scroll origin.
9890          * @param oldScrollY Previous vertical scroll origin.
9891          */
9892         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
9893     }
9894 
9895     /**
9896      * Interface definition for a callback to be invoked when the layout bounds of a view
9897      * changes due to layout processing.
9898      */
9899     public interface OnLayoutChangeListener {
9900         /**
9901          * Called when the layout bounds of a view changes due to layout processing.
9902          *
9903          * @param v The view whose bounds have changed.
9904          * @param left The new value of the view's left property.
9905          * @param top The new value of the view's top property.
9906          * @param right The new value of the view's right property.
9907          * @param bottom The new value of the view's bottom property.
9908          * @param oldLeft The previous value of the view's left property.
9909          * @param oldTop The previous value of the view's top property.
9910          * @param oldRight The previous value of the view's right property.
9911          * @param oldBottom The previous value of the view's bottom property.
9912          */
9913         void onLayoutChange(View v, int left, int top, int right, int bottom,
9914             int oldLeft, int oldTop, int oldRight, int oldBottom);
9915     }
9916 
9917     /**
9918      * This is called during layout when the size of this view has changed. If
9919      * you were just added to the view hierarchy, you're called with the old
9920      * values of 0.
9921      *
9922      * @param w Current width of this view.
9923      * @param h Current height of this view.
9924      * @param oldw Old width of this view.
9925      * @param oldh Old height of this view.
9926      */
9927     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
9928     }
9929 
9930     /**
9931      * Called by draw to draw the child views. This may be overridden
9932      * by derived classes to gain control just before its children are drawn
9933      * (but after its own view has been drawn).
9934      * @param canvas the canvas on which to draw the view
9935      */
9936     protected void dispatchDraw(Canvas canvas) {
9937 
9938     }
9939 
9940     /**
9941      * Gets the parent of this view. Note that the parent is a
9942      * ViewParent and not necessarily a View.
9943      *
9944      * @return Parent of this view.
9945      */
9946     public final ViewParent getParent() {
9947         return mParent;
9948     }
9949 
9950     /**
9951      * Set the horizontal scrolled position of your view. This will cause a call to
9952      * {@link #onScrollChanged(int, int, int, int)} and the view will be
9953      * invalidated.
9954      * @param value the x position to scroll to
9955      */
9956     public void setScrollX(int value) {
9957         scrollTo(value, mScrollY);
9958     }
9959 
9960     /**
9961      * Set the vertical scrolled position of your view. This will cause a call to
9962      * {@link #onScrollChanged(int, int, int, int)} and the view will be
9963      * invalidated.
9964      * @param value the y position to scroll to
9965      */
9966     public void setScrollY(int value) {
9967         scrollTo(mScrollX, value);
9968     }
9969 
9970     /**
9971      * Return the scrolled left position of this view. This is the left edge of
9972      * the displayed part of your view. You do not need to draw any pixels
9973      * farther left, since those are outside of the frame of your view on
9974      * screen.
9975      *
9976      * @return The left edge of the displayed part of your view, in pixels.
9977      */
9978     public final int getScrollX() {
9979         return mScrollX;
9980     }
9981 
9982     /**
9983      * Return the scrolled top position of this view. This is the top edge of
9984      * the displayed part of your view. You do not need to draw any pixels above
9985      * it, since those are outside of the frame of your view on screen.
9986      *
9987      * @return The top edge of the displayed part of your view, in pixels.
9988      */
9989     public final int getScrollY() {
9990         return mScrollY;
9991     }
9992 
9993     /**
9994      * Return the width of the your view.
9995      *
9996      * @return The width of your view, in pixels.
9997      */
9998     @ViewDebug.ExportedProperty(category = "layout")
9999     public final int getWidth() {
10000         return mRight - mLeft;
10001     }
10002 
10003     /**
10004      * Return the height of your view.
10005      *
10006      * @return The height of your view, in pixels.
10007      */
10008     @ViewDebug.ExportedProperty(category = "layout")
10009     public final int getHeight() {
10010         return mBottom - mTop;
10011     }
10012 
10013     /**
10014      * Return the visible drawing bounds of your view. Fills in the output
10015      * rectangle with the values from getScrollX(), getScrollY(),
10016      * getWidth(), and getHeight(). These bounds do not account for any
10017      * transformation properties currently set on the view, such as
10018      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10019      *
10020      * @param outRect The (scrolled) drawing bounds of the view.
10021      */
10022     public void getDrawingRect(Rect outRect) {
10023         outRect.left = mScrollX;
10024         outRect.top = mScrollY;
10025         outRect.right = mScrollX + (mRight - mLeft);
10026         outRect.bottom = mScrollY + (mBottom - mTop);
10027     }
10028 
10029     /**
10030      * Like {@link #getMeasuredWidthAndState()}, but only returns the
10031      * raw width component (that is the result is masked by
10032      * {@link #MEASURED_SIZE_MASK}).
10033      *
10034      * @return The raw measured width of this view.
10035      */
10036     public final int getMeasuredWidth() {
10037         return mMeasuredWidth & MEASURED_SIZE_MASK;
10038     }
10039 
10040     /**
10041      * Return the full width measurement information for this view as computed
10042      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10043      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10044      * This should be used during measurement and layout calculations only. Use
10045      * {@link #getWidth()} to see how wide a view is after layout.
10046      *
10047      * @return The measured width of this view as a bit mask.
10048      */
10049     public final int getMeasuredWidthAndState() {
10050         return mMeasuredWidth;
10051     }
10052 
10053     /**
10054      * Like {@link #getMeasuredHeightAndState()}, but only returns the
10055      * raw width component (that is the result is masked by
10056      * {@link #MEASURED_SIZE_MASK}).
10057      *
10058      * @return The raw measured height of this view.
10059      */
10060     public final int getMeasuredHeight() {
10061         return mMeasuredHeight & MEASURED_SIZE_MASK;
10062     }
10063 
10064     /**
10065      * Return the full height measurement information for this view as computed
10066      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10067      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10068      * This should be used during measurement and layout calculations only. Use
10069      * {@link #getHeight()} to see how wide a view is after layout.
10070      *
10071      * @return The measured width of this view as a bit mask.
10072      */
10073     public final int getMeasuredHeightAndState() {
10074         return mMeasuredHeight;
10075     }
10076 
10077     /**
10078      * Return only the state bits of {@link #getMeasuredWidthAndState()}
10079      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10080      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10081      * and the height component is at the shifted bits
10082      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10083      */
10084     public final int getMeasuredState() {
10085         return (mMeasuredWidth&MEASURED_STATE_MASK)
10086                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10087                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10088     }
10089 
10090     /**
10091      * The transform matrix of this view, which is calculated based on the current
10092      * rotation, scale, and pivot properties.
10093      *
10094      * @see #getRotation()
10095      * @see #getScaleX()
10096      * @see #getScaleY()
10097      * @see #getPivotX()
10098      * @see #getPivotY()
10099      * @return The current transform matrix for the view
10100      */
10101     public Matrix getMatrix() {
10102         ensureTransformationInfo();
10103         final Matrix matrix = mTransformationInfo.mMatrix;
10104         mRenderNode.getMatrix(matrix);
10105         return matrix;
10106     }
10107 
10108     /**
10109      * Returns true if the transform matrix is the identity matrix.
10110      * Recomputes the matrix if necessary.
10111      *
10112      * @return True if the transform matrix is the identity matrix, false otherwise.
10113      */
10114     final boolean hasIdentityMatrix() {
10115         return mRenderNode.hasIdentityMatrix();
10116     }
10117 
10118     void ensureTransformationInfo() {
10119         if (mTransformationInfo == null) {
10120             mTransformationInfo = new TransformationInfo();
10121         }
10122     }
10123 
10124    /**
10125      * Utility method to retrieve the inverse of the current mMatrix property.
10126      * We cache the matrix to avoid recalculating it when transform properties
10127      * have not changed.
10128      *
10129      * @return The inverse of the current matrix of this view.
10130      * @hide
10131      */
10132     public final Matrix getInverseMatrix() {
10133         ensureTransformationInfo();
10134         if (mTransformationInfo.mInverseMatrix == null) {
10135             mTransformationInfo.mInverseMatrix = new Matrix();
10136         }
10137         final Matrix matrix = mTransformationInfo.mInverseMatrix;
10138         mRenderNode.getInverseMatrix(matrix);
10139         return matrix;
10140     }
10141 
10142     /**
10143      * Gets the distance along the Z axis from the camera to this view.
10144      *
10145      * @see #setCameraDistance(float)
10146      *
10147      * @return The distance along the Z axis.
10148      */
10149     public float getCameraDistance() {
10150         final float dpi = mResources.getDisplayMetrics().densityDpi;
10151         return -(mRenderNode.getCameraDistance() * dpi);
10152     }
10153 
10154     /**
10155      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10156      * views are drawn) from the camera to this view. The camera's distance
10157      * affects 3D transformations, for instance rotations around the X and Y
10158      * axis. If the rotationX or rotationY properties are changed and this view is
10159      * large (more than half the size of the screen), it is recommended to always
10160      * use a camera distance that's greater than the height (X axis rotation) or
10161      * the width (Y axis rotation) of this view.</p>
10162      *
10163      * <p>The distance of the camera from the view plane can have an affect on the
10164      * perspective distortion of the view when it is rotated around the x or y axis.
10165      * For example, a large distance will result in a large viewing angle, and there
10166      * will not be much perspective distortion of the view as it rotates. A short
10167      * distance may cause much more perspective distortion upon rotation, and can
10168      * also result in some drawing artifacts if the rotated view ends up partially
10169      * behind the camera (which is why the recommendation is to use a distance at
10170      * least as far as the size of the view, if the view is to be rotated.)</p>
10171      *
10172      * <p>The distance is expressed in "depth pixels." The default distance depends
10173      * on the screen density. For instance, on a medium density display, the
10174      * default distance is 1280. On a high density display, the default distance
10175      * is 1920.</p>
10176      *
10177      * <p>If you want to specify a distance that leads to visually consistent
10178      * results across various densities, use the following formula:</p>
10179      * <pre>
10180      * float scale = context.getResources().getDisplayMetrics().density;
10181      * view.setCameraDistance(distance * scale);
10182      * </pre>
10183      *
10184      * <p>The density scale factor of a high density display is 1.5,
10185      * and 1920 = 1280 * 1.5.</p>
10186      *
10187      * @param distance The distance in "depth pixels", if negative the opposite
10188      *        value is used
10189      *
10190      * @see #setRotationX(float)
10191      * @see #setRotationY(float)
10192      */
10193     public void setCameraDistance(float distance) {
10194         final float dpi = mResources.getDisplayMetrics().densityDpi;
10195 
10196         invalidateViewProperty(true, false);
10197         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10198         invalidateViewProperty(false, false);
10199 
10200         invalidateParentIfNeededAndWasQuickRejected();
10201     }
10202 
10203     /**
10204      * The degrees that the view is rotated around the pivot point.
10205      *
10206      * @see #setRotation(float)
10207      * @see #getPivotX()
10208      * @see #getPivotY()
10209      *
10210      * @return The degrees of rotation.
10211      */
10212     @ViewDebug.ExportedProperty(category = "drawing")
10213     public float getRotation() {
10214         return mRenderNode.getRotation();
10215     }
10216 
10217     /**
10218      * Sets the degrees that the view is rotated around the pivot point. Increasing values
10219      * result in clockwise rotation.
10220      *
10221      * @param rotation The degrees of rotation.
10222      *
10223      * @see #getRotation()
10224      * @see #getPivotX()
10225      * @see #getPivotY()
10226      * @see #setRotationX(float)
10227      * @see #setRotationY(float)
10228      *
10229      * @attr ref android.R.styleable#View_rotation
10230      */
10231     public void setRotation(float rotation) {
10232         if (rotation != getRotation()) {
10233             // Double-invalidation is necessary to capture view's old and new areas
10234             invalidateViewProperty(true, false);
10235             mRenderNode.setRotation(rotation);
10236             invalidateViewProperty(false, true);
10237 
10238             invalidateParentIfNeededAndWasQuickRejected();
10239             notifySubtreeAccessibilityStateChangedIfNeeded();
10240         }
10241     }
10242 
10243     /**
10244      * The degrees that the view is rotated around the vertical axis through the pivot point.
10245      *
10246      * @see #getPivotX()
10247      * @see #getPivotY()
10248      * @see #setRotationY(float)
10249      *
10250      * @return The degrees of Y rotation.
10251      */
10252     @ViewDebug.ExportedProperty(category = "drawing")
10253     public float getRotationY() {
10254         return mRenderNode.getRotationY();
10255     }
10256 
10257     /**
10258      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10259      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10260      * down the y axis.
10261      *
10262      * When rotating large views, it is recommended to adjust the camera distance
10263      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10264      *
10265      * @param rotationY The degrees of Y rotation.
10266      *
10267      * @see #getRotationY()
10268      * @see #getPivotX()
10269      * @see #getPivotY()
10270      * @see #setRotation(float)
10271      * @see #setRotationX(float)
10272      * @see #setCameraDistance(float)
10273      *
10274      * @attr ref android.R.styleable#View_rotationY
10275      */
10276     public void setRotationY(float rotationY) {
10277         if (rotationY != getRotationY()) {
10278             invalidateViewProperty(true, false);
10279             mRenderNode.setRotationY(rotationY);
10280             invalidateViewProperty(false, true);
10281 
10282             invalidateParentIfNeededAndWasQuickRejected();
10283             notifySubtreeAccessibilityStateChangedIfNeeded();
10284         }
10285     }
10286 
10287     /**
10288      * The degrees that the view is rotated around the horizontal axis through the pivot point.
10289      *
10290      * @see #getPivotX()
10291      * @see #getPivotY()
10292      * @see #setRotationX(float)
10293      *
10294      * @return The degrees of X rotation.
10295      */
10296     @ViewDebug.ExportedProperty(category = "drawing")
10297     public float getRotationX() {
10298         return mRenderNode.getRotationX();
10299     }
10300 
10301     /**
10302      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10303      * Increasing values result in clockwise rotation from the viewpoint of looking down the
10304      * x axis.
10305      *
10306      * When rotating large views, it is recommended to adjust the camera distance
10307      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10308      *
10309      * @param rotationX The degrees of X rotation.
10310      *
10311      * @see #getRotationX()
10312      * @see #getPivotX()
10313      * @see #getPivotY()
10314      * @see #setRotation(float)
10315      * @see #setRotationY(float)
10316      * @see #setCameraDistance(float)
10317      *
10318      * @attr ref android.R.styleable#View_rotationX
10319      */
10320     public void setRotationX(float rotationX) {
10321         if (rotationX != getRotationX()) {
10322             invalidateViewProperty(true, false);
10323             mRenderNode.setRotationX(rotationX);
10324             invalidateViewProperty(false, true);
10325 
10326             invalidateParentIfNeededAndWasQuickRejected();
10327             notifySubtreeAccessibilityStateChangedIfNeeded();
10328         }
10329     }
10330 
10331     /**
10332      * The amount that the view is scaled in x around the pivot point, as a proportion of
10333      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10334      *
10335      * <p>By default, this is 1.0f.
10336      *
10337      * @see #getPivotX()
10338      * @see #getPivotY()
10339      * @return The scaling factor.
10340      */
10341     @ViewDebug.ExportedProperty(category = "drawing")
10342     public float getScaleX() {
10343         return mRenderNode.getScaleX();
10344     }
10345 
10346     /**
10347      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10348      * the view's unscaled width. A value of 1 means that no scaling is applied.
10349      *
10350      * @param scaleX The scaling factor.
10351      * @see #getPivotX()
10352      * @see #getPivotY()
10353      *
10354      * @attr ref android.R.styleable#View_scaleX
10355      */
10356     public void setScaleX(float scaleX) {
10357         if (scaleX != getScaleX()) {
10358             invalidateViewProperty(true, false);
10359             mRenderNode.setScaleX(scaleX);
10360             invalidateViewProperty(false, true);
10361 
10362             invalidateParentIfNeededAndWasQuickRejected();
10363             notifySubtreeAccessibilityStateChangedIfNeeded();
10364         }
10365     }
10366 
10367     /**
10368      * The amount that the view is scaled in y around the pivot point, as a proportion of
10369      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10370      *
10371      * <p>By default, this is 1.0f.
10372      *
10373      * @see #getPivotX()
10374      * @see #getPivotY()
10375      * @return The scaling factor.
10376      */
10377     @ViewDebug.ExportedProperty(category = "drawing")
10378     public float getScaleY() {
10379         return mRenderNode.getScaleY();
10380     }
10381 
10382     /**
10383      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10384      * the view's unscaled width. A value of 1 means that no scaling is applied.
10385      *
10386      * @param scaleY The scaling factor.
10387      * @see #getPivotX()
10388      * @see #getPivotY()
10389      *
10390      * @attr ref android.R.styleable#View_scaleY
10391      */
10392     public void setScaleY(float scaleY) {
10393         if (scaleY != getScaleY()) {
10394             invalidateViewProperty(true, false);
10395             mRenderNode.setScaleY(scaleY);
10396             invalidateViewProperty(false, true);
10397 
10398             invalidateParentIfNeededAndWasQuickRejected();
10399             notifySubtreeAccessibilityStateChangedIfNeeded();
10400         }
10401     }
10402 
10403     /**
10404      * The x location of the point around which the view is {@link #setRotation(float) rotated}
10405      * and {@link #setScaleX(float) scaled}.
10406      *
10407      * @see #getRotation()
10408      * @see #getScaleX()
10409      * @see #getScaleY()
10410      * @see #getPivotY()
10411      * @return The x location of the pivot point.
10412      *
10413      * @attr ref android.R.styleable#View_transformPivotX
10414      */
10415     @ViewDebug.ExportedProperty(category = "drawing")
10416     public float getPivotX() {
10417         return mRenderNode.getPivotX();
10418     }
10419 
10420     /**
10421      * Sets the x location of the point around which the view is
10422      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10423      * By default, the pivot point is centered on the object.
10424      * Setting this property disables this behavior and causes the view to use only the
10425      * explicitly set pivotX and pivotY values.
10426      *
10427      * @param pivotX The x location of the pivot point.
10428      * @see #getRotation()
10429      * @see #getScaleX()
10430      * @see #getScaleY()
10431      * @see #getPivotY()
10432      *
10433      * @attr ref android.R.styleable#View_transformPivotX
10434      */
10435     public void setPivotX(float pivotX) {
10436         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10437             invalidateViewProperty(true, false);
10438             mRenderNode.setPivotX(pivotX);
10439             invalidateViewProperty(false, true);
10440 
10441             invalidateParentIfNeededAndWasQuickRejected();
10442         }
10443     }
10444 
10445     /**
10446      * The y location of the point around which the view is {@link #setRotation(float) rotated}
10447      * and {@link #setScaleY(float) scaled}.
10448      *
10449      * @see #getRotation()
10450      * @see #getScaleX()
10451      * @see #getScaleY()
10452      * @see #getPivotY()
10453      * @return The y location of the pivot point.
10454      *
10455      * @attr ref android.R.styleable#View_transformPivotY
10456      */
10457     @ViewDebug.ExportedProperty(category = "drawing")
10458     public float getPivotY() {
10459         return mRenderNode.getPivotY();
10460     }
10461 
10462     /**
10463      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10464      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10465      * Setting this property disables this behavior and causes the view to use only the
10466      * explicitly set pivotX and pivotY values.
10467      *
10468      * @param pivotY The y location of the pivot point.
10469      * @see #getRotation()
10470      * @see #getScaleX()
10471      * @see #getScaleY()
10472      * @see #getPivotY()
10473      *
10474      * @attr ref android.R.styleable#View_transformPivotY
10475      */
10476     public void setPivotY(float pivotY) {
10477         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10478             invalidateViewProperty(true, false);
10479             mRenderNode.setPivotY(pivotY);
10480             invalidateViewProperty(false, true);
10481 
10482             invalidateParentIfNeededAndWasQuickRejected();
10483         }
10484     }
10485 
10486     /**
10487      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10488      * completely transparent and 1 means the view is completely opaque.
10489      *
10490      * <p>By default this is 1.0f.
10491      * @return The opacity of the view.
10492      */
10493     @ViewDebug.ExportedProperty(category = "drawing")
10494     public float getAlpha() {
10495         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10496     }
10497 
10498     /**
10499      * Returns whether this View has content which overlaps.
10500      *
10501      * <p>This function, intended to be overridden by specific View types, is an optimization when
10502      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10503      * an offscreen buffer and then composited into place, which can be expensive. If the view has
10504      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10505      * directly. An example of overlapping rendering is a TextView with a background image, such as
10506      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10507      * ImageView with only the foreground image. The default implementation returns true; subclasses
10508      * should override if they have cases which can be optimized.</p>
10509      *
10510      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10511      * necessitates that a View return true if it uses the methods internally without passing the
10512      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10513      *
10514      * @return true if the content in this view might overlap, false otherwise.
10515      */
10516     @ViewDebug.ExportedProperty(category = "drawing")
10517     public boolean hasOverlappingRendering() {
10518         return true;
10519     }
10520 
10521     /**
10522      * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10523      * completely transparent and 1 means the view is completely opaque.</p>
10524      *
10525      * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10526      * performance implications, especially for large views. It is best to use the alpha property
10527      * sparingly and transiently, as in the case of fading animations.</p>
10528      *
10529      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10530      * strongly recommended for performance reasons to either override
10531      * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10532      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10533      *
10534      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10535      * responsible for applying the opacity itself.</p>
10536      *
10537      * <p>Note that if the view is backed by a
10538      * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10539      * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10540      * 1.0 will supercede the alpha of the layer paint.</p>
10541      *
10542      * @param alpha The opacity of the view.
10543      *
10544      * @see #hasOverlappingRendering()
10545      * @see #setLayerType(int, android.graphics.Paint)
10546      *
10547      * @attr ref android.R.styleable#View_alpha
10548      */
10549     public void setAlpha(float alpha) {
10550         ensureTransformationInfo();
10551         if (mTransformationInfo.mAlpha != alpha) {
10552             mTransformationInfo.mAlpha = alpha;
10553             if (onSetAlpha((int) (alpha * 255))) {
10554                 mPrivateFlags |= PFLAG_ALPHA_SET;
10555                 // subclass is handling alpha - don't optimize rendering cache invalidation
10556                 invalidateParentCaches();
10557                 invalidate(true);
10558             } else {
10559                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10560                 invalidateViewProperty(true, false);
10561                 mRenderNode.setAlpha(getFinalAlpha());
10562                 notifyViewAccessibilityStateChangedIfNeeded(
10563                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10564             }
10565         }
10566     }
10567 
10568     /**
10569      * Faster version of setAlpha() which performs the same steps except there are
10570      * no calls to invalidate(). The caller of this function should perform proper invalidation
10571      * on the parent and this object. The return value indicates whether the subclass handles
10572      * alpha (the return value for onSetAlpha()).
10573      *
10574      * @param alpha The new value for the alpha property
10575      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10576      *         the new value for the alpha property is different from the old value
10577      */
10578     boolean setAlphaNoInvalidation(float alpha) {
10579         ensureTransformationInfo();
10580         if (mTransformationInfo.mAlpha != alpha) {
10581             mTransformationInfo.mAlpha = alpha;
10582             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10583             if (subclassHandlesAlpha) {
10584                 mPrivateFlags |= PFLAG_ALPHA_SET;
10585                 return true;
10586             } else {
10587                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10588                 mRenderNode.setAlpha(getFinalAlpha());
10589             }
10590         }
10591         return false;
10592     }
10593 
10594     /**
10595      * This property is hidden and intended only for use by the Fade transition, which
10596      * animates it to produce a visual translucency that does not side-effect (or get
10597      * affected by) the real alpha property. This value is composited with the other
10598      * alpha value (and the AlphaAnimation value, when that is present) to produce
10599      * a final visual translucency result, which is what is passed into the DisplayList.
10600      *
10601      * @hide
10602      */
10603     public void setTransitionAlpha(float alpha) {
10604         ensureTransformationInfo();
10605         if (mTransformationInfo.mTransitionAlpha != alpha) {
10606             mTransformationInfo.mTransitionAlpha = alpha;
10607             mPrivateFlags &= ~PFLAG_ALPHA_SET;
10608             invalidateViewProperty(true, false);
10609             mRenderNode.setAlpha(getFinalAlpha());
10610         }
10611     }
10612 
10613     /**
10614      * Calculates the visual alpha of this view, which is a combination of the actual
10615      * alpha value and the transitionAlpha value (if set).
10616      */
10617     private float getFinalAlpha() {
10618         if (mTransformationInfo != null) {
10619             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10620         }
10621         return 1;
10622     }
10623 
10624     /**
10625      * This property is hidden and intended only for use by the Fade transition, which
10626      * animates it to produce a visual translucency that does not side-effect (or get
10627      * affected by) the real alpha property. This value is composited with the other
10628      * alpha value (and the AlphaAnimation value, when that is present) to produce
10629      * a final visual translucency result, which is what is passed into the DisplayList.
10630      *
10631      * @hide
10632      */
10633     @ViewDebug.ExportedProperty(category = "drawing")
10634     public float getTransitionAlpha() {
10635         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10636     }
10637 
10638     /**
10639      * Top position of this view relative to its parent.
10640      *
10641      * @return The top of this view, in pixels.
10642      */
10643     @ViewDebug.CapturedViewProperty
10644     public final int getTop() {
10645         return mTop;
10646     }
10647 
10648     /**
10649      * Sets the top position of this view relative to its parent. This method is meant to be called
10650      * by the layout system and should not generally be called otherwise, because the property
10651      * may be changed at any time by the layout.
10652      *
10653      * @param top The top of this view, in pixels.
10654      */
10655     public final void setTop(int top) {
10656         if (top != mTop) {
10657             final boolean matrixIsIdentity = hasIdentityMatrix();
10658             if (matrixIsIdentity) {
10659                 if (mAttachInfo != null) {
10660                     int minTop;
10661                     int yLoc;
10662                     if (top < mTop) {
10663                         minTop = top;
10664                         yLoc = top - mTop;
10665                     } else {
10666                         minTop = mTop;
10667                         yLoc = 0;
10668                     }
10669                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10670                 }
10671             } else {
10672                 // Double-invalidation is necessary to capture view's old and new areas
10673                 invalidate(true);
10674             }
10675 
10676             int width = mRight - mLeft;
10677             int oldHeight = mBottom - mTop;
10678 
10679             mTop = top;
10680             mRenderNode.setTop(mTop);
10681 
10682             sizeChange(width, mBottom - mTop, width, oldHeight);
10683 
10684             if (!matrixIsIdentity) {
10685                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10686                 invalidate(true);
10687             }
10688             mBackgroundSizeChanged = true;
10689             invalidateParentIfNeeded();
10690             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10691                 // View was rejected last time it was drawn by its parent; this may have changed
10692                 invalidateParentIfNeeded();
10693             }
10694         }
10695     }
10696 
10697     /**
10698      * Bottom position of this view relative to its parent.
10699      *
10700      * @return The bottom of this view, in pixels.
10701      */
10702     @ViewDebug.CapturedViewProperty
10703     public final int getBottom() {
10704         return mBottom;
10705     }
10706 
10707     /**
10708      * True if this view has changed since the last time being drawn.
10709      *
10710      * @return The dirty state of this view.
10711      */
10712     public boolean isDirty() {
10713         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10714     }
10715 
10716     /**
10717      * Sets the bottom position of this view relative to its parent. This method is meant to be
10718      * called by the layout system and should not generally be called otherwise, because the
10719      * property may be changed at any time by the layout.
10720      *
10721      * @param bottom The bottom of this view, in pixels.
10722      */
10723     public final void setBottom(int bottom) {
10724         if (bottom != mBottom) {
10725             final boolean matrixIsIdentity = hasIdentityMatrix();
10726             if (matrixIsIdentity) {
10727                 if (mAttachInfo != null) {
10728                     int maxBottom;
10729                     if (bottom < mBottom) {
10730                         maxBottom = mBottom;
10731                     } else {
10732                         maxBottom = bottom;
10733                     }
10734                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10735                 }
10736             } else {
10737                 // Double-invalidation is necessary to capture view's old and new areas
10738                 invalidate(true);
10739             }
10740 
10741             int width = mRight - mLeft;
10742             int oldHeight = mBottom - mTop;
10743 
10744             mBottom = bottom;
10745             mRenderNode.setBottom(mBottom);
10746 
10747             sizeChange(width, mBottom - mTop, width, oldHeight);
10748 
10749             if (!matrixIsIdentity) {
10750                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10751                 invalidate(true);
10752             }
10753             mBackgroundSizeChanged = true;
10754             invalidateParentIfNeeded();
10755             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10756                 // View was rejected last time it was drawn by its parent; this may have changed
10757                 invalidateParentIfNeeded();
10758             }
10759         }
10760     }
10761 
10762     /**
10763      * Left position of this view relative to its parent.
10764      *
10765      * @return The left edge of this view, in pixels.
10766      */
10767     @ViewDebug.CapturedViewProperty
10768     public final int getLeft() {
10769         return mLeft;
10770     }
10771 
10772     /**
10773      * Sets the left position of this view relative to its parent. This method is meant to be called
10774      * by the layout system and should not generally be called otherwise, because the property
10775      * may be changed at any time by the layout.
10776      *
10777      * @param left The left of this view, in pixels.
10778      */
10779     public final void setLeft(int left) {
10780         if (left != mLeft) {
10781             final boolean matrixIsIdentity = hasIdentityMatrix();
10782             if (matrixIsIdentity) {
10783                 if (mAttachInfo != null) {
10784                     int minLeft;
10785                     int xLoc;
10786                     if (left < mLeft) {
10787                         minLeft = left;
10788                         xLoc = left - mLeft;
10789                     } else {
10790                         minLeft = mLeft;
10791                         xLoc = 0;
10792                     }
10793                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
10794                 }
10795             } else {
10796                 // Double-invalidation is necessary to capture view's old and new areas
10797                 invalidate(true);
10798             }
10799 
10800             int oldWidth = mRight - mLeft;
10801             int height = mBottom - mTop;
10802 
10803             mLeft = left;
10804             mRenderNode.setLeft(left);
10805 
10806             sizeChange(mRight - mLeft, height, oldWidth, height);
10807 
10808             if (!matrixIsIdentity) {
10809                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10810                 invalidate(true);
10811             }
10812             mBackgroundSizeChanged = true;
10813             invalidateParentIfNeeded();
10814             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10815                 // View was rejected last time it was drawn by its parent; this may have changed
10816                 invalidateParentIfNeeded();
10817             }
10818         }
10819     }
10820 
10821     /**
10822      * Right position of this view relative to its parent.
10823      *
10824      * @return The right edge of this view, in pixels.
10825      */
10826     @ViewDebug.CapturedViewProperty
10827     public final int getRight() {
10828         return mRight;
10829     }
10830 
10831     /**
10832      * Sets the right position of this view relative to its parent. This method is meant to be called
10833      * by the layout system and should not generally be called otherwise, because the property
10834      * may be changed at any time by the layout.
10835      *
10836      * @param right The right of this view, in pixels.
10837      */
10838     public final void setRight(int right) {
10839         if (right != mRight) {
10840             final boolean matrixIsIdentity = hasIdentityMatrix();
10841             if (matrixIsIdentity) {
10842                 if (mAttachInfo != null) {
10843                     int maxRight;
10844                     if (right < mRight) {
10845                         maxRight = mRight;
10846                     } else {
10847                         maxRight = right;
10848                     }
10849                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
10850                 }
10851             } else {
10852                 // Double-invalidation is necessary to capture view's old and new areas
10853                 invalidate(true);
10854             }
10855 
10856             int oldWidth = mRight - mLeft;
10857             int height = mBottom - mTop;
10858 
10859             mRight = right;
10860             mRenderNode.setRight(mRight);
10861 
10862             sizeChange(mRight - mLeft, height, oldWidth, height);
10863 
10864             if (!matrixIsIdentity) {
10865                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10866                 invalidate(true);
10867             }
10868             mBackgroundSizeChanged = true;
10869             invalidateParentIfNeeded();
10870             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10871                 // View was rejected last time it was drawn by its parent; this may have changed
10872                 invalidateParentIfNeeded();
10873             }
10874         }
10875     }
10876 
10877     /**
10878      * The visual x position of this view, in pixels. This is equivalent to the
10879      * {@link #setTranslationX(float) translationX} property plus the current
10880      * {@link #getLeft() left} property.
10881      *
10882      * @return The visual x position of this view, in pixels.
10883      */
10884     @ViewDebug.ExportedProperty(category = "drawing")
10885     public float getX() {
10886         return mLeft + getTranslationX();
10887     }
10888 
10889     /**
10890      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
10891      * {@link #setTranslationX(float) translationX} property to be the difference between
10892      * the x value passed in and the current {@link #getLeft() left} property.
10893      *
10894      * @param x The visual x position of this view, in pixels.
10895      */
10896     public void setX(float x) {
10897         setTranslationX(x - mLeft);
10898     }
10899 
10900     /**
10901      * The visual y position of this view, in pixels. This is equivalent to the
10902      * {@link #setTranslationY(float) translationY} property plus the current
10903      * {@link #getTop() top} property.
10904      *
10905      * @return The visual y position of this view, in pixels.
10906      */
10907     @ViewDebug.ExportedProperty(category = "drawing")
10908     public float getY() {
10909         return mTop + getTranslationY();
10910     }
10911 
10912     /**
10913      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
10914      * {@link #setTranslationY(float) translationY} property to be the difference between
10915      * the y value passed in and the current {@link #getTop() top} property.
10916      *
10917      * @param y The visual y position of this view, in pixels.
10918      */
10919     public void setY(float y) {
10920         setTranslationY(y - mTop);
10921     }
10922 
10923     /**
10924      * The visual z position of this view, in pixels. This is equivalent to the
10925      * {@link #setTranslationZ(float) translationZ} property plus the current
10926      * {@link #getElevation() elevation} property.
10927      *
10928      * @return The visual z position of this view, in pixels.
10929      */
10930     @ViewDebug.ExportedProperty(category = "drawing")
10931     public float getZ() {
10932         return getElevation() + getTranslationZ();
10933     }
10934 
10935     /**
10936      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
10937      * {@link #setTranslationZ(float) translationZ} property to be the difference between
10938      * the x value passed in and the current {@link #getElevation() elevation} property.
10939      *
10940      * @param z The visual z position of this view, in pixels.
10941      */
10942     public void setZ(float z) {
10943         setTranslationZ(z - getElevation());
10944     }
10945 
10946     /**
10947      * The base elevation of this view relative to its parent, in pixels.
10948      *
10949      * @return The base depth position of the view, in pixels.
10950      */
10951     @ViewDebug.ExportedProperty(category = "drawing")
10952     public float getElevation() {
10953         return mRenderNode.getElevation();
10954     }
10955 
10956     /**
10957      * Sets the base elevation of this view, in pixels.
10958      *
10959      * @attr ref android.R.styleable#View_elevation
10960      */
10961     public void setElevation(float elevation) {
10962         if (elevation != getElevation()) {
10963             invalidateViewProperty(true, false);
10964             mRenderNode.setElevation(elevation);
10965             invalidateViewProperty(false, true);
10966 
10967             invalidateParentIfNeededAndWasQuickRejected();
10968         }
10969     }
10970 
10971     /**
10972      * The horizontal location of this view relative to its {@link #getLeft() left} position.
10973      * This position is post-layout, in addition to wherever the object's
10974      * layout placed it.
10975      *
10976      * @return The horizontal position of this view relative to its left position, in pixels.
10977      */
10978     @ViewDebug.ExportedProperty(category = "drawing")
10979     public float getTranslationX() {
10980         return mRenderNode.getTranslationX();
10981     }
10982 
10983     /**
10984      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
10985      * This effectively positions the object post-layout, in addition to wherever the object's
10986      * layout placed it.
10987      *
10988      * @param translationX The horizontal position of this view relative to its left position,
10989      * in pixels.
10990      *
10991      * @attr ref android.R.styleable#View_translationX
10992      */
10993     public void setTranslationX(float translationX) {
10994         if (translationX != getTranslationX()) {
10995             invalidateViewProperty(true, false);
10996             mRenderNode.setTranslationX(translationX);
10997             invalidateViewProperty(false, true);
10998 
10999             invalidateParentIfNeededAndWasQuickRejected();
11000             notifySubtreeAccessibilityStateChangedIfNeeded();
11001         }
11002     }
11003 
11004     /**
11005      * The vertical location of this view relative to its {@link #getTop() top} position.
11006      * This position is post-layout, in addition to wherever the object's
11007      * layout placed it.
11008      *
11009      * @return The vertical position of this view relative to its top position,
11010      * in pixels.
11011      */
11012     @ViewDebug.ExportedProperty(category = "drawing")
11013     public float getTranslationY() {
11014         return mRenderNode.getTranslationY();
11015     }
11016 
11017     /**
11018      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11019      * This effectively positions the object post-layout, in addition to wherever the object's
11020      * layout placed it.
11021      *
11022      * @param translationY The vertical position of this view relative to its top position,
11023      * in pixels.
11024      *
11025      * @attr ref android.R.styleable#View_translationY
11026      */
11027     public void setTranslationY(float translationY) {
11028         if (translationY != getTranslationY()) {
11029             invalidateViewProperty(true, false);
11030             mRenderNode.setTranslationY(translationY);
11031             invalidateViewProperty(false, true);
11032 
11033             invalidateParentIfNeededAndWasQuickRejected();
11034         }
11035     }
11036 
11037     /**
11038      * The depth location of this view relative to its {@link #getElevation() elevation}.
11039      *
11040      * @return The depth of this view relative to its elevation.
11041      */
11042     @ViewDebug.ExportedProperty(category = "drawing")
11043     public float getTranslationZ() {
11044         return mRenderNode.getTranslationZ();
11045     }
11046 
11047     /**
11048      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11049      *
11050      * @attr ref android.R.styleable#View_translationZ
11051      */
11052     public void setTranslationZ(float translationZ) {
11053         if (translationZ != getTranslationZ()) {
11054             invalidateViewProperty(true, false);
11055             mRenderNode.setTranslationZ(translationZ);
11056             invalidateViewProperty(false, true);
11057 
11058             invalidateParentIfNeededAndWasQuickRejected();
11059         }
11060     }
11061 
11062     /** @hide */
11063     public void setAnimationMatrix(Matrix matrix) {
11064         invalidateViewProperty(true, false);
11065         mRenderNode.setAnimationMatrix(matrix);
11066         invalidateViewProperty(false, true);
11067 
11068         invalidateParentIfNeededAndWasQuickRejected();
11069     }
11070 
11071     /**
11072      * Returns the current StateListAnimator if exists.
11073      *
11074      * @return StateListAnimator or null if it does not exists
11075      * @see    #setStateListAnimator(android.animation.StateListAnimator)
11076      */
11077     public StateListAnimator getStateListAnimator() {
11078         return mStateListAnimator;
11079     }
11080 
11081     /**
11082      * Attaches the provided StateListAnimator to this View.
11083      * <p>
11084      * Any previously attached StateListAnimator will be detached.
11085      *
11086      * @param stateListAnimator The StateListAnimator to update the view
11087      * @see {@link android.animation.StateListAnimator}
11088      */
11089     public void setStateListAnimator(StateListAnimator stateListAnimator) {
11090         if (mStateListAnimator == stateListAnimator) {
11091             return;
11092         }
11093         if (mStateListAnimator != null) {
11094             mStateListAnimator.setTarget(null);
11095         }
11096         mStateListAnimator = stateListAnimator;
11097         if (stateListAnimator != null) {
11098             stateListAnimator.setTarget(this);
11099             if (isAttachedToWindow()) {
11100                 stateListAnimator.setState(getDrawableState());
11101             }
11102         }
11103     }
11104 
11105     /**
11106      * Returns whether the Outline should be used to clip the contents of the View.
11107      * <p>
11108      * Note that this flag will only be respected if the View's Outline returns true from
11109      * {@link Outline#canClip()}.
11110      *
11111      * @see #setOutlineProvider(ViewOutlineProvider)
11112      * @see #setClipToOutline(boolean)
11113      */
11114     public final boolean getClipToOutline() {
11115         return mRenderNode.getClipToOutline();
11116     }
11117 
11118     /**
11119      * Sets whether the View's Outline should be used to clip the contents of the View.
11120      * <p>
11121      * Only a single non-rectangular clip can be applied on a View at any time.
11122      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11123      * circular reveal} animation take priority over Outline clipping, and
11124      * child Outline clipping takes priority over Outline clipping done by a
11125      * parent.
11126      * <p>
11127      * Note that this flag will only be respected if the View's Outline returns true from
11128      * {@link Outline#canClip()}.
11129      *
11130      * @see #setOutlineProvider(ViewOutlineProvider)
11131      * @see #getClipToOutline()
11132      */
11133     public void setClipToOutline(boolean clipToOutline) {
11134         damageInParent();
11135         if (getClipToOutline() != clipToOutline) {
11136             mRenderNode.setClipToOutline(clipToOutline);
11137         }
11138     }
11139 
11140     // correspond to the enum values of View_outlineProvider
11141     private static final int PROVIDER_BACKGROUND = 0;
11142     private static final int PROVIDER_NONE = 1;
11143     private static final int PROVIDER_BOUNDS = 2;
11144     private static final int PROVIDER_PADDED_BOUNDS = 3;
11145     private void setOutlineProviderFromAttribute(int providerInt) {
11146         switch (providerInt) {
11147             case PROVIDER_BACKGROUND:
11148                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
11149                 break;
11150             case PROVIDER_NONE:
11151                 setOutlineProvider(null);
11152                 break;
11153             case PROVIDER_BOUNDS:
11154                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
11155                 break;
11156             case PROVIDER_PADDED_BOUNDS:
11157                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11158                 break;
11159         }
11160     }
11161 
11162     /**
11163      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11164      * the shape of the shadow it casts, and enables outline clipping.
11165      * <p>
11166      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11167      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11168      * outline provider with this method allows this behavior to be overridden.
11169      * <p>
11170      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11171      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11172      * <p>
11173      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11174      *
11175      * @see #setClipToOutline(boolean)
11176      * @see #getClipToOutline()
11177      * @see #getOutlineProvider()
11178      */
11179     public void setOutlineProvider(ViewOutlineProvider provider) {
11180         mOutlineProvider = provider;
11181         invalidateOutline();
11182     }
11183 
11184     /**
11185      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11186      * that defines the shape of the shadow it casts, and enables outline clipping.
11187      *
11188      * @see #setOutlineProvider(ViewOutlineProvider)
11189      */
11190     public ViewOutlineProvider getOutlineProvider() {
11191         return mOutlineProvider;
11192     }
11193 
11194     /**
11195      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11196      *
11197      * @see #setOutlineProvider(ViewOutlineProvider)
11198      */
11199     public void invalidateOutline() {
11200         rebuildOutline();
11201 
11202         notifySubtreeAccessibilityStateChangedIfNeeded();
11203         invalidateViewProperty(false, false);
11204     }
11205 
11206     /**
11207      * Internal version of {@link #invalidateOutline()} which invalidates the
11208      * outline without invalidating the view itself. This is intended to be called from
11209      * within methods in the View class itself which are the result of the view being
11210      * invalidated already. For example, when we are drawing the background of a View,
11211      * we invalidate the outline in case it changed in the meantime, but we do not
11212      * need to invalidate the view because we're already drawing the background as part
11213      * of drawing the view in response to an earlier invalidation of the view.
11214      */
11215     private void rebuildOutline() {
11216         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11217         if (mAttachInfo == null) return;
11218 
11219         if (mOutlineProvider == null) {
11220             // no provider, remove outline
11221             mRenderNode.setOutline(null);
11222         } else {
11223             final Outline outline = mAttachInfo.mTmpOutline;
11224             outline.setEmpty();
11225             outline.setAlpha(1.0f);
11226 
11227             mOutlineProvider.getOutline(this, outline);
11228             mRenderNode.setOutline(outline);
11229         }
11230     }
11231 
11232     /**
11233      * HierarchyViewer only
11234      *
11235      * @hide
11236      */
11237     @ViewDebug.ExportedProperty(category = "drawing")
11238     public boolean hasShadow() {
11239         return mRenderNode.hasShadow();
11240     }
11241 
11242 
11243     /** @hide */
11244     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11245         mRenderNode.setRevealClip(shouldClip, x, y, radius);
11246         invalidateViewProperty(false, false);
11247     }
11248 
11249     /**
11250      * Hit rectangle in parent's coordinates
11251      *
11252      * @param outRect The hit rectangle of the view.
11253      */
11254     public void getHitRect(Rect outRect) {
11255         if (hasIdentityMatrix() || mAttachInfo == null) {
11256             outRect.set(mLeft, mTop, mRight, mBottom);
11257         } else {
11258             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11259             tmpRect.set(0, 0, getWidth(), getHeight());
11260             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11261             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11262                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11263         }
11264     }
11265 
11266     /**
11267      * Determines whether the given point, in local coordinates is inside the view.
11268      */
11269     /*package*/ final boolean pointInView(float localX, float localY) {
11270         return localX >= 0 && localX < (mRight - mLeft)
11271                 && localY >= 0 && localY < (mBottom - mTop);
11272     }
11273 
11274     /**
11275      * Utility method to determine whether the given point, in local coordinates,
11276      * is inside the view, where the area of the view is expanded by the slop factor.
11277      * This method is called while processing touch-move events to determine if the event
11278      * is still within the view.
11279      *
11280      * @hide
11281      */
11282     public boolean pointInView(float localX, float localY, float slop) {
11283         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11284                 localY < ((mBottom - mTop) + slop);
11285     }
11286 
11287     /**
11288      * When a view has focus and the user navigates away from it, the next view is searched for
11289      * starting from the rectangle filled in by this method.
11290      *
11291      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11292      * of the view.  However, if your view maintains some idea of internal selection,
11293      * such as a cursor, or a selected row or column, you should override this method and
11294      * fill in a more specific rectangle.
11295      *
11296      * @param r The rectangle to fill in, in this view's coordinates.
11297      */
11298     public void getFocusedRect(Rect r) {
11299         getDrawingRect(r);
11300     }
11301 
11302     /**
11303      * If some part of this view is not clipped by any of its parents, then
11304      * return that area in r in global (root) coordinates. To convert r to local
11305      * coordinates (without taking possible View rotations into account), offset
11306      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11307      * If the view is completely clipped or translated out, return false.
11308      *
11309      * @param r If true is returned, r holds the global coordinates of the
11310      *        visible portion of this view.
11311      * @param globalOffset If true is returned, globalOffset holds the dx,dy
11312      *        between this view and its root. globalOffet may be null.
11313      * @return true if r is non-empty (i.e. part of the view is visible at the
11314      *         root level.
11315      */
11316     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11317         int width = mRight - mLeft;
11318         int height = mBottom - mTop;
11319         if (width > 0 && height > 0) {
11320             r.set(0, 0, width, height);
11321             if (globalOffset != null) {
11322                 globalOffset.set(-mScrollX, -mScrollY);
11323             }
11324             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11325         }
11326         return false;
11327     }
11328 
11329     public final boolean getGlobalVisibleRect(Rect r) {
11330         return getGlobalVisibleRect(r, null);
11331     }
11332 
11333     public final boolean getLocalVisibleRect(Rect r) {
11334         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11335         if (getGlobalVisibleRect(r, offset)) {
11336             r.offset(-offset.x, -offset.y); // make r local
11337             return true;
11338         }
11339         return false;
11340     }
11341 
11342     /**
11343      * Offset this view's vertical location by the specified number of pixels.
11344      *
11345      * @param offset the number of pixels to offset the view by
11346      */
11347     public void offsetTopAndBottom(int offset) {
11348         if (offset != 0) {
11349             final boolean matrixIsIdentity = hasIdentityMatrix();
11350             if (matrixIsIdentity) {
11351                 if (isHardwareAccelerated()) {
11352                     invalidateViewProperty(false, false);
11353                 } else {
11354                     final ViewParent p = mParent;
11355                     if (p != null && mAttachInfo != null) {
11356                         final Rect r = mAttachInfo.mTmpInvalRect;
11357                         int minTop;
11358                         int maxBottom;
11359                         int yLoc;
11360                         if (offset < 0) {
11361                             minTop = mTop + offset;
11362                             maxBottom = mBottom;
11363                             yLoc = offset;
11364                         } else {
11365                             minTop = mTop;
11366                             maxBottom = mBottom + offset;
11367                             yLoc = 0;
11368                         }
11369                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11370                         p.invalidateChild(this, r);
11371                     }
11372                 }
11373             } else {
11374                 invalidateViewProperty(false, false);
11375             }
11376 
11377             mTop += offset;
11378             mBottom += offset;
11379             mRenderNode.offsetTopAndBottom(offset);
11380             if (isHardwareAccelerated()) {
11381                 invalidateViewProperty(false, false);
11382             } else {
11383                 if (!matrixIsIdentity) {
11384                     invalidateViewProperty(false, true);
11385                 }
11386                 invalidateParentIfNeeded();
11387             }
11388             notifySubtreeAccessibilityStateChangedIfNeeded();
11389         }
11390     }
11391 
11392     /**
11393      * Offset this view's horizontal location by the specified amount of pixels.
11394      *
11395      * @param offset the number of pixels to offset the view by
11396      */
11397     public void offsetLeftAndRight(int offset) {
11398         if (offset != 0) {
11399             final boolean matrixIsIdentity = hasIdentityMatrix();
11400             if (matrixIsIdentity) {
11401                 if (isHardwareAccelerated()) {
11402                     invalidateViewProperty(false, false);
11403                 } else {
11404                     final ViewParent p = mParent;
11405                     if (p != null && mAttachInfo != null) {
11406                         final Rect r = mAttachInfo.mTmpInvalRect;
11407                         int minLeft;
11408                         int maxRight;
11409                         if (offset < 0) {
11410                             minLeft = mLeft + offset;
11411                             maxRight = mRight;
11412                         } else {
11413                             minLeft = mLeft;
11414                             maxRight = mRight + offset;
11415                         }
11416                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11417                         p.invalidateChild(this, r);
11418                     }
11419                 }
11420             } else {
11421                 invalidateViewProperty(false, false);
11422             }
11423 
11424             mLeft += offset;
11425             mRight += offset;
11426             mRenderNode.offsetLeftAndRight(offset);
11427             if (isHardwareAccelerated()) {
11428                 invalidateViewProperty(false, false);
11429             } else {
11430                 if (!matrixIsIdentity) {
11431                     invalidateViewProperty(false, true);
11432                 }
11433                 invalidateParentIfNeeded();
11434             }
11435             notifySubtreeAccessibilityStateChangedIfNeeded();
11436         }
11437     }
11438 
11439     /**
11440      * Get the LayoutParams associated with this view. All views should have
11441      * layout parameters. These supply parameters to the <i>parent</i> of this
11442      * view specifying how it should be arranged. There are many subclasses of
11443      * ViewGroup.LayoutParams, and these correspond to the different subclasses
11444      * of ViewGroup that are responsible for arranging their children.
11445      *
11446      * This method may return null if this View is not attached to a parent
11447      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11448      * was not invoked successfully. When a View is attached to a parent
11449      * ViewGroup, this method must not return null.
11450      *
11451      * @return The LayoutParams associated with this view, or null if no
11452      *         parameters have been set yet
11453      */
11454     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11455     public ViewGroup.LayoutParams getLayoutParams() {
11456         return mLayoutParams;
11457     }
11458 
11459     /**
11460      * Set the layout parameters associated with this view. These supply
11461      * parameters to the <i>parent</i> of this view specifying how it should be
11462      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11463      * correspond to the different subclasses of ViewGroup that are responsible
11464      * for arranging their children.
11465      *
11466      * @param params The layout parameters for this view, cannot be null
11467      */
11468     public void setLayoutParams(ViewGroup.LayoutParams params) {
11469         if (params == null) {
11470             throw new NullPointerException("Layout parameters cannot be null");
11471         }
11472         mLayoutParams = params;
11473         resolveLayoutParams();
11474         if (mParent instanceof ViewGroup) {
11475             ((ViewGroup) mParent).onSetLayoutParams(this, params);
11476         }
11477         requestLayout();
11478     }
11479 
11480     /**
11481      * Resolve the layout parameters depending on the resolved layout direction
11482      *
11483      * @hide
11484      */
11485     public void resolveLayoutParams() {
11486         if (mLayoutParams != null) {
11487             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11488         }
11489     }
11490 
11491     /**
11492      * Set the scrolled position of your view. This will cause a call to
11493      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11494      * invalidated.
11495      * @param x the x position to scroll to
11496      * @param y the y position to scroll to
11497      */
11498     public void scrollTo(int x, int y) {
11499         if (mScrollX != x || mScrollY != y) {
11500             int oldX = mScrollX;
11501             int oldY = mScrollY;
11502             mScrollX = x;
11503             mScrollY = y;
11504             invalidateParentCaches();
11505             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11506             if (!awakenScrollBars()) {
11507                 postInvalidateOnAnimation();
11508             }
11509         }
11510     }
11511 
11512     /**
11513      * Move the scrolled position of your view. This will cause a call to
11514      * {@link #onScrollChanged(int, int, int, int)} and the view will be
11515      * invalidated.
11516      * @param x the amount of pixels to scroll by horizontally
11517      * @param y the amount of pixels to scroll by vertically
11518      */
11519     public void scrollBy(int x, int y) {
11520         scrollTo(mScrollX + x, mScrollY + y);
11521     }
11522 
11523     /**
11524      * <p>Trigger the scrollbars to draw. When invoked this method starts an
11525      * animation to fade the scrollbars out after a default delay. If a subclass
11526      * provides animated scrolling, the start delay should equal the duration
11527      * of the scrolling animation.</p>
11528      *
11529      * <p>The animation starts only if at least one of the scrollbars is
11530      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11531      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11532      * this method returns true, and false otherwise. If the animation is
11533      * started, this method calls {@link #invalidate()}; in that case the
11534      * caller should not call {@link #invalidate()}.</p>
11535      *
11536      * <p>This method should be invoked every time a subclass directly updates
11537      * the scroll parameters.</p>
11538      *
11539      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11540      * and {@link #scrollTo(int, int)}.</p>
11541      *
11542      * @return true if the animation is played, false otherwise
11543      *
11544      * @see #awakenScrollBars(int)
11545      * @see #scrollBy(int, int)
11546      * @see #scrollTo(int, int)
11547      * @see #isHorizontalScrollBarEnabled()
11548      * @see #isVerticalScrollBarEnabled()
11549      * @see #setHorizontalScrollBarEnabled(boolean)
11550      * @see #setVerticalScrollBarEnabled(boolean)
11551      */
11552     protected boolean awakenScrollBars() {
11553         return mScrollCache != null &&
11554                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11555     }
11556 
11557     /**
11558      * Trigger the scrollbars to draw.
11559      * This method differs from awakenScrollBars() only in its default duration.
11560      * initialAwakenScrollBars() will show the scroll bars for longer than
11561      * usual to give the user more of a chance to notice them.
11562      *
11563      * @return true if the animation is played, false otherwise.
11564      */
11565     private boolean initialAwakenScrollBars() {
11566         return mScrollCache != null &&
11567                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11568     }
11569 
11570     /**
11571      * <p>
11572      * Trigger the scrollbars to draw. When invoked this method starts an
11573      * animation to fade the scrollbars out after a fixed delay. If a subclass
11574      * provides animated scrolling, the start delay should equal the duration of
11575      * the scrolling animation.
11576      * </p>
11577      *
11578      * <p>
11579      * The animation starts only if at least one of the scrollbars is enabled,
11580      * as specified by {@link #isHorizontalScrollBarEnabled()} and
11581      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11582      * this method returns true, and false otherwise. If the animation is
11583      * started, this method calls {@link #invalidate()}; in that case the caller
11584      * should not call {@link #invalidate()}.
11585      * </p>
11586      *
11587      * <p>
11588      * This method should be invoked everytime a subclass directly updates the
11589      * scroll parameters.
11590      * </p>
11591      *
11592      * @param startDelay the delay, in milliseconds, after which the animation
11593      *        should start; when the delay is 0, the animation starts
11594      *        immediately
11595      * @return true if the animation is played, false otherwise
11596      *
11597      * @see #scrollBy(int, int)
11598      * @see #scrollTo(int, int)
11599      * @see #isHorizontalScrollBarEnabled()
11600      * @see #isVerticalScrollBarEnabled()
11601      * @see #setHorizontalScrollBarEnabled(boolean)
11602      * @see #setVerticalScrollBarEnabled(boolean)
11603      */
11604     protected boolean awakenScrollBars(int startDelay) {
11605         return awakenScrollBars(startDelay, true);
11606     }
11607 
11608     /**
11609      * <p>
11610      * Trigger the scrollbars to draw. When invoked this method starts an
11611      * animation to fade the scrollbars out after a fixed delay. If a subclass
11612      * provides animated scrolling, the start delay should equal the duration of
11613      * the scrolling animation.
11614      * </p>
11615      *
11616      * <p>
11617      * The animation starts only if at least one of the scrollbars is enabled,
11618      * as specified by {@link #isHorizontalScrollBarEnabled()} and
11619      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11620      * this method returns true, and false otherwise. If the animation is
11621      * started, this method calls {@link #invalidate()} if the invalidate parameter
11622      * is set to true; in that case the caller
11623      * should not call {@link #invalidate()}.
11624      * </p>
11625      *
11626      * <p>
11627      * This method should be invoked everytime a subclass directly updates the
11628      * scroll parameters.
11629      * </p>
11630      *
11631      * @param startDelay the delay, in milliseconds, after which the animation
11632      *        should start; when the delay is 0, the animation starts
11633      *        immediately
11634      *
11635      * @param invalidate Wheter this method should call invalidate
11636      *
11637      * @return true if the animation is played, false otherwise
11638      *
11639      * @see #scrollBy(int, int)
11640      * @see #scrollTo(int, int)
11641      * @see #isHorizontalScrollBarEnabled()
11642      * @see #isVerticalScrollBarEnabled()
11643      * @see #setHorizontalScrollBarEnabled(boolean)
11644      * @see #setVerticalScrollBarEnabled(boolean)
11645      */
11646     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11647         final ScrollabilityCache scrollCache = mScrollCache;
11648 
11649         if (scrollCache == null || !scrollCache.fadeScrollBars) {
11650             return false;
11651         }
11652 
11653         if (scrollCache.scrollBar == null) {
11654             scrollCache.scrollBar = new ScrollBarDrawable();
11655         }
11656 
11657         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11658 
11659             if (invalidate) {
11660                 // Invalidate to show the scrollbars
11661                 postInvalidateOnAnimation();
11662             }
11663 
11664             if (scrollCache.state == ScrollabilityCache.OFF) {
11665                 // FIXME: this is copied from WindowManagerService.
11666                 // We should get this value from the system when it
11667                 // is possible to do so.
11668                 final int KEY_REPEAT_FIRST_DELAY = 750;
11669                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11670             }
11671 
11672             // Tell mScrollCache when we should start fading. This may
11673             // extend the fade start time if one was already scheduled
11674             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11675             scrollCache.fadeStartTime = fadeStartTime;
11676             scrollCache.state = ScrollabilityCache.ON;
11677 
11678             // Schedule our fader to run, unscheduling any old ones first
11679             if (mAttachInfo != null) {
11680                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
11681                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11682             }
11683 
11684             return true;
11685         }
11686 
11687         return false;
11688     }
11689 
11690     /**
11691      * Do not invalidate views which are not visible and which are not running an animation. They
11692      * will not get drawn and they should not set dirty flags as if they will be drawn
11693      */
11694     private boolean skipInvalidate() {
11695         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11696                 (!(mParent instanceof ViewGroup) ||
11697                         !((ViewGroup) mParent).isViewTransitioning(this));
11698     }
11699 
11700     /**
11701      * Mark the area defined by dirty as needing to be drawn. If the view is
11702      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11703      * point in the future.
11704      * <p>
11705      * This must be called from a UI thread. To call from a non-UI thread, call
11706      * {@link #postInvalidate()}.
11707      * <p>
11708      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11709      * {@code dirty}.
11710      *
11711      * @param dirty the rectangle representing the bounds of the dirty region
11712      */
11713     public void invalidate(Rect dirty) {
11714         final int scrollX = mScrollX;
11715         final int scrollY = mScrollY;
11716         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11717                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11718     }
11719 
11720     /**
11721      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11722      * coordinates of the dirty rect are relative to the view. If the view is
11723      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11724      * point in the future.
11725      * <p>
11726      * This must be called from a UI thread. To call from a non-UI thread, call
11727      * {@link #postInvalidate()}.
11728      *
11729      * @param l the left position of the dirty region
11730      * @param t the top position of the dirty region
11731      * @param r the right position of the dirty region
11732      * @param b the bottom position of the dirty region
11733      */
11734     public void invalidate(int l, int t, int r, int b) {
11735         final int scrollX = mScrollX;
11736         final int scrollY = mScrollY;
11737         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
11738     }
11739 
11740     /**
11741      * Invalidate the whole view. If the view is visible,
11742      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
11743      * the future.
11744      * <p>
11745      * This must be called from a UI thread. To call from a non-UI thread, call
11746      * {@link #postInvalidate()}.
11747      */
11748     public void invalidate() {
11749         invalidate(true);
11750     }
11751 
11752     /**
11753      * This is where the invalidate() work actually happens. A full invalidate()
11754      * causes the drawing cache to be invalidated, but this function can be
11755      * called with invalidateCache set to false to skip that invalidation step
11756      * for cases that do not need it (for example, a component that remains at
11757      * the same dimensions with the same content).
11758      *
11759      * @param invalidateCache Whether the drawing cache for this view should be
11760      *            invalidated as well. This is usually true for a full
11761      *            invalidate, but may be set to false if the View's contents or
11762      *            dimensions have not changed.
11763      */
11764     void invalidate(boolean invalidateCache) {
11765         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
11766     }
11767 
11768     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
11769             boolean fullInvalidate) {
11770         if (mGhostView != null) {
11771             mGhostView.invalidate(true);
11772             return;
11773         }
11774 
11775         if (skipInvalidate()) {
11776             return;
11777         }
11778 
11779         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
11780                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
11781                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
11782                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
11783             if (fullInvalidate) {
11784                 mLastIsOpaque = isOpaque();
11785                 mPrivateFlags &= ~PFLAG_DRAWN;
11786             }
11787 
11788             mPrivateFlags |= PFLAG_DIRTY;
11789 
11790             if (invalidateCache) {
11791                 mPrivateFlags |= PFLAG_INVALIDATED;
11792                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11793             }
11794 
11795             // Propagate the damage rectangle to the parent view.
11796             final AttachInfo ai = mAttachInfo;
11797             final ViewParent p = mParent;
11798             if (p != null && ai != null && l < r && t < b) {
11799                 final Rect damage = ai.mTmpInvalRect;
11800                 damage.set(l, t, r, b);
11801                 p.invalidateChild(this, damage);
11802             }
11803 
11804             // Damage the entire projection receiver, if necessary.
11805             if (mBackground != null && mBackground.isProjected()) {
11806                 final View receiver = getProjectionReceiver();
11807                 if (receiver != null) {
11808                     receiver.damageInParent();
11809                 }
11810             }
11811 
11812             // Damage the entire IsolatedZVolume receiving this view's shadow.
11813             if (isHardwareAccelerated() && getZ() != 0) {
11814                 damageShadowReceiver();
11815             }
11816         }
11817     }
11818 
11819     /**
11820      * @return this view's projection receiver, or {@code null} if none exists
11821      */
11822     private View getProjectionReceiver() {
11823         ViewParent p = getParent();
11824         while (p != null && p instanceof View) {
11825             final View v = (View) p;
11826             if (v.isProjectionReceiver()) {
11827                 return v;
11828             }
11829             p = p.getParent();
11830         }
11831 
11832         return null;
11833     }
11834 
11835     /**
11836      * @return whether the view is a projection receiver
11837      */
11838     private boolean isProjectionReceiver() {
11839         return mBackground != null;
11840     }
11841 
11842     /**
11843      * Damage area of the screen that can be covered by this View's shadow.
11844      *
11845      * This method will guarantee that any changes to shadows cast by a View
11846      * are damaged on the screen for future redraw.
11847      */
11848     private void damageShadowReceiver() {
11849         final AttachInfo ai = mAttachInfo;
11850         if (ai != null) {
11851             ViewParent p = getParent();
11852             if (p != null && p instanceof ViewGroup) {
11853                 final ViewGroup vg = (ViewGroup) p;
11854                 vg.damageInParent();
11855             }
11856         }
11857     }
11858 
11859     /**
11860      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
11861      * set any flags or handle all of the cases handled by the default invalidation methods.
11862      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
11863      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
11864      * walk up the hierarchy, transforming the dirty rect as necessary.
11865      *
11866      * The method also handles normal invalidation logic if display list properties are not
11867      * being used in this view. The invalidateParent and forceRedraw flags are used by that
11868      * backup approach, to handle these cases used in the various property-setting methods.
11869      *
11870      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
11871      * are not being used in this view
11872      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
11873      * list properties are not being used in this view
11874      */
11875     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
11876         if (!isHardwareAccelerated()
11877                 || !mRenderNode.isValid()
11878                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
11879             if (invalidateParent) {
11880                 invalidateParentCaches();
11881             }
11882             if (forceRedraw) {
11883                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11884             }
11885             invalidate(false);
11886         } else {
11887             damageInParent();
11888         }
11889         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
11890             damageShadowReceiver();
11891         }
11892     }
11893 
11894     /**
11895      * Tells the parent view to damage this view's bounds.
11896      *
11897      * @hide
11898      */
11899     protected void damageInParent() {
11900         final AttachInfo ai = mAttachInfo;
11901         final ViewParent p = mParent;
11902         if (p != null && ai != null) {
11903             final Rect r = ai.mTmpInvalRect;
11904             r.set(0, 0, mRight - mLeft, mBottom - mTop);
11905             if (mParent instanceof ViewGroup) {
11906                 ((ViewGroup) mParent).damageChild(this, r);
11907             } else {
11908                 mParent.invalidateChild(this, r);
11909             }
11910         }
11911     }
11912 
11913     /**
11914      * Utility method to transform a given Rect by the current matrix of this view.
11915      */
11916     void transformRect(final Rect rect) {
11917         if (!getMatrix().isIdentity()) {
11918             RectF boundingRect = mAttachInfo.mTmpTransformRect;
11919             boundingRect.set(rect);
11920             getMatrix().mapRect(boundingRect);
11921             rect.set((int) Math.floor(boundingRect.left),
11922                     (int) Math.floor(boundingRect.top),
11923                     (int) Math.ceil(boundingRect.right),
11924                     (int) Math.ceil(boundingRect.bottom));
11925         }
11926     }
11927 
11928     /**
11929      * Used to indicate that the parent of this view should clear its caches. This functionality
11930      * is used to force the parent to rebuild its display list (when hardware-accelerated),
11931      * which is necessary when various parent-managed properties of the view change, such as
11932      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
11933      * clears the parent caches and does not causes an invalidate event.
11934      *
11935      * @hide
11936      */
11937     protected void invalidateParentCaches() {
11938         if (mParent instanceof View) {
11939             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
11940         }
11941     }
11942 
11943     /**
11944      * Used to indicate that the parent of this view should be invalidated. This functionality
11945      * is used to force the parent to rebuild its display list (when hardware-accelerated),
11946      * which is necessary when various parent-managed properties of the view change, such as
11947      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
11948      * an invalidation event to the parent.
11949      *
11950      * @hide
11951      */
11952     protected void invalidateParentIfNeeded() {
11953         if (isHardwareAccelerated() && mParent instanceof View) {
11954             ((View) mParent).invalidate(true);
11955         }
11956     }
11957 
11958     /**
11959      * @hide
11960      */
11961     protected void invalidateParentIfNeededAndWasQuickRejected() {
11962         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
11963             // View was rejected last time it was drawn by its parent; this may have changed
11964             invalidateParentIfNeeded();
11965         }
11966     }
11967 
11968     /**
11969      * Indicates whether this View is opaque. An opaque View guarantees that it will
11970      * draw all the pixels overlapping its bounds using a fully opaque color.
11971      *
11972      * Subclasses of View should override this method whenever possible to indicate
11973      * whether an instance is opaque. Opaque Views are treated in a special way by
11974      * the View hierarchy, possibly allowing it to perform optimizations during
11975      * invalidate/draw passes.
11976      *
11977      * @return True if this View is guaranteed to be fully opaque, false otherwise.
11978      */
11979     @ViewDebug.ExportedProperty(category = "drawing")
11980     public boolean isOpaque() {
11981         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
11982                 getFinalAlpha() >= 1.0f;
11983     }
11984 
11985     /**
11986      * @hide
11987      */
11988     protected void computeOpaqueFlags() {
11989         // Opaque if:
11990         //   - Has a background
11991         //   - Background is opaque
11992         //   - Doesn't have scrollbars or scrollbars overlay
11993 
11994         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
11995             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
11996         } else {
11997             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
11998         }
11999 
12000         final int flags = mViewFlags;
12001         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12002                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12003                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12004             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12005         } else {
12006             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12007         }
12008     }
12009 
12010     /**
12011      * @hide
12012      */
12013     protected boolean hasOpaqueScrollbars() {
12014         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12015     }
12016 
12017     /**
12018      * @return A handler associated with the thread running the View. This
12019      * handler can be used to pump events in the UI events queue.
12020      */
12021     public Handler getHandler() {
12022         final AttachInfo attachInfo = mAttachInfo;
12023         if (attachInfo != null) {
12024             return attachInfo.mHandler;
12025         }
12026         return null;
12027     }
12028 
12029     /**
12030      * Gets the view root associated with the View.
12031      * @return The view root, or null if none.
12032      * @hide
12033      */
12034     public ViewRootImpl getViewRootImpl() {
12035         if (mAttachInfo != null) {
12036             return mAttachInfo.mViewRootImpl;
12037         }
12038         return null;
12039     }
12040 
12041     /**
12042      * @hide
12043      */
12044     public HardwareRenderer getHardwareRenderer() {
12045         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12046     }
12047 
12048     /**
12049      * <p>Causes the Runnable to be added to the message queue.
12050      * The runnable will be run on the user interface thread.</p>
12051      *
12052      * @param action The Runnable that will be executed.
12053      *
12054      * @return Returns true if the Runnable was successfully placed in to the
12055      *         message queue.  Returns false on failure, usually because the
12056      *         looper processing the message queue is exiting.
12057      *
12058      * @see #postDelayed
12059      * @see #removeCallbacks
12060      */
12061     public boolean post(Runnable action) {
12062         final AttachInfo attachInfo = mAttachInfo;
12063         if (attachInfo != null) {
12064             return attachInfo.mHandler.post(action);
12065         }
12066         // Assume that post will succeed later
12067         ViewRootImpl.getRunQueue().post(action);
12068         return true;
12069     }
12070 
12071     /**
12072      * <p>Causes the Runnable to be added to the message queue, to be run
12073      * after the specified amount of time elapses.
12074      * The runnable will be run on the user interface thread.</p>
12075      *
12076      * @param action The Runnable that will be executed.
12077      * @param delayMillis The delay (in milliseconds) until the Runnable
12078      *        will be executed.
12079      *
12080      * @return true if the Runnable was successfully placed in to the
12081      *         message queue.  Returns false on failure, usually because the
12082      *         looper processing the message queue is exiting.  Note that a
12083      *         result of true does not mean the Runnable will be processed --
12084      *         if the looper is quit before the delivery time of the message
12085      *         occurs then the message will be dropped.
12086      *
12087      * @see #post
12088      * @see #removeCallbacks
12089      */
12090     public boolean postDelayed(Runnable action, long delayMillis) {
12091         final AttachInfo attachInfo = mAttachInfo;
12092         if (attachInfo != null) {
12093             return attachInfo.mHandler.postDelayed(action, delayMillis);
12094         }
12095         // Assume that post will succeed later
12096         ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12097         return true;
12098     }
12099 
12100     /**
12101      * <p>Causes the Runnable to execute on the next animation time step.
12102      * The runnable will be run on the user interface thread.</p>
12103      *
12104      * @param action The Runnable that will be executed.
12105      *
12106      * @see #postOnAnimationDelayed
12107      * @see #removeCallbacks
12108      */
12109     public void postOnAnimation(Runnable action) {
12110         final AttachInfo attachInfo = mAttachInfo;
12111         if (attachInfo != null) {
12112             attachInfo.mViewRootImpl.mChoreographer.postCallback(
12113                     Choreographer.CALLBACK_ANIMATION, action, null);
12114         } else {
12115             // Assume that post will succeed later
12116             ViewRootImpl.getRunQueue().post(action);
12117         }
12118     }
12119 
12120     /**
12121      * <p>Causes the Runnable to execute on the next animation time step,
12122      * after the specified amount of time elapses.
12123      * The runnable will be run on the user interface thread.</p>
12124      *
12125      * @param action The Runnable that will be executed.
12126      * @param delayMillis The delay (in milliseconds) until the Runnable
12127      *        will be executed.
12128      *
12129      * @see #postOnAnimation
12130      * @see #removeCallbacks
12131      */
12132     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12133         final AttachInfo attachInfo = mAttachInfo;
12134         if (attachInfo != null) {
12135             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12136                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12137         } else {
12138             // Assume that post will succeed later
12139             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12140         }
12141     }
12142 
12143     /**
12144      * <p>Removes the specified Runnable from the message queue.</p>
12145      *
12146      * @param action The Runnable to remove from the message handling queue
12147      *
12148      * @return true if this view could ask the Handler to remove the Runnable,
12149      *         false otherwise. When the returned value is true, the Runnable
12150      *         may or may not have been actually removed from the message queue
12151      *         (for instance, if the Runnable was not in the queue already.)
12152      *
12153      * @see #post
12154      * @see #postDelayed
12155      * @see #postOnAnimation
12156      * @see #postOnAnimationDelayed
12157      */
12158     public boolean removeCallbacks(Runnable action) {
12159         if (action != null) {
12160             final AttachInfo attachInfo = mAttachInfo;
12161             if (attachInfo != null) {
12162                 attachInfo.mHandler.removeCallbacks(action);
12163                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
12164                         Choreographer.CALLBACK_ANIMATION, action, null);
12165             }
12166             // Assume that post will succeed later
12167             ViewRootImpl.getRunQueue().removeCallbacks(action);
12168         }
12169         return true;
12170     }
12171 
12172     /**
12173      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12174      * Use this to invalidate the View from a non-UI thread.</p>
12175      *
12176      * <p>This method can be invoked from outside of the UI thread
12177      * only when this View is attached to a window.</p>
12178      *
12179      * @see #invalidate()
12180      * @see #postInvalidateDelayed(long)
12181      */
12182     public void postInvalidate() {
12183         postInvalidateDelayed(0);
12184     }
12185 
12186     /**
12187      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12188      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12189      *
12190      * <p>This method can be invoked from outside of the UI thread
12191      * only when this View is attached to a window.</p>
12192      *
12193      * @param left The left coordinate of the rectangle to invalidate.
12194      * @param top The top coordinate of the rectangle to invalidate.
12195      * @param right The right coordinate of the rectangle to invalidate.
12196      * @param bottom The bottom coordinate of the rectangle to invalidate.
12197      *
12198      * @see #invalidate(int, int, int, int)
12199      * @see #invalidate(Rect)
12200      * @see #postInvalidateDelayed(long, int, int, int, int)
12201      */
12202     public void postInvalidate(int left, int top, int right, int bottom) {
12203         postInvalidateDelayed(0, left, top, right, bottom);
12204     }
12205 
12206     /**
12207      * <p>Cause an invalidate to happen on a subsequent cycle through the event
12208      * loop. Waits for the specified amount of time.</p>
12209      *
12210      * <p>This method can be invoked from outside of the UI thread
12211      * only when this View is attached to a window.</p>
12212      *
12213      * @param delayMilliseconds the duration in milliseconds to delay the
12214      *         invalidation by
12215      *
12216      * @see #invalidate()
12217      * @see #postInvalidate()
12218      */
12219     public void postInvalidateDelayed(long delayMilliseconds) {
12220         // We try only with the AttachInfo because there's no point in invalidating
12221         // if we are not attached to our window
12222         final AttachInfo attachInfo = mAttachInfo;
12223         if (attachInfo != null) {
12224             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12225         }
12226     }
12227 
12228     /**
12229      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12230      * through the event loop. Waits for the specified amount of time.</p>
12231      *
12232      * <p>This method can be invoked from outside of the UI thread
12233      * only when this View is attached to a window.</p>
12234      *
12235      * @param delayMilliseconds the duration in milliseconds to delay the
12236      *         invalidation by
12237      * @param left The left coordinate of the rectangle to invalidate.
12238      * @param top The top coordinate of the rectangle to invalidate.
12239      * @param right The right coordinate of the rectangle to invalidate.
12240      * @param bottom The bottom coordinate of the rectangle to invalidate.
12241      *
12242      * @see #invalidate(int, int, int, int)
12243      * @see #invalidate(Rect)
12244      * @see #postInvalidate(int, int, int, int)
12245      */
12246     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12247             int right, int bottom) {
12248 
12249         // We try only with the AttachInfo because there's no point in invalidating
12250         // if we are not attached to our window
12251         final AttachInfo attachInfo = mAttachInfo;
12252         if (attachInfo != null) {
12253             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12254             info.target = this;
12255             info.left = left;
12256             info.top = top;
12257             info.right = right;
12258             info.bottom = bottom;
12259 
12260             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12261         }
12262     }
12263 
12264     /**
12265      * <p>Cause an invalidate to happen on the next animation time step, typically the
12266      * next display frame.</p>
12267      *
12268      * <p>This method can be invoked from outside of the UI thread
12269      * only when this View is attached to a window.</p>
12270      *
12271      * @see #invalidate()
12272      */
12273     public void postInvalidateOnAnimation() {
12274         // We try only with the AttachInfo because there's no point in invalidating
12275         // if we are not attached to our window
12276         final AttachInfo attachInfo = mAttachInfo;
12277         if (attachInfo != null) {
12278             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12279         }
12280     }
12281 
12282     /**
12283      * <p>Cause an invalidate of the specified area to happen on the next animation
12284      * time step, typically the next display frame.</p>
12285      *
12286      * <p>This method can be invoked from outside of the UI thread
12287      * only when this View is attached to a window.</p>
12288      *
12289      * @param left The left coordinate of the rectangle to invalidate.
12290      * @param top The top coordinate of the rectangle to invalidate.
12291      * @param right The right coordinate of the rectangle to invalidate.
12292      * @param bottom The bottom coordinate of the rectangle to invalidate.
12293      *
12294      * @see #invalidate(int, int, int, int)
12295      * @see #invalidate(Rect)
12296      */
12297     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12298         // We try only with the AttachInfo because there's no point in invalidating
12299         // if we are not attached to our window
12300         final AttachInfo attachInfo = mAttachInfo;
12301         if (attachInfo != null) {
12302             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12303             info.target = this;
12304             info.left = left;
12305             info.top = top;
12306             info.right = right;
12307             info.bottom = bottom;
12308 
12309             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12310         }
12311     }
12312 
12313     /**
12314      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12315      * This event is sent at most once every
12316      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12317      */
12318     private void postSendViewScrolledAccessibilityEventCallback() {
12319         if (mSendViewScrolledAccessibilityEvent == null) {
12320             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12321         }
12322         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12323             mSendViewScrolledAccessibilityEvent.mIsPending = true;
12324             postDelayed(mSendViewScrolledAccessibilityEvent,
12325                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12326         }
12327     }
12328 
12329     /**
12330      * Called by a parent to request that a child update its values for mScrollX
12331      * and mScrollY if necessary. This will typically be done if the child is
12332      * animating a scroll using a {@link android.widget.Scroller Scroller}
12333      * object.
12334      */
12335     public void computeScroll() {
12336     }
12337 
12338     /**
12339      * <p>Indicate whether the horizontal edges are faded when the view is
12340      * scrolled horizontally.</p>
12341      *
12342      * @return true if the horizontal edges should are faded on scroll, false
12343      *         otherwise
12344      *
12345      * @see #setHorizontalFadingEdgeEnabled(boolean)
12346      *
12347      * @attr ref android.R.styleable#View_requiresFadingEdge
12348      */
12349     public boolean isHorizontalFadingEdgeEnabled() {
12350         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12351     }
12352 
12353     /**
12354      * <p>Define whether the horizontal edges should be faded when this view
12355      * is scrolled horizontally.</p>
12356      *
12357      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12358      *                                    be faded when the view is scrolled
12359      *                                    horizontally
12360      *
12361      * @see #isHorizontalFadingEdgeEnabled()
12362      *
12363      * @attr ref android.R.styleable#View_requiresFadingEdge
12364      */
12365     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12366         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12367             if (horizontalFadingEdgeEnabled) {
12368                 initScrollCache();
12369             }
12370 
12371             mViewFlags ^= FADING_EDGE_HORIZONTAL;
12372         }
12373     }
12374 
12375     /**
12376      * <p>Indicate whether the vertical edges are faded when the view is
12377      * scrolled horizontally.</p>
12378      *
12379      * @return true if the vertical edges should are faded on scroll, false
12380      *         otherwise
12381      *
12382      * @see #setVerticalFadingEdgeEnabled(boolean)
12383      *
12384      * @attr ref android.R.styleable#View_requiresFadingEdge
12385      */
12386     public boolean isVerticalFadingEdgeEnabled() {
12387         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12388     }
12389 
12390     /**
12391      * <p>Define whether the vertical edges should be faded when this view
12392      * is scrolled vertically.</p>
12393      *
12394      * @param verticalFadingEdgeEnabled true if the vertical edges should
12395      *                                  be faded when the view is scrolled
12396      *                                  vertically
12397      *
12398      * @see #isVerticalFadingEdgeEnabled()
12399      *
12400      * @attr ref android.R.styleable#View_requiresFadingEdge
12401      */
12402     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12403         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12404             if (verticalFadingEdgeEnabled) {
12405                 initScrollCache();
12406             }
12407 
12408             mViewFlags ^= FADING_EDGE_VERTICAL;
12409         }
12410     }
12411 
12412     /**
12413      * Returns the strength, or intensity, of the top faded edge. The strength is
12414      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12415      * returns 0.0 or 1.0 but no value in between.
12416      *
12417      * Subclasses should override this method to provide a smoother fade transition
12418      * when scrolling occurs.
12419      *
12420      * @return the intensity of the top fade as a float between 0.0f and 1.0f
12421      */
12422     protected float getTopFadingEdgeStrength() {
12423         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12424     }
12425 
12426     /**
12427      * Returns the strength, or intensity, of the bottom faded edge. The strength is
12428      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12429      * returns 0.0 or 1.0 but no value in between.
12430      *
12431      * Subclasses should override this method to provide a smoother fade transition
12432      * when scrolling occurs.
12433      *
12434      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12435      */
12436     protected float getBottomFadingEdgeStrength() {
12437         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12438                 computeVerticalScrollRange() ? 1.0f : 0.0f;
12439     }
12440 
12441     /**
12442      * Returns the strength, or intensity, of the left faded edge. The strength is
12443      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12444      * returns 0.0 or 1.0 but no value in between.
12445      *
12446      * Subclasses should override this method to provide a smoother fade transition
12447      * when scrolling occurs.
12448      *
12449      * @return the intensity of the left fade as a float between 0.0f and 1.0f
12450      */
12451     protected float getLeftFadingEdgeStrength() {
12452         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12453     }
12454 
12455     /**
12456      * Returns the strength, or intensity, of the right faded edge. The strength is
12457      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12458      * returns 0.0 or 1.0 but no value in between.
12459      *
12460      * Subclasses should override this method to provide a smoother fade transition
12461      * when scrolling occurs.
12462      *
12463      * @return the intensity of the right fade as a float between 0.0f and 1.0f
12464      */
12465     protected float getRightFadingEdgeStrength() {
12466         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12467                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
12468     }
12469 
12470     /**
12471      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12472      * scrollbar is not drawn by default.</p>
12473      *
12474      * @return true if the horizontal scrollbar should be painted, false
12475      *         otherwise
12476      *
12477      * @see #setHorizontalScrollBarEnabled(boolean)
12478      */
12479     public boolean isHorizontalScrollBarEnabled() {
12480         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12481     }
12482 
12483     /**
12484      * <p>Define whether the horizontal scrollbar should be drawn or not. The
12485      * scrollbar is not drawn by default.</p>
12486      *
12487      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12488      *                                   be painted
12489      *
12490      * @see #isHorizontalScrollBarEnabled()
12491      */
12492     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12493         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12494             mViewFlags ^= SCROLLBARS_HORIZONTAL;
12495             computeOpaqueFlags();
12496             resolvePadding();
12497         }
12498     }
12499 
12500     /**
12501      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12502      * scrollbar is not drawn by default.</p>
12503      *
12504      * @return true if the vertical scrollbar should be painted, false
12505      *         otherwise
12506      *
12507      * @see #setVerticalScrollBarEnabled(boolean)
12508      */
12509     public boolean isVerticalScrollBarEnabled() {
12510         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12511     }
12512 
12513     /**
12514      * <p>Define whether the vertical scrollbar should be drawn or not. The
12515      * scrollbar is not drawn by default.</p>
12516      *
12517      * @param verticalScrollBarEnabled true if the vertical scrollbar should
12518      *                                 be painted
12519      *
12520      * @see #isVerticalScrollBarEnabled()
12521      */
12522     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12523         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12524             mViewFlags ^= SCROLLBARS_VERTICAL;
12525             computeOpaqueFlags();
12526             resolvePadding();
12527         }
12528     }
12529 
12530     /**
12531      * @hide
12532      */
12533     protected void recomputePadding() {
12534         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12535     }
12536 
12537     /**
12538      * Define whether scrollbars will fade when the view is not scrolling.
12539      *
12540      * @param fadeScrollbars wheter to enable fading
12541      *
12542      * @attr ref android.R.styleable#View_fadeScrollbars
12543      */
12544     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12545         initScrollCache();
12546         final ScrollabilityCache scrollabilityCache = mScrollCache;
12547         scrollabilityCache.fadeScrollBars = fadeScrollbars;
12548         if (fadeScrollbars) {
12549             scrollabilityCache.state = ScrollabilityCache.OFF;
12550         } else {
12551             scrollabilityCache.state = ScrollabilityCache.ON;
12552         }
12553     }
12554 
12555     /**
12556      *
12557      * Returns true if scrollbars will fade when this view is not scrolling
12558      *
12559      * @return true if scrollbar fading is enabled
12560      *
12561      * @attr ref android.R.styleable#View_fadeScrollbars
12562      */
12563     public boolean isScrollbarFadingEnabled() {
12564         return mScrollCache != null && mScrollCache.fadeScrollBars;
12565     }
12566 
12567     /**
12568      *
12569      * Returns the delay before scrollbars fade.
12570      *
12571      * @return the delay before scrollbars fade
12572      *
12573      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12574      */
12575     public int getScrollBarDefaultDelayBeforeFade() {
12576         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12577                 mScrollCache.scrollBarDefaultDelayBeforeFade;
12578     }
12579 
12580     /**
12581      * Define the delay before scrollbars fade.
12582      *
12583      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12584      *
12585      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12586      */
12587     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12588         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12589     }
12590 
12591     /**
12592      *
12593      * Returns the scrollbar fade duration.
12594      *
12595      * @return the scrollbar fade duration
12596      *
12597      * @attr ref android.R.styleable#View_scrollbarFadeDuration
12598      */
12599     public int getScrollBarFadeDuration() {
12600         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
12601                 mScrollCache.scrollBarFadeDuration;
12602     }
12603 
12604     /**
12605      * Define the scrollbar fade duration.
12606      *
12607      * @param scrollBarFadeDuration - the scrollbar fade duration
12608      *
12609      * @attr ref android.R.styleable#View_scrollbarFadeDuration
12610      */
12611     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
12612         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
12613     }
12614 
12615     /**
12616      *
12617      * Returns the scrollbar size.
12618      *
12619      * @return the scrollbar size
12620      *
12621      * @attr ref android.R.styleable#View_scrollbarSize
12622      */
12623     public int getScrollBarSize() {
12624         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
12625                 mScrollCache.scrollBarSize;
12626     }
12627 
12628     /**
12629      * Define the scrollbar size.
12630      *
12631      * @param scrollBarSize - the scrollbar size
12632      *
12633      * @attr ref android.R.styleable#View_scrollbarSize
12634      */
12635     public void setScrollBarSize(int scrollBarSize) {
12636         getScrollCache().scrollBarSize = scrollBarSize;
12637     }
12638 
12639     /**
12640      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12641      * inset. When inset, they add to the padding of the view. And the scrollbars
12642      * can be drawn inside the padding area or on the edge of the view. For example,
12643      * if a view has a background drawable and you want to draw the scrollbars
12644      * inside the padding specified by the drawable, you can use
12645      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12646      * appear at the edge of the view, ignoring the padding, then you can use
12647      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12648      * @param style the style of the scrollbars. Should be one of
12649      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12650      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12651      * @see #SCROLLBARS_INSIDE_OVERLAY
12652      * @see #SCROLLBARS_INSIDE_INSET
12653      * @see #SCROLLBARS_OUTSIDE_OVERLAY
12654      * @see #SCROLLBARS_OUTSIDE_INSET
12655      *
12656      * @attr ref android.R.styleable#View_scrollbarStyle
12657      */
12658     public void setScrollBarStyle(@ScrollBarStyle int style) {
12659         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12660             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12661             computeOpaqueFlags();
12662             resolvePadding();
12663         }
12664     }
12665 
12666     /**
12667      * <p>Returns the current scrollbar style.</p>
12668      * @return the current scrollbar style
12669      * @see #SCROLLBARS_INSIDE_OVERLAY
12670      * @see #SCROLLBARS_INSIDE_INSET
12671      * @see #SCROLLBARS_OUTSIDE_OVERLAY
12672      * @see #SCROLLBARS_OUTSIDE_INSET
12673      *
12674      * @attr ref android.R.styleable#View_scrollbarStyle
12675      */
12676     @ViewDebug.ExportedProperty(mapping = {
12677             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12678             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12679             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12680             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12681     })
12682     @ScrollBarStyle
12683     public int getScrollBarStyle() {
12684         return mViewFlags & SCROLLBARS_STYLE_MASK;
12685     }
12686 
12687     /**
12688      * <p>Compute the horizontal range that the horizontal scrollbar
12689      * represents.</p>
12690      *
12691      * <p>The range is expressed in arbitrary units that must be the same as the
12692      * units used by {@link #computeHorizontalScrollExtent()} and
12693      * {@link #computeHorizontalScrollOffset()}.</p>
12694      *
12695      * <p>The default range is the drawing width of this view.</p>
12696      *
12697      * @return the total horizontal range represented by the horizontal
12698      *         scrollbar
12699      *
12700      * @see #computeHorizontalScrollExtent()
12701      * @see #computeHorizontalScrollOffset()
12702      * @see android.widget.ScrollBarDrawable
12703      */
12704     protected int computeHorizontalScrollRange() {
12705         return getWidth();
12706     }
12707 
12708     /**
12709      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12710      * within the horizontal range. This value is used to compute the position
12711      * of the thumb within the scrollbar's track.</p>
12712      *
12713      * <p>The range is expressed in arbitrary units that must be the same as the
12714      * units used by {@link #computeHorizontalScrollRange()} and
12715      * {@link #computeHorizontalScrollExtent()}.</p>
12716      *
12717      * <p>The default offset is the scroll offset of this view.</p>
12718      *
12719      * @return the horizontal offset of the scrollbar's thumb
12720      *
12721      * @see #computeHorizontalScrollRange()
12722      * @see #computeHorizontalScrollExtent()
12723      * @see android.widget.ScrollBarDrawable
12724      */
12725     protected int computeHorizontalScrollOffset() {
12726         return mScrollX;
12727     }
12728 
12729     /**
12730      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
12731      * within the horizontal range. This value is used to compute the length
12732      * of the thumb within the scrollbar's track.</p>
12733      *
12734      * <p>The range is expressed in arbitrary units that must be the same as the
12735      * units used by {@link #computeHorizontalScrollRange()} and
12736      * {@link #computeHorizontalScrollOffset()}.</p>
12737      *
12738      * <p>The default extent is the drawing width of this view.</p>
12739      *
12740      * @return the horizontal extent of the scrollbar's thumb
12741      *
12742      * @see #computeHorizontalScrollRange()
12743      * @see #computeHorizontalScrollOffset()
12744      * @see android.widget.ScrollBarDrawable
12745      */
12746     protected int computeHorizontalScrollExtent() {
12747         return getWidth();
12748     }
12749 
12750     /**
12751      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
12752      *
12753      * <p>The range is expressed in arbitrary units that must be the same as the
12754      * units used by {@link #computeVerticalScrollExtent()} and
12755      * {@link #computeVerticalScrollOffset()}.</p>
12756      *
12757      * @return the total vertical range represented by the vertical scrollbar
12758      *
12759      * <p>The default range is the drawing height of this view.</p>
12760      *
12761      * @see #computeVerticalScrollExtent()
12762      * @see #computeVerticalScrollOffset()
12763      * @see android.widget.ScrollBarDrawable
12764      */
12765     protected int computeVerticalScrollRange() {
12766         return getHeight();
12767     }
12768 
12769     /**
12770      * <p>Compute the vertical offset of the vertical scrollbar's thumb
12771      * within the horizontal range. This value is used to compute the position
12772      * of the thumb within the scrollbar's track.</p>
12773      *
12774      * <p>The range is expressed in arbitrary units that must be the same as the
12775      * units used by {@link #computeVerticalScrollRange()} and
12776      * {@link #computeVerticalScrollExtent()}.</p>
12777      *
12778      * <p>The default offset is the scroll offset of this view.</p>
12779      *
12780      * @return the vertical offset of the scrollbar's thumb
12781      *
12782      * @see #computeVerticalScrollRange()
12783      * @see #computeVerticalScrollExtent()
12784      * @see android.widget.ScrollBarDrawable
12785      */
12786     protected int computeVerticalScrollOffset() {
12787         return mScrollY;
12788     }
12789 
12790     /**
12791      * <p>Compute the vertical extent of the vertical scrollbar's thumb
12792      * within the vertical range. This value is used to compute the length
12793      * of the thumb within the scrollbar's track.</p>
12794      *
12795      * <p>The range is expressed in arbitrary units that must be the same as the
12796      * units used by {@link #computeVerticalScrollRange()} and
12797      * {@link #computeVerticalScrollOffset()}.</p>
12798      *
12799      * <p>The default extent is the drawing height of this view.</p>
12800      *
12801      * @return the vertical extent of the scrollbar's thumb
12802      *
12803      * @see #computeVerticalScrollRange()
12804      * @see #computeVerticalScrollOffset()
12805      * @see android.widget.ScrollBarDrawable
12806      */
12807     protected int computeVerticalScrollExtent() {
12808         return getHeight();
12809     }
12810 
12811     /**
12812      * Check if this view can be scrolled horizontally in a certain direction.
12813      *
12814      * @param direction Negative to check scrolling left, positive to check scrolling right.
12815      * @return true if this view can be scrolled in the specified direction, false otherwise.
12816      */
12817     public boolean canScrollHorizontally(int direction) {
12818         final int offset = computeHorizontalScrollOffset();
12819         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
12820         if (range == 0) return false;
12821         if (direction < 0) {
12822             return offset > 0;
12823         } else {
12824             return offset < range - 1;
12825         }
12826     }
12827 
12828     /**
12829      * Check if this view can be scrolled vertically in a certain direction.
12830      *
12831      * @param direction Negative to check scrolling up, positive to check scrolling down.
12832      * @return true if this view can be scrolled in the specified direction, false otherwise.
12833      */
12834     public boolean canScrollVertically(int direction) {
12835         final int offset = computeVerticalScrollOffset();
12836         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
12837         if (range == 0) return false;
12838         if (direction < 0) {
12839             return offset > 0;
12840         } else {
12841             return offset < range - 1;
12842         }
12843     }
12844 
12845     /**
12846      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
12847      * scrollbars are painted only if they have been awakened first.</p>
12848      *
12849      * @param canvas the canvas on which to draw the scrollbars
12850      *
12851      * @see #awakenScrollBars(int)
12852      */
12853     protected final void onDrawScrollBars(Canvas canvas) {
12854         // scrollbars are drawn only when the animation is running
12855         final ScrollabilityCache cache = mScrollCache;
12856         if (cache != null) {
12857 
12858             int state = cache.state;
12859 
12860             if (state == ScrollabilityCache.OFF) {
12861                 return;
12862             }
12863 
12864             boolean invalidate = false;
12865 
12866             if (state == ScrollabilityCache.FADING) {
12867                 // We're fading -- get our fade interpolation
12868                 if (cache.interpolatorValues == null) {
12869                     cache.interpolatorValues = new float[1];
12870                 }
12871 
12872                 float[] values = cache.interpolatorValues;
12873 
12874                 // Stops the animation if we're done
12875                 if (cache.scrollBarInterpolator.timeToValues(values) ==
12876                         Interpolator.Result.FREEZE_END) {
12877                     cache.state = ScrollabilityCache.OFF;
12878                 } else {
12879                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
12880                 }
12881 
12882                 // This will make the scroll bars inval themselves after
12883                 // drawing. We only want this when we're fading so that
12884                 // we prevent excessive redraws
12885                 invalidate = true;
12886             } else {
12887                 // We're just on -- but we may have been fading before so
12888                 // reset alpha
12889                 cache.scrollBar.mutate().setAlpha(255);
12890             }
12891 
12892 
12893             final int viewFlags = mViewFlags;
12894 
12895             final boolean drawHorizontalScrollBar =
12896                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12897             final boolean drawVerticalScrollBar =
12898                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
12899                 && !isVerticalScrollBarHidden();
12900 
12901             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
12902                 final int width = mRight - mLeft;
12903                 final int height = mBottom - mTop;
12904 
12905                 final ScrollBarDrawable scrollBar = cache.scrollBar;
12906 
12907                 final int scrollX = mScrollX;
12908                 final int scrollY = mScrollY;
12909                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
12910 
12911                 int left;
12912                 int top;
12913                 int right;
12914                 int bottom;
12915 
12916                 if (drawHorizontalScrollBar) {
12917                     int size = scrollBar.getSize(false);
12918                     if (size <= 0) {
12919                         size = cache.scrollBarSize;
12920                     }
12921 
12922                     scrollBar.setParameters(computeHorizontalScrollRange(),
12923                                             computeHorizontalScrollOffset(),
12924                                             computeHorizontalScrollExtent(), false);
12925                     final int verticalScrollBarGap = drawVerticalScrollBar ?
12926                             getVerticalScrollbarWidth() : 0;
12927                     top = scrollY + height - size - (mUserPaddingBottom & inside);
12928                     left = scrollX + (mPaddingLeft & inside);
12929                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
12930                     bottom = top + size;
12931                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
12932                     if (invalidate) {
12933                         invalidate(left, top, right, bottom);
12934                     }
12935                 }
12936 
12937                 if (drawVerticalScrollBar) {
12938                     int size = scrollBar.getSize(true);
12939                     if (size <= 0) {
12940                         size = cache.scrollBarSize;
12941                     }
12942 
12943                     scrollBar.setParameters(computeVerticalScrollRange(),
12944                                             computeVerticalScrollOffset(),
12945                                             computeVerticalScrollExtent(), true);
12946                     int verticalScrollbarPosition = mVerticalScrollbarPosition;
12947                     if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
12948                         verticalScrollbarPosition = isLayoutRtl() ?
12949                                 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
12950                     }
12951                     switch (verticalScrollbarPosition) {
12952                         default:
12953                         case SCROLLBAR_POSITION_RIGHT:
12954                             left = scrollX + width - size - (mUserPaddingRight & inside);
12955                             break;
12956                         case SCROLLBAR_POSITION_LEFT:
12957                             left = scrollX + (mUserPaddingLeft & inside);
12958                             break;
12959                     }
12960                     top = scrollY + (mPaddingTop & inside);
12961                     right = left + size;
12962                     bottom = scrollY + height - (mUserPaddingBottom & inside);
12963                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
12964                     if (invalidate) {
12965                         invalidate(left, top, right, bottom);
12966                     }
12967                 }
12968             }
12969         }
12970     }
12971 
12972     /**
12973      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
12974      * FastScroller is visible.
12975      * @return whether to temporarily hide the vertical scrollbar
12976      * @hide
12977      */
12978     protected boolean isVerticalScrollBarHidden() {
12979         return false;
12980     }
12981 
12982     /**
12983      * <p>Draw the horizontal scrollbar if
12984      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
12985      *
12986      * @param canvas the canvas on which to draw the scrollbar
12987      * @param scrollBar the scrollbar's drawable
12988      *
12989      * @see #isHorizontalScrollBarEnabled()
12990      * @see #computeHorizontalScrollRange()
12991      * @see #computeHorizontalScrollExtent()
12992      * @see #computeHorizontalScrollOffset()
12993      * @see android.widget.ScrollBarDrawable
12994      * @hide
12995      */
12996     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
12997             int l, int t, int r, int b) {
12998         scrollBar.setBounds(l, t, r, b);
12999         scrollBar.draw(canvas);
13000     }
13001 
13002     /**
13003      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13004      * returns true.</p>
13005      *
13006      * @param canvas the canvas on which to draw the scrollbar
13007      * @param scrollBar the scrollbar's drawable
13008      *
13009      * @see #isVerticalScrollBarEnabled()
13010      * @see #computeVerticalScrollRange()
13011      * @see #computeVerticalScrollExtent()
13012      * @see #computeVerticalScrollOffset()
13013      * @see android.widget.ScrollBarDrawable
13014      * @hide
13015      */
13016     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13017             int l, int t, int r, int b) {
13018         scrollBar.setBounds(l, t, r, b);
13019         scrollBar.draw(canvas);
13020     }
13021 
13022     /**
13023      * Implement this to do your drawing.
13024      *
13025      * @param canvas the canvas on which the background will be drawn
13026      */
13027     protected void onDraw(Canvas canvas) {
13028     }
13029 
13030     /*
13031      * Caller is responsible for calling requestLayout if necessary.
13032      * (This allows addViewInLayout to not request a new layout.)
13033      */
13034     void assignParent(ViewParent parent) {
13035         if (mParent == null) {
13036             mParent = parent;
13037         } else if (parent == null) {
13038             mParent = null;
13039         } else {
13040             throw new RuntimeException("view " + this + " being added, but"
13041                     + " it already has a parent");
13042         }
13043     }
13044 
13045     /**
13046      * This is called when the view is attached to a window.  At this point it
13047      * has a Surface and will start drawing.  Note that this function is
13048      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
13049      * however it may be called any time before the first onDraw -- including
13050      * before or after {@link #onMeasure(int, int)}.
13051      *
13052      * @see #onDetachedFromWindow()
13053      */
13054     protected void onAttachedToWindow() {
13055         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
13056             mParent.requestTransparentRegion(this);
13057         }
13058 
13059         if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
13060             initialAwakenScrollBars();
13061             mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
13062         }
13063 
13064         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13065 
13066         jumpDrawablesToCurrentState();
13067 
13068         resetSubtreeAccessibilityStateChanged();
13069 
13070         // rebuild, since Outline not maintained while View is detached
13071         rebuildOutline();
13072 
13073         if (isFocused()) {
13074             InputMethodManager imm = InputMethodManager.peekInstance();
13075             imm.focusIn(this);
13076         }
13077     }
13078 
13079     /**
13080      * Resolve all RTL related properties.
13081      *
13082      * @return true if resolution of RTL properties has been done
13083      *
13084      * @hide
13085      */
13086     public boolean resolveRtlPropertiesIfNeeded() {
13087         if (!needRtlPropertiesResolution()) return false;
13088 
13089         // Order is important here: LayoutDirection MUST be resolved first
13090         if (!isLayoutDirectionResolved()) {
13091             resolveLayoutDirection();
13092             resolveLayoutParams();
13093         }
13094         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
13095         if (!isTextDirectionResolved()) {
13096             resolveTextDirection();
13097         }
13098         if (!isTextAlignmentResolved()) {
13099             resolveTextAlignment();
13100         }
13101         // Should resolve Drawables before Padding because we need the layout direction of the
13102         // Drawable to correctly resolve Padding.
13103         if (!areDrawablesResolved()) {
13104             resolveDrawables();
13105         }
13106         if (!isPaddingResolved()) {
13107             resolvePadding();
13108         }
13109         onRtlPropertiesChanged(getLayoutDirection());
13110         return true;
13111     }
13112 
13113     /**
13114      * Reset resolution of all RTL related properties.
13115      *
13116      * @hide
13117      */
13118     public void resetRtlProperties() {
13119         resetResolvedLayoutDirection();
13120         resetResolvedTextDirection();
13121         resetResolvedTextAlignment();
13122         resetResolvedPadding();
13123         resetResolvedDrawables();
13124     }
13125 
13126     /**
13127      * @see #onScreenStateChanged(int)
13128      */
13129     void dispatchScreenStateChanged(int screenState) {
13130         onScreenStateChanged(screenState);
13131     }
13132 
13133     /**
13134      * This method is called whenever the state of the screen this view is
13135      * attached to changes. A state change will usually occurs when the screen
13136      * turns on or off (whether it happens automatically or the user does it
13137      * manually.)
13138      *
13139      * @param screenState The new state of the screen. Can be either
13140      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
13141      */
13142     public void onScreenStateChanged(int screenState) {
13143     }
13144 
13145     /**
13146      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
13147      */
13148     private boolean hasRtlSupport() {
13149         return mContext.getApplicationInfo().hasRtlSupport();
13150     }
13151 
13152     /**
13153      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
13154      * RTL not supported)
13155      */
13156     private boolean isRtlCompatibilityMode() {
13157         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13158         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
13159     }
13160 
13161     /**
13162      * @return true if RTL properties need resolution.
13163      *
13164      */
13165     private boolean needRtlPropertiesResolution() {
13166         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
13167     }
13168 
13169     /**
13170      * Called when any RTL property (layout direction or text direction or text alignment) has
13171      * been changed.
13172      *
13173      * Subclasses need to override this method to take care of cached information that depends on the
13174      * resolved layout direction, or to inform child views that inherit their layout direction.
13175      *
13176      * The default implementation does nothing.
13177      *
13178      * @param layoutDirection the direction of the layout
13179      *
13180      * @see #LAYOUT_DIRECTION_LTR
13181      * @see #LAYOUT_DIRECTION_RTL
13182      */
13183     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13184     }
13185 
13186     /**
13187      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13188      * that the parent directionality can and will be resolved before its children.
13189      *
13190      * @return true if resolution has been done, false otherwise.
13191      *
13192      * @hide
13193      */
13194     public boolean resolveLayoutDirection() {
13195         // Clear any previous layout direction resolution
13196         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13197 
13198         if (hasRtlSupport()) {
13199             // Set resolved depending on layout direction
13200             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13201                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13202                 case LAYOUT_DIRECTION_INHERIT:
13203                     // We cannot resolve yet. LTR is by default and let the resolution happen again
13204                     // later to get the correct resolved value
13205                     if (!canResolveLayoutDirection()) return false;
13206 
13207                     // Parent has not yet resolved, LTR is still the default
13208                     try {
13209                         if (!mParent.isLayoutDirectionResolved()) return false;
13210 
13211                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13212                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13213                         }
13214                     } catch (AbstractMethodError e) {
13215                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13216                                 " does not fully implement ViewParent", e);
13217                     }
13218                     break;
13219                 case LAYOUT_DIRECTION_RTL:
13220                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13221                     break;
13222                 case LAYOUT_DIRECTION_LOCALE:
13223                     if((LAYOUT_DIRECTION_RTL ==
13224                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13225                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13226                     }
13227                     break;
13228                 default:
13229                     // Nothing to do, LTR by default
13230             }
13231         }
13232 
13233         // Set to resolved
13234         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13235         return true;
13236     }
13237 
13238     /**
13239      * Check if layout direction resolution can be done.
13240      *
13241      * @return true if layout direction resolution can be done otherwise return false.
13242      */
13243     public boolean canResolveLayoutDirection() {
13244         switch (getRawLayoutDirection()) {
13245             case LAYOUT_DIRECTION_INHERIT:
13246                 if (mParent != null) {
13247                     try {
13248                         return mParent.canResolveLayoutDirection();
13249                     } catch (AbstractMethodError e) {
13250                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13251                                 " does not fully implement ViewParent", e);
13252                     }
13253                 }
13254                 return false;
13255 
13256             default:
13257                 return true;
13258         }
13259     }
13260 
13261     /**
13262      * Reset the resolved layout direction. Layout direction will be resolved during a call to
13263      * {@link #onMeasure(int, int)}.
13264      *
13265      * @hide
13266      */
13267     public void resetResolvedLayoutDirection() {
13268         // Reset the current resolved bits
13269         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13270     }
13271 
13272     /**
13273      * @return true if the layout direction is inherited.
13274      *
13275      * @hide
13276      */
13277     public boolean isLayoutDirectionInherited() {
13278         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13279     }
13280 
13281     /**
13282      * @return true if layout direction has been resolved.
13283      */
13284     public boolean isLayoutDirectionResolved() {
13285         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13286     }
13287 
13288     /**
13289      * Return if padding has been resolved
13290      *
13291      * @hide
13292      */
13293     boolean isPaddingResolved() {
13294         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13295     }
13296 
13297     /**
13298      * Resolves padding depending on layout direction, if applicable, and
13299      * recomputes internal padding values to adjust for scroll bars.
13300      *
13301      * @hide
13302      */
13303     public void resolvePadding() {
13304         final int resolvedLayoutDirection = getLayoutDirection();
13305 
13306         if (!isRtlCompatibilityMode()) {
13307             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13308             // If start / end padding are defined, they will be resolved (hence overriding) to
13309             // left / right or right / left depending on the resolved layout direction.
13310             // If start / end padding are not defined, use the left / right ones.
13311             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13312                 Rect padding = sThreadLocal.get();
13313                 if (padding == null) {
13314                     padding = new Rect();
13315                     sThreadLocal.set(padding);
13316                 }
13317                 mBackground.getPadding(padding);
13318                 if (!mLeftPaddingDefined) {
13319                     mUserPaddingLeftInitial = padding.left;
13320                 }
13321                 if (!mRightPaddingDefined) {
13322                     mUserPaddingRightInitial = padding.right;
13323                 }
13324             }
13325             switch (resolvedLayoutDirection) {
13326                 case LAYOUT_DIRECTION_RTL:
13327                     if (mUserPaddingStart != UNDEFINED_PADDING) {
13328                         mUserPaddingRight = mUserPaddingStart;
13329                     } else {
13330                         mUserPaddingRight = mUserPaddingRightInitial;
13331                     }
13332                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
13333                         mUserPaddingLeft = mUserPaddingEnd;
13334                     } else {
13335                         mUserPaddingLeft = mUserPaddingLeftInitial;
13336                     }
13337                     break;
13338                 case LAYOUT_DIRECTION_LTR:
13339                 default:
13340                     if (mUserPaddingStart != UNDEFINED_PADDING) {
13341                         mUserPaddingLeft = mUserPaddingStart;
13342                     } else {
13343                         mUserPaddingLeft = mUserPaddingLeftInitial;
13344                     }
13345                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
13346                         mUserPaddingRight = mUserPaddingEnd;
13347                     } else {
13348                         mUserPaddingRight = mUserPaddingRightInitial;
13349                     }
13350             }
13351 
13352             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13353         }
13354 
13355         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13356         onRtlPropertiesChanged(resolvedLayoutDirection);
13357 
13358         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13359     }
13360 
13361     /**
13362      * Reset the resolved layout direction.
13363      *
13364      * @hide
13365      */
13366     public void resetResolvedPadding() {
13367         resetResolvedPaddingInternal();
13368     }
13369 
13370     /**
13371      * Used when we only want to reset *this* view's padding and not trigger overrides
13372      * in ViewGroup that reset children too.
13373      */
13374     void resetResolvedPaddingInternal() {
13375         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13376     }
13377 
13378     /**
13379      * This is called when the view is detached from a window.  At this point it
13380      * no longer has a surface for drawing.
13381      *
13382      * @see #onAttachedToWindow()
13383      */
13384     protected void onDetachedFromWindow() {
13385     }
13386 
13387     /**
13388      * This is a framework-internal mirror of onDetachedFromWindow() that's called
13389      * after onDetachedFromWindow().
13390      *
13391      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13392      * The super method should be called at the end of the overriden method to ensure
13393      * subclasses are destroyed first
13394      *
13395      * @hide
13396      */
13397     protected void onDetachedFromWindowInternal() {
13398         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13399         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13400 
13401         removeUnsetPressCallback();
13402         removeLongPressCallback();
13403         removePerformClickCallback();
13404         removeSendViewScrolledAccessibilityEventCallback();
13405         stopNestedScroll();
13406 
13407         // Anything that started animating right before detach should already
13408         // be in its final state when re-attached.
13409         jumpDrawablesToCurrentState();
13410 
13411         destroyDrawingCache();
13412 
13413         cleanupDraw();
13414         mCurrentAnimation = null;
13415     }
13416 
13417     private void cleanupDraw() {
13418         resetDisplayList();
13419         if (mAttachInfo != null) {
13420             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13421         }
13422     }
13423 
13424     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13425     }
13426 
13427     /**
13428      * @return The number of times this view has been attached to a window
13429      */
13430     protected int getWindowAttachCount() {
13431         return mWindowAttachCount;
13432     }
13433 
13434     /**
13435      * Retrieve a unique token identifying the window this view is attached to.
13436      * @return Return the window's token for use in
13437      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13438      */
13439     public IBinder getWindowToken() {
13440         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13441     }
13442 
13443     /**
13444      * Retrieve the {@link WindowId} for the window this view is
13445      * currently attached to.
13446      */
13447     public WindowId getWindowId() {
13448         if (mAttachInfo == null) {
13449             return null;
13450         }
13451         if (mAttachInfo.mWindowId == null) {
13452             try {
13453                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13454                         mAttachInfo.mWindowToken);
13455                 mAttachInfo.mWindowId = new WindowId(
13456                         mAttachInfo.mIWindowId);
13457             } catch (RemoteException e) {
13458             }
13459         }
13460         return mAttachInfo.mWindowId;
13461     }
13462 
13463     /**
13464      * Retrieve a unique token identifying the top-level "real" window of
13465      * the window that this view is attached to.  That is, this is like
13466      * {@link #getWindowToken}, except if the window this view in is a panel
13467      * window (attached to another containing window), then the token of
13468      * the containing window is returned instead.
13469      *
13470      * @return Returns the associated window token, either
13471      * {@link #getWindowToken()} or the containing window's token.
13472      */
13473     public IBinder getApplicationWindowToken() {
13474         AttachInfo ai = mAttachInfo;
13475         if (ai != null) {
13476             IBinder appWindowToken = ai.mPanelParentWindowToken;
13477             if (appWindowToken == null) {
13478                 appWindowToken = ai.mWindowToken;
13479             }
13480             return appWindowToken;
13481         }
13482         return null;
13483     }
13484 
13485     /**
13486      * Gets the logical display to which the view's window has been attached.
13487      *
13488      * @return The logical display, or null if the view is not currently attached to a window.
13489      */
13490     public Display getDisplay() {
13491         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13492     }
13493 
13494     /**
13495      * Retrieve private session object this view hierarchy is using to
13496      * communicate with the window manager.
13497      * @return the session object to communicate with the window manager
13498      */
13499     /*package*/ IWindowSession getWindowSession() {
13500         return mAttachInfo != null ? mAttachInfo.mSession : null;
13501     }
13502 
13503     /**
13504      * @param info the {@link android.view.View.AttachInfo} to associated with
13505      *        this view
13506      */
13507     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13508         //System.out.println("Attached! " + this);
13509         mAttachInfo = info;
13510         if (mOverlay != null) {
13511             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13512         }
13513         mWindowAttachCount++;
13514         // We will need to evaluate the drawable state at least once.
13515         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13516         if (mFloatingTreeObserver != null) {
13517             info.mTreeObserver.merge(mFloatingTreeObserver);
13518             mFloatingTreeObserver = null;
13519         }
13520         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13521             mAttachInfo.mScrollContainers.add(this);
13522             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13523         }
13524         performCollectViewAttributes(mAttachInfo, visibility);
13525         onAttachedToWindow();
13526 
13527         ListenerInfo li = mListenerInfo;
13528         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13529                 li != null ? li.mOnAttachStateChangeListeners : null;
13530         if (listeners != null && listeners.size() > 0) {
13531             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13532             // perform the dispatching. The iterator is a safe guard against listeners that
13533             // could mutate the list by calling the various add/remove methods. This prevents
13534             // the array from being modified while we iterate it.
13535             for (OnAttachStateChangeListener listener : listeners) {
13536                 listener.onViewAttachedToWindow(this);
13537             }
13538         }
13539 
13540         int vis = info.mWindowVisibility;
13541         if (vis != GONE) {
13542             onWindowVisibilityChanged(vis);
13543         }
13544         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13545             // If nobody has evaluated the drawable state yet, then do it now.
13546             refreshDrawableState();
13547         }
13548         needGlobalAttributesUpdate(false);
13549     }
13550 
13551     void dispatchDetachedFromWindow() {
13552         AttachInfo info = mAttachInfo;
13553         if (info != null) {
13554             int vis = info.mWindowVisibility;
13555             if (vis != GONE) {
13556                 onWindowVisibilityChanged(GONE);
13557             }
13558         }
13559 
13560         onDetachedFromWindow();
13561         onDetachedFromWindowInternal();
13562 
13563         ListenerInfo li = mListenerInfo;
13564         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13565                 li != null ? li.mOnAttachStateChangeListeners : null;
13566         if (listeners != null && listeners.size() > 0) {
13567             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13568             // perform the dispatching. The iterator is a safe guard against listeners that
13569             // could mutate the list by calling the various add/remove methods. This prevents
13570             // the array from being modified while we iterate it.
13571             for (OnAttachStateChangeListener listener : listeners) {
13572                 listener.onViewDetachedFromWindow(this);
13573             }
13574         }
13575 
13576         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13577             mAttachInfo.mScrollContainers.remove(this);
13578             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13579         }
13580 
13581         mAttachInfo = null;
13582         if (mOverlay != null) {
13583             mOverlay.getOverlayView().dispatchDetachedFromWindow();
13584         }
13585     }
13586 
13587     /**
13588      * Cancel any deferred high-level input events that were previously posted to the event queue.
13589      *
13590      * <p>Many views post high-level events such as click handlers to the event queue
13591      * to run deferred in order to preserve a desired user experience - clearing visible
13592      * pressed states before executing, etc. This method will abort any events of this nature
13593      * that are currently in flight.</p>
13594      *
13595      * <p>Custom views that generate their own high-level deferred input events should override
13596      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
13597      *
13598      * <p>This will also cancel pending input events for any child views.</p>
13599      *
13600      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
13601      * This will not impact newer events posted after this call that may occur as a result of
13602      * lower-level input events still waiting in the queue. If you are trying to prevent
13603      * double-submitted  events for the duration of some sort of asynchronous transaction
13604      * you should also take other steps to protect against unexpected double inputs e.g. calling
13605      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
13606      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
13607      */
13608     public final void cancelPendingInputEvents() {
13609         dispatchCancelPendingInputEvents();
13610     }
13611 
13612     /**
13613      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13614      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13615      */
13616     void dispatchCancelPendingInputEvents() {
13617         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13618         onCancelPendingInputEvents();
13619         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13620             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13621                     " did not call through to super.onCancelPendingInputEvents()");
13622         }
13623     }
13624 
13625     /**
13626      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13627      * a parent view.
13628      *
13629      * <p>This method is responsible for removing any pending high-level input events that were
13630      * posted to the event queue to run later. Custom view classes that post their own deferred
13631      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13632      * {@link android.os.Handler} should override this method, call
13633      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13634      * </p>
13635      */
13636     public void onCancelPendingInputEvents() {
13637         removePerformClickCallback();
13638         cancelLongPress();
13639         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13640     }
13641 
13642     /**
13643      * Store this view hierarchy's frozen state into the given container.
13644      *
13645      * @param container The SparseArray in which to save the view's state.
13646      *
13647      * @see #restoreHierarchyState(android.util.SparseArray)
13648      * @see #dispatchSaveInstanceState(android.util.SparseArray)
13649      * @see #onSaveInstanceState()
13650      */
13651     public void saveHierarchyState(SparseArray<Parcelable> container) {
13652         dispatchSaveInstanceState(container);
13653     }
13654 
13655     /**
13656      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13657      * this view and its children. May be overridden to modify how freezing happens to a
13658      * view's children; for example, some views may want to not store state for their children.
13659      *
13660      * @param container The SparseArray in which to save the view's state.
13661      *
13662      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13663      * @see #saveHierarchyState(android.util.SparseArray)
13664      * @see #onSaveInstanceState()
13665      */
13666     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13667         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13668             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13669             Parcelable state = onSaveInstanceState();
13670             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13671                 throw new IllegalStateException(
13672                         "Derived class did not call super.onSaveInstanceState()");
13673             }
13674             if (state != null) {
13675                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13676                 // + ": " + state);
13677                 container.put(mID, state);
13678             }
13679         }
13680     }
13681 
13682     /**
13683      * Hook allowing a view to generate a representation of its internal state
13684      * that can later be used to create a new instance with that same state.
13685      * This state should only contain information that is not persistent or can
13686      * not be reconstructed later. For example, you will never store your
13687      * current position on screen because that will be computed again when a
13688      * new instance of the view is placed in its view hierarchy.
13689      * <p>
13690      * Some examples of things you may store here: the current cursor position
13691      * in a text view (but usually not the text itself since that is stored in a
13692      * content provider or other persistent storage), the currently selected
13693      * item in a list view.
13694      *
13695      * @return Returns a Parcelable object containing the view's current dynamic
13696      *         state, or null if there is nothing interesting to save. The
13697      *         default implementation returns null.
13698      * @see #onRestoreInstanceState(android.os.Parcelable)
13699      * @see #saveHierarchyState(android.util.SparseArray)
13700      * @see #dispatchSaveInstanceState(android.util.SparseArray)
13701      * @see #setSaveEnabled(boolean)
13702      */
13703     protected Parcelable onSaveInstanceState() {
13704         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13705         return BaseSavedState.EMPTY_STATE;
13706     }
13707 
13708     /**
13709      * Restore this view hierarchy's frozen state from the given container.
13710      *
13711      * @param container The SparseArray which holds previously frozen states.
13712      *
13713      * @see #saveHierarchyState(android.util.SparseArray)
13714      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13715      * @see #onRestoreInstanceState(android.os.Parcelable)
13716      */
13717     public void restoreHierarchyState(SparseArray<Parcelable> container) {
13718         dispatchRestoreInstanceState(container);
13719     }
13720 
13721     /**
13722      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
13723      * state for this view and its children. May be overridden to modify how restoring
13724      * happens to a view's children; for example, some views may want to not store state
13725      * for their children.
13726      *
13727      * @param container The SparseArray which holds previously saved state.
13728      *
13729      * @see #dispatchSaveInstanceState(android.util.SparseArray)
13730      * @see #restoreHierarchyState(android.util.SparseArray)
13731      * @see #onRestoreInstanceState(android.os.Parcelable)
13732      */
13733     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
13734         if (mID != NO_ID) {
13735             Parcelable state = container.get(mID);
13736             if (state != null) {
13737                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
13738                 // + ": " + state);
13739                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13740                 onRestoreInstanceState(state);
13741                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13742                     throw new IllegalStateException(
13743                             "Derived class did not call super.onRestoreInstanceState()");
13744                 }
13745             }
13746         }
13747     }
13748 
13749     /**
13750      * Hook allowing a view to re-apply a representation of its internal state that had previously
13751      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
13752      * null state.
13753      *
13754      * @param state The frozen state that had previously been returned by
13755      *        {@link #onSaveInstanceState}.
13756      *
13757      * @see #onSaveInstanceState()
13758      * @see #restoreHierarchyState(android.util.SparseArray)
13759      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13760      */
13761     protected void onRestoreInstanceState(Parcelable state) {
13762         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13763         if (state != BaseSavedState.EMPTY_STATE && state != null) {
13764             throw new IllegalArgumentException("Wrong state class, expecting View State but "
13765                     + "received " + state.getClass().toString() + " instead. This usually happens "
13766                     + "when two views of different type have the same id in the same hierarchy. "
13767                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
13768                     + "other views do not use the same id.");
13769         }
13770     }
13771 
13772     /**
13773      * <p>Return the time at which the drawing of the view hierarchy started.</p>
13774      *
13775      * @return the drawing start time in milliseconds
13776      */
13777     public long getDrawingTime() {
13778         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
13779     }
13780 
13781     /**
13782      * <p>Enables or disables the duplication of the parent's state into this view. When
13783      * duplication is enabled, this view gets its drawable state from its parent rather
13784      * than from its own internal properties.</p>
13785      *
13786      * <p>Note: in the current implementation, setting this property to true after the
13787      * view was added to a ViewGroup might have no effect at all. This property should
13788      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
13789      *
13790      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
13791      * property is enabled, an exception will be thrown.</p>
13792      *
13793      * <p>Note: if the child view uses and updates additionnal states which are unknown to the
13794      * parent, these states should not be affected by this method.</p>
13795      *
13796      * @param enabled True to enable duplication of the parent's drawable state, false
13797      *                to disable it.
13798      *
13799      * @see #getDrawableState()
13800      * @see #isDuplicateParentStateEnabled()
13801      */
13802     public void setDuplicateParentStateEnabled(boolean enabled) {
13803         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
13804     }
13805 
13806     /**
13807      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
13808      *
13809      * @return True if this view's drawable state is duplicated from the parent,
13810      *         false otherwise
13811      *
13812      * @see #getDrawableState()
13813      * @see #setDuplicateParentStateEnabled(boolean)
13814      */
13815     public boolean isDuplicateParentStateEnabled() {
13816         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
13817     }
13818 
13819     /**
13820      * <p>Specifies the type of layer backing this view. The layer can be
13821      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13822      * {@link #LAYER_TYPE_HARDWARE}.</p>
13823      *
13824      * <p>A layer is associated with an optional {@link android.graphics.Paint}
13825      * instance that controls how the layer is composed on screen. The following
13826      * properties of the paint are taken into account when composing the layer:</p>
13827      * <ul>
13828      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13829      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13830      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13831      * </ul>
13832      *
13833      * <p>If this view has an alpha value set to < 1.0 by calling
13834      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
13835      * by this view's alpha value.</p>
13836      *
13837      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
13838      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
13839      * for more information on when and how to use layers.</p>
13840      *
13841      * @param layerType The type of layer to use with this view, must be one of
13842      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13843      *        {@link #LAYER_TYPE_HARDWARE}
13844      * @param paint The paint used to compose the layer. This argument is optional
13845      *        and can be null. It is ignored when the layer type is
13846      *        {@link #LAYER_TYPE_NONE}
13847      *
13848      * @see #getLayerType()
13849      * @see #LAYER_TYPE_NONE
13850      * @see #LAYER_TYPE_SOFTWARE
13851      * @see #LAYER_TYPE_HARDWARE
13852      * @see #setAlpha(float)
13853      *
13854      * @attr ref android.R.styleable#View_layerType
13855      */
13856     public void setLayerType(int layerType, Paint paint) {
13857         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
13858             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
13859                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
13860         }
13861 
13862         boolean typeChanged = mRenderNode.setLayerType(layerType);
13863 
13864         if (!typeChanged) {
13865             setLayerPaint(paint);
13866             return;
13867         }
13868 
13869         // Destroy any previous software drawing cache if needed
13870         if (mLayerType == LAYER_TYPE_SOFTWARE) {
13871             destroyDrawingCache();
13872         }
13873 
13874         mLayerType = layerType;
13875         final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
13876         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
13877         mRenderNode.setLayerPaint(mLayerPaint);
13878 
13879         // draw() behaves differently if we are on a layer, so we need to
13880         // invalidate() here
13881         invalidateParentCaches();
13882         invalidate(true);
13883     }
13884 
13885     /**
13886      * Updates the {@link Paint} object used with the current layer (used only if the current
13887      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
13888      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
13889      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
13890      * ensure that the view gets redrawn immediately.
13891      *
13892      * <p>A layer is associated with an optional {@link android.graphics.Paint}
13893      * instance that controls how the layer is composed on screen. The following
13894      * properties of the paint are taken into account when composing the layer:</p>
13895      * <ul>
13896      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13897      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13898      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13899      * </ul>
13900      *
13901      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
13902      * alpha value of the layer's paint is superceded by this view's alpha value.</p>
13903      *
13904      * @param paint The paint used to compose the layer. This argument is optional
13905      *        and can be null. It is ignored when the layer type is
13906      *        {@link #LAYER_TYPE_NONE}
13907      *
13908      * @see #setLayerType(int, android.graphics.Paint)
13909      */
13910     public void setLayerPaint(Paint paint) {
13911         int layerType = getLayerType();
13912         if (layerType != LAYER_TYPE_NONE) {
13913             mLayerPaint = paint == null ? new Paint() : paint;
13914             if (layerType == LAYER_TYPE_HARDWARE) {
13915                 if (mRenderNode.setLayerPaint(mLayerPaint)) {
13916                     invalidateViewProperty(false, false);
13917                 }
13918             } else {
13919                 invalidate();
13920             }
13921         }
13922     }
13923 
13924     /**
13925      * Indicates whether this view has a static layer. A view with layer type
13926      * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
13927      * dynamic.
13928      */
13929     boolean hasStaticLayer() {
13930         return true;
13931     }
13932 
13933     /**
13934      * Indicates what type of layer is currently associated with this view. By default
13935      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
13936      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
13937      * for more information on the different types of layers.
13938      *
13939      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13940      *         {@link #LAYER_TYPE_HARDWARE}
13941      *
13942      * @see #setLayerType(int, android.graphics.Paint)
13943      * @see #buildLayer()
13944      * @see #LAYER_TYPE_NONE
13945      * @see #LAYER_TYPE_SOFTWARE
13946      * @see #LAYER_TYPE_HARDWARE
13947      */
13948     public int getLayerType() {
13949         return mLayerType;
13950     }
13951 
13952     /**
13953      * Forces this view's layer to be created and this view to be rendered
13954      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
13955      * invoking this method will have no effect.
13956      *
13957      * This method can for instance be used to render a view into its layer before
13958      * starting an animation. If this view is complex, rendering into the layer
13959      * before starting the animation will avoid skipping frames.
13960      *
13961      * @throws IllegalStateException If this view is not attached to a window
13962      *
13963      * @see #setLayerType(int, android.graphics.Paint)
13964      */
13965     public void buildLayer() {
13966         if (mLayerType == LAYER_TYPE_NONE) return;
13967 
13968         final AttachInfo attachInfo = mAttachInfo;
13969         if (attachInfo == null) {
13970             throw new IllegalStateException("This view must be attached to a window first");
13971         }
13972 
13973         if (getWidth() == 0 || getHeight() == 0) {
13974             return;
13975         }
13976 
13977         switch (mLayerType) {
13978             case LAYER_TYPE_HARDWARE:
13979                 updateDisplayListIfDirty();
13980                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
13981                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
13982                 }
13983                 break;
13984             case LAYER_TYPE_SOFTWARE:
13985                 buildDrawingCache(true);
13986                 break;
13987         }
13988     }
13989 
13990     /**
13991      * If this View draws with a HardwareLayer, returns it.
13992      * Otherwise returns null
13993      *
13994      * TODO: Only TextureView uses this, can we eliminate it?
13995      */
13996     HardwareLayer getHardwareLayer() {
13997         return null;
13998     }
13999 
14000     /**
14001      * Destroys all hardware rendering resources. This method is invoked
14002      * when the system needs to reclaim resources. Upon execution of this
14003      * method, you should free any OpenGL resources created by the view.
14004      *
14005      * Note: you <strong>must</strong> call
14006      * <code>super.destroyHardwareResources()</code> when overriding
14007      * this method.
14008      *
14009      * @hide
14010      */
14011     protected void destroyHardwareResources() {
14012         // Although the Layer will be destroyed by RenderNode, we want to release
14013         // the staging display list, which is also a signal to RenderNode that it's
14014         // safe to free its copy of the display list as it knows that we will
14015         // push an updated DisplayList if we try to draw again
14016         resetDisplayList();
14017     }
14018 
14019     /**
14020      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
14021      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
14022      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
14023      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
14024      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
14025      * null.</p>
14026      *
14027      * <p>Enabling the drawing cache is similar to
14028      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
14029      * acceleration is turned off. When hardware acceleration is turned on, enabling the
14030      * drawing cache has no effect on rendering because the system uses a different mechanism
14031      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
14032      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
14033      * for information on how to enable software and hardware layers.</p>
14034      *
14035      * <p>This API can be used to manually generate
14036      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
14037      * {@link #getDrawingCache()}.</p>
14038      *
14039      * @param enabled true to enable the drawing cache, false otherwise
14040      *
14041      * @see #isDrawingCacheEnabled()
14042      * @see #getDrawingCache()
14043      * @see #buildDrawingCache()
14044      * @see #setLayerType(int, android.graphics.Paint)
14045      */
14046     public void setDrawingCacheEnabled(boolean enabled) {
14047         mCachingFailed = false;
14048         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
14049     }
14050 
14051     /**
14052      * <p>Indicates whether the drawing cache is enabled for this view.</p>
14053      *
14054      * @return true if the drawing cache is enabled
14055      *
14056      * @see #setDrawingCacheEnabled(boolean)
14057      * @see #getDrawingCache()
14058      */
14059     @ViewDebug.ExportedProperty(category = "drawing")
14060     public boolean isDrawingCacheEnabled() {
14061         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
14062     }
14063 
14064     /**
14065      * Debugging utility which recursively outputs the dirty state of a view and its
14066      * descendants.
14067      *
14068      * @hide
14069      */
14070     @SuppressWarnings({"UnusedDeclaration"})
14071     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
14072         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
14073                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
14074                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
14075                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
14076         if (clear) {
14077             mPrivateFlags &= clearMask;
14078         }
14079         if (this instanceof ViewGroup) {
14080             ViewGroup parent = (ViewGroup) this;
14081             final int count = parent.getChildCount();
14082             for (int i = 0; i < count; i++) {
14083                 final View child = parent.getChildAt(i);
14084                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
14085             }
14086         }
14087     }
14088 
14089     /**
14090      * This method is used by ViewGroup to cause its children to restore or recreate their
14091      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
14092      * to recreate its own display list, which would happen if it went through the normal
14093      * draw/dispatchDraw mechanisms.
14094      *
14095      * @hide
14096      */
14097     protected void dispatchGetDisplayList() {}
14098 
14099     /**
14100      * A view that is not attached or hardware accelerated cannot create a display list.
14101      * This method checks these conditions and returns the appropriate result.
14102      *
14103      * @return true if view has the ability to create a display list, false otherwise.
14104      *
14105      * @hide
14106      */
14107     public boolean canHaveDisplayList() {
14108         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
14109     }
14110 
14111     private void updateDisplayListIfDirty() {
14112         final RenderNode renderNode = mRenderNode;
14113         if (!canHaveDisplayList()) {
14114             // can't populate RenderNode, don't try
14115             return;
14116         }
14117 
14118         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
14119                 || !renderNode.isValid()
14120                 || (mRecreateDisplayList)) {
14121             // Don't need to recreate the display list, just need to tell our
14122             // children to restore/recreate theirs
14123             if (renderNode.isValid()
14124                     && !mRecreateDisplayList) {
14125                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14126                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14127                 dispatchGetDisplayList();
14128 
14129                 return; // no work needed
14130             }
14131 
14132             // If we got here, we're recreating it. Mark it as such to ensure that
14133             // we copy in child display lists into ours in drawChild()
14134             mRecreateDisplayList = true;
14135 
14136             int width = mRight - mLeft;
14137             int height = mBottom - mTop;
14138             int layerType = getLayerType();
14139 
14140             final HardwareCanvas canvas = renderNode.start(width, height);
14141             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
14142 
14143             try {
14144                 final HardwareLayer layer = getHardwareLayer();
14145                 if (layer != null && layer.isValid()) {
14146                     canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
14147                 } else if (layerType == LAYER_TYPE_SOFTWARE) {
14148                     buildDrawingCache(true);
14149                     Bitmap cache = getDrawingCache(true);
14150                     if (cache != null) {
14151                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
14152                     }
14153                 } else {
14154                     computeScroll();
14155 
14156                     canvas.translate(-mScrollX, -mScrollY);
14157                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14158                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14159 
14160                     // Fast path for layouts with no backgrounds
14161                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14162                         dispatchDraw(canvas);
14163                         if (mOverlay != null && !mOverlay.isEmpty()) {
14164                             mOverlay.getOverlayView().draw(canvas);
14165                         }
14166                     } else {
14167                         draw(canvas);
14168                     }
14169                 }
14170             } finally {
14171                 renderNode.end(canvas);
14172                 setDisplayListProperties(renderNode);
14173             }
14174         } else {
14175             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14176             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14177         }
14178     }
14179 
14180     /**
14181      * Returns a RenderNode with View draw content recorded, which can be
14182      * used to draw this view again without executing its draw method.
14183      *
14184      * @return A RenderNode ready to replay, or null if caching is not enabled.
14185      *
14186      * @hide
14187      */
14188     public RenderNode getDisplayList() {
14189         updateDisplayListIfDirty();
14190         return mRenderNode;
14191     }
14192 
14193     private void resetDisplayList() {
14194         if (mRenderNode.isValid()) {
14195             mRenderNode.destroyDisplayListData();
14196         }
14197 
14198         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14199             mBackgroundRenderNode.destroyDisplayListData();
14200         }
14201     }
14202 
14203     /**
14204      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14205      *
14206      * @return A non-scaled bitmap representing this view or null if cache is disabled.
14207      *
14208      * @see #getDrawingCache(boolean)
14209      */
14210     public Bitmap getDrawingCache() {
14211         return getDrawingCache(false);
14212     }
14213 
14214     /**
14215      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14216      * is null when caching is disabled. If caching is enabled and the cache is not ready,
14217      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14218      * draw from the cache when the cache is enabled. To benefit from the cache, you must
14219      * request the drawing cache by calling this method and draw it on screen if the
14220      * returned bitmap is not null.</p>
14221      *
14222      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14223      * this method will create a bitmap of the same size as this view. Because this bitmap
14224      * will be drawn scaled by the parent ViewGroup, the result on screen might show
14225      * scaling artifacts. To avoid such artifacts, you should call this method by setting
14226      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14227      * size than the view. This implies that your application must be able to handle this
14228      * size.</p>
14229      *
14230      * @param autoScale Indicates whether the generated bitmap should be scaled based on
14231      *        the current density of the screen when the application is in compatibility
14232      *        mode.
14233      *
14234      * @return A bitmap representing this view or null if cache is disabled.
14235      *
14236      * @see #setDrawingCacheEnabled(boolean)
14237      * @see #isDrawingCacheEnabled()
14238      * @see #buildDrawingCache(boolean)
14239      * @see #destroyDrawingCache()
14240      */
14241     public Bitmap getDrawingCache(boolean autoScale) {
14242         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14243             return null;
14244         }
14245         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14246             buildDrawingCache(autoScale);
14247         }
14248         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14249     }
14250 
14251     /**
14252      * <p>Frees the resources used by the drawing cache. If you call
14253      * {@link #buildDrawingCache()} manually without calling
14254      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14255      * should cleanup the cache with this method afterwards.</p>
14256      *
14257      * @see #setDrawingCacheEnabled(boolean)
14258      * @see #buildDrawingCache()
14259      * @see #getDrawingCache()
14260      */
14261     public void destroyDrawingCache() {
14262         if (mDrawingCache != null) {
14263             mDrawingCache.recycle();
14264             mDrawingCache = null;
14265         }
14266         if (mUnscaledDrawingCache != null) {
14267             mUnscaledDrawingCache.recycle();
14268             mUnscaledDrawingCache = null;
14269         }
14270     }
14271 
14272     /**
14273      * Setting a solid background color for the drawing cache's bitmaps will improve
14274      * performance and memory usage. Note, though that this should only be used if this
14275      * view will always be drawn on top of a solid color.
14276      *
14277      * @param color The background color to use for the drawing cache's bitmap
14278      *
14279      * @see #setDrawingCacheEnabled(boolean)
14280      * @see #buildDrawingCache()
14281      * @see #getDrawingCache()
14282      */
14283     public void setDrawingCacheBackgroundColor(int color) {
14284         if (color != mDrawingCacheBackgroundColor) {
14285             mDrawingCacheBackgroundColor = color;
14286             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14287         }
14288     }
14289 
14290     /**
14291      * @see #setDrawingCacheBackgroundColor(int)
14292      *
14293      * @return The background color to used for the drawing cache's bitmap
14294      */
14295     public int getDrawingCacheBackgroundColor() {
14296         return mDrawingCacheBackgroundColor;
14297     }
14298 
14299     /**
14300      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14301      *
14302      * @see #buildDrawingCache(boolean)
14303      */
14304     public void buildDrawingCache() {
14305         buildDrawingCache(false);
14306     }
14307 
14308     /**
14309      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14310      *
14311      * <p>If you call {@link #buildDrawingCache()} manually without calling
14312      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14313      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14314      *
14315      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14316      * this method will create a bitmap of the same size as this view. Because this bitmap
14317      * will be drawn scaled by the parent ViewGroup, the result on screen might show
14318      * scaling artifacts. To avoid such artifacts, you should call this method by setting
14319      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14320      * size than the view. This implies that your application must be able to handle this
14321      * size.</p>
14322      *
14323      * <p>You should avoid calling this method when hardware acceleration is enabled. If
14324      * you do not need the drawing cache bitmap, calling this method will increase memory
14325      * usage and cause the view to be rendered in software once, thus negatively impacting
14326      * performance.</p>
14327      *
14328      * @see #getDrawingCache()
14329      * @see #destroyDrawingCache()
14330      */
14331     public void buildDrawingCache(boolean autoScale) {
14332         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14333                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
14334             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
14335                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
14336                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
14337             }
14338             try {
14339                 buildDrawingCacheImpl(autoScale);
14340             } finally {
14341                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
14342             }
14343         }
14344     }
14345 
14346     /**
14347      * private, internal implementation of buildDrawingCache, used to enable tracing
14348      */
14349     private void buildDrawingCacheImpl(boolean autoScale) {
14350         mCachingFailed = false;
14351 
14352         int width = mRight - mLeft;
14353         int height = mBottom - mTop;
14354 
14355         final AttachInfo attachInfo = mAttachInfo;
14356         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14357 
14358         if (autoScale && scalingRequired) {
14359             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14360             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14361         }
14362 
14363         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14364         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14365         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14366 
14367         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14368         final long drawingCacheSize =
14369                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14370         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14371             if (width > 0 && height > 0) {
14372                 Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14373                         + projectedBitmapSize + " bytes, only "
14374                         + drawingCacheSize + " available");
14375             }
14376             destroyDrawingCache();
14377             mCachingFailed = true;
14378             return;
14379         }
14380 
14381         boolean clear = true;
14382         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14383 
14384         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14385             Bitmap.Config quality;
14386             if (!opaque) {
14387                 // Never pick ARGB_4444 because it looks awful
14388                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14389                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14390                     case DRAWING_CACHE_QUALITY_AUTO:
14391                     case DRAWING_CACHE_QUALITY_LOW:
14392                     case DRAWING_CACHE_QUALITY_HIGH:
14393                     default:
14394                         quality = Bitmap.Config.ARGB_8888;
14395                         break;
14396                 }
14397             } else {
14398                 // Optimization for translucent windows
14399                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14400                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14401             }
14402 
14403             // Try to cleanup memory
14404             if (bitmap != null) bitmap.recycle();
14405 
14406             try {
14407                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14408                         width, height, quality);
14409                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14410                 if (autoScale) {
14411                     mDrawingCache = bitmap;
14412                 } else {
14413                     mUnscaledDrawingCache = bitmap;
14414                 }
14415                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14416             } catch (OutOfMemoryError e) {
14417                 // If there is not enough memory to create the bitmap cache, just
14418                 // ignore the issue as bitmap caches are not required to draw the
14419                 // view hierarchy
14420                 if (autoScale) {
14421                     mDrawingCache = null;
14422                 } else {
14423                     mUnscaledDrawingCache = null;
14424                 }
14425                 mCachingFailed = true;
14426                 return;
14427             }
14428 
14429             clear = drawingCacheBackgroundColor != 0;
14430         }
14431 
14432         Canvas canvas;
14433         if (attachInfo != null) {
14434             canvas = attachInfo.mCanvas;
14435             if (canvas == null) {
14436                 canvas = new Canvas();
14437             }
14438             canvas.setBitmap(bitmap);
14439             // Temporarily clobber the cached Canvas in case one of our children
14440             // is also using a drawing cache. Without this, the children would
14441             // steal the canvas by attaching their own bitmap to it and bad, bad
14442             // thing would happen (invisible views, corrupted drawings, etc.)
14443             attachInfo.mCanvas = null;
14444         } else {
14445             // This case should hopefully never or seldom happen
14446             canvas = new Canvas(bitmap);
14447         }
14448 
14449         if (clear) {
14450             bitmap.eraseColor(drawingCacheBackgroundColor);
14451         }
14452 
14453         computeScroll();
14454         final int restoreCount = canvas.save();
14455 
14456         if (autoScale && scalingRequired) {
14457             final float scale = attachInfo.mApplicationScale;
14458             canvas.scale(scale, scale);
14459         }
14460 
14461         canvas.translate(-mScrollX, -mScrollY);
14462 
14463         mPrivateFlags |= PFLAG_DRAWN;
14464         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14465                 mLayerType != LAYER_TYPE_NONE) {
14466             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14467         }
14468 
14469         // Fast path for layouts with no backgrounds
14470         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14471             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14472             dispatchDraw(canvas);
14473             if (mOverlay != null && !mOverlay.isEmpty()) {
14474                 mOverlay.getOverlayView().draw(canvas);
14475             }
14476         } else {
14477             draw(canvas);
14478         }
14479 
14480         canvas.restoreToCount(restoreCount);
14481         canvas.setBitmap(null);
14482 
14483         if (attachInfo != null) {
14484             // Restore the cached Canvas for our siblings
14485             attachInfo.mCanvas = canvas;
14486         }
14487     }
14488 
14489     /**
14490      * Create a snapshot of the view into a bitmap.  We should probably make
14491      * some form of this public, but should think about the API.
14492      */
14493     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14494         int width = mRight - mLeft;
14495         int height = mBottom - mTop;
14496 
14497         final AttachInfo attachInfo = mAttachInfo;
14498         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14499         width = (int) ((width * scale) + 0.5f);
14500         height = (int) ((height * scale) + 0.5f);
14501 
14502         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14503                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
14504         if (bitmap == null) {
14505             throw new OutOfMemoryError();
14506         }
14507 
14508         Resources resources = getResources();
14509         if (resources != null) {
14510             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14511         }
14512 
14513         Canvas canvas;
14514         if (attachInfo != null) {
14515             canvas = attachInfo.mCanvas;
14516             if (canvas == null) {
14517                 canvas = new Canvas();
14518             }
14519             canvas.setBitmap(bitmap);
14520             // Temporarily clobber the cached Canvas in case one of our children
14521             // is also using a drawing cache. Without this, the children would
14522             // steal the canvas by attaching their own bitmap to it and bad, bad
14523             // things would happen (invisible views, corrupted drawings, etc.)
14524             attachInfo.mCanvas = null;
14525         } else {
14526             // This case should hopefully never or seldom happen
14527             canvas = new Canvas(bitmap);
14528         }
14529 
14530         if ((backgroundColor & 0xff000000) != 0) {
14531             bitmap.eraseColor(backgroundColor);
14532         }
14533 
14534         computeScroll();
14535         final int restoreCount = canvas.save();
14536         canvas.scale(scale, scale);
14537         canvas.translate(-mScrollX, -mScrollY);
14538 
14539         // Temporarily remove the dirty mask
14540         int flags = mPrivateFlags;
14541         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14542 
14543         // Fast path for layouts with no backgrounds
14544         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14545             dispatchDraw(canvas);
14546             if (mOverlay != null && !mOverlay.isEmpty()) {
14547                 mOverlay.getOverlayView().draw(canvas);
14548             }
14549         } else {
14550             draw(canvas);
14551         }
14552 
14553         mPrivateFlags = flags;
14554 
14555         canvas.restoreToCount(restoreCount);
14556         canvas.setBitmap(null);
14557 
14558         if (attachInfo != null) {
14559             // Restore the cached Canvas for our siblings
14560             attachInfo.mCanvas = canvas;
14561         }
14562 
14563         return bitmap;
14564     }
14565 
14566     /**
14567      * Indicates whether this View is currently in edit mode. A View is usually
14568      * in edit mode when displayed within a developer tool. For instance, if
14569      * this View is being drawn by a visual user interface builder, this method
14570      * should return true.
14571      *
14572      * Subclasses should check the return value of this method to provide
14573      * different behaviors if their normal behavior might interfere with the
14574      * host environment. For instance: the class spawns a thread in its
14575      * constructor, the drawing code relies on device-specific features, etc.
14576      *
14577      * This method is usually checked in the drawing code of custom widgets.
14578      *
14579      * @return True if this View is in edit mode, false otherwise.
14580      */
14581     public boolean isInEditMode() {
14582         return false;
14583     }
14584 
14585     /**
14586      * If the View draws content inside its padding and enables fading edges,
14587      * it needs to support padding offsets. Padding offsets are added to the
14588      * fading edges to extend the length of the fade so that it covers pixels
14589      * drawn inside the padding.
14590      *
14591      * Subclasses of this class should override this method if they need
14592      * to draw content inside the padding.
14593      *
14594      * @return True if padding offset must be applied, false otherwise.
14595      *
14596      * @see #getLeftPaddingOffset()
14597      * @see #getRightPaddingOffset()
14598      * @see #getTopPaddingOffset()
14599      * @see #getBottomPaddingOffset()
14600      *
14601      * @since CURRENT
14602      */
14603     protected boolean isPaddingOffsetRequired() {
14604         return false;
14605     }
14606 
14607     /**
14608      * Amount by which to extend the left fading region. Called only when
14609      * {@link #isPaddingOffsetRequired()} returns true.
14610      *
14611      * @return The left padding offset in pixels.
14612      *
14613      * @see #isPaddingOffsetRequired()
14614      *
14615      * @since CURRENT
14616      */
14617     protected int getLeftPaddingOffset() {
14618         return 0;
14619     }
14620 
14621     /**
14622      * Amount by which to extend the right fading region. Called only when
14623      * {@link #isPaddingOffsetRequired()} returns true.
14624      *
14625      * @return The right padding offset in pixels.
14626      *
14627      * @see #isPaddingOffsetRequired()
14628      *
14629      * @since CURRENT
14630      */
14631     protected int getRightPaddingOffset() {
14632         return 0;
14633     }
14634 
14635     /**
14636      * Amount by which to extend the top fading region. Called only when
14637      * {@link #isPaddingOffsetRequired()} returns true.
14638      *
14639      * @return The top padding offset in pixels.
14640      *
14641      * @see #isPaddingOffsetRequired()
14642      *
14643      * @since CURRENT
14644      */
14645     protected int getTopPaddingOffset() {
14646         return 0;
14647     }
14648 
14649     /**
14650      * Amount by which to extend the bottom fading region. Called only when
14651      * {@link #isPaddingOffsetRequired()} returns true.
14652      *
14653      * @return The bottom padding offset in pixels.
14654      *
14655      * @see #isPaddingOffsetRequired()
14656      *
14657      * @since CURRENT
14658      */
14659     protected int getBottomPaddingOffset() {
14660         return 0;
14661     }
14662 
14663     /**
14664      * @hide
14665      * @param offsetRequired
14666      */
14667     protected int getFadeTop(boolean offsetRequired) {
14668         int top = mPaddingTop;
14669         if (offsetRequired) top += getTopPaddingOffset();
14670         return top;
14671     }
14672 
14673     /**
14674      * @hide
14675      * @param offsetRequired
14676      */
14677     protected int getFadeHeight(boolean offsetRequired) {
14678         int padding = mPaddingTop;
14679         if (offsetRequired) padding += getTopPaddingOffset();
14680         return mBottom - mTop - mPaddingBottom - padding;
14681     }
14682 
14683     /**
14684      * <p>Indicates whether this view is attached to a hardware accelerated
14685      * window or not.</p>
14686      *
14687      * <p>Even if this method returns true, it does not mean that every call
14688      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14689      * accelerated {@link android.graphics.Canvas}. For instance, if this view
14690      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14691      * window is hardware accelerated,
14692      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14693      * return false, and this method will return true.</p>
14694      *
14695      * @return True if the view is attached to a window and the window is
14696      *         hardware accelerated; false in any other case.
14697      */
14698     @ViewDebug.ExportedProperty(category = "drawing")
14699     public boolean isHardwareAccelerated() {
14700         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14701     }
14702 
14703     /**
14704      * Sets a rectangular area on this view to which the view will be clipped
14705      * when it is drawn. Setting the value to null will remove the clip bounds
14706      * and the view will draw normally, using its full bounds.
14707      *
14708      * @param clipBounds The rectangular area, in the local coordinates of
14709      * this view, to which future drawing operations will be clipped.
14710      */
14711     public void setClipBounds(Rect clipBounds) {
14712         if (clipBounds == mClipBounds
14713                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
14714             return;
14715         }
14716         if (clipBounds != null) {
14717             if (mClipBounds == null) {
14718                 mClipBounds = new Rect(clipBounds);
14719             } else {
14720                 mClipBounds.set(clipBounds);
14721             }
14722         } else {
14723             mClipBounds = null;
14724         }
14725         mRenderNode.setClipBounds(mClipBounds);
14726         invalidateViewProperty(false, false);
14727     }
14728 
14729     /**
14730      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
14731      *
14732      * @return A copy of the current clip bounds if clip bounds are set,
14733      * otherwise null.
14734      */
14735     public Rect getClipBounds() {
14736         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
14737     }
14738 
14739     /**
14740      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
14741      * case of an active Animation being run on the view.
14742      */
14743     private boolean drawAnimation(ViewGroup parent, long drawingTime,
14744             Animation a, boolean scalingRequired) {
14745         Transformation invalidationTransform;
14746         final int flags = parent.mGroupFlags;
14747         final boolean initialized = a.isInitialized();
14748         if (!initialized) {
14749             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
14750             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
14751             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
14752             onAnimationStart();
14753         }
14754 
14755         final Transformation t = parent.getChildTransformation();
14756         boolean more = a.getTransformation(drawingTime, t, 1f);
14757         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
14758             if (parent.mInvalidationTransformation == null) {
14759                 parent.mInvalidationTransformation = new Transformation();
14760             }
14761             invalidationTransform = parent.mInvalidationTransformation;
14762             a.getTransformation(drawingTime, invalidationTransform, 1f);
14763         } else {
14764             invalidationTransform = t;
14765         }
14766 
14767         if (more) {
14768             if (!a.willChangeBounds()) {
14769                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
14770                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
14771                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
14772                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
14773                     // The child need to draw an animation, potentially offscreen, so
14774                     // make sure we do not cancel invalidate requests
14775                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14776                     parent.invalidate(mLeft, mTop, mRight, mBottom);
14777                 }
14778             } else {
14779                 if (parent.mInvalidateRegion == null) {
14780                     parent.mInvalidateRegion = new RectF();
14781                 }
14782                 final RectF region = parent.mInvalidateRegion;
14783                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
14784                         invalidationTransform);
14785 
14786                 // The child need to draw an animation, potentially offscreen, so
14787                 // make sure we do not cancel invalidate requests
14788                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14789 
14790                 final int left = mLeft + (int) region.left;
14791                 final int top = mTop + (int) region.top;
14792                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
14793                         top + (int) (region.height() + .5f));
14794             }
14795         }
14796         return more;
14797     }
14798 
14799     /**
14800      * This method is called by getDisplayList() when a display list is recorded for a View.
14801      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
14802      */
14803     void setDisplayListProperties(RenderNode renderNode) {
14804         if (renderNode != null) {
14805             renderNode.setHasOverlappingRendering(hasOverlappingRendering());
14806             if (mParent instanceof ViewGroup) {
14807                 renderNode.setClipToBounds(
14808                         (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
14809             }
14810             float alpha = 1;
14811             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
14812                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14813                 ViewGroup parentVG = (ViewGroup) mParent;
14814                 final Transformation t = parentVG.getChildTransformation();
14815                 if (parentVG.getChildStaticTransformation(this, t)) {
14816                     final int transformType = t.getTransformationType();
14817                     if (transformType != Transformation.TYPE_IDENTITY) {
14818                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
14819                             alpha = t.getAlpha();
14820                         }
14821                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
14822                             renderNode.setStaticMatrix(t.getMatrix());
14823                         }
14824                     }
14825                 }
14826             }
14827             if (mTransformationInfo != null) {
14828                 alpha *= getFinalAlpha();
14829                 if (alpha < 1) {
14830                     final int multipliedAlpha = (int) (255 * alpha);
14831                     if (onSetAlpha(multipliedAlpha)) {
14832                         alpha = 1;
14833                     }
14834                 }
14835                 renderNode.setAlpha(alpha);
14836             } else if (alpha < 1) {
14837                 renderNode.setAlpha(alpha);
14838             }
14839         }
14840     }
14841 
14842     /**
14843      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
14844      * This draw() method is an implementation detail and is not intended to be overridden or
14845      * to be called from anywhere else other than ViewGroup.drawChild().
14846      */
14847     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
14848         boolean usingRenderNodeProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14849         boolean more = false;
14850         final boolean childHasIdentityMatrix = hasIdentityMatrix();
14851         final int flags = parent.mGroupFlags;
14852 
14853         if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
14854             parent.getChildTransformation().clear();
14855             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14856         }
14857 
14858         Transformation transformToApply = null;
14859         boolean concatMatrix = false;
14860 
14861         boolean scalingRequired = false;
14862         boolean caching;
14863         int layerType = getLayerType();
14864 
14865         final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
14866         if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
14867                 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
14868             caching = true;
14869             // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
14870             if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
14871         } else {
14872             caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
14873         }
14874 
14875         final Animation a = getAnimation();
14876         if (a != null) {
14877             more = drawAnimation(parent, drawingTime, a, scalingRequired);
14878             concatMatrix = a.willChangeTransformationMatrix();
14879             if (concatMatrix) {
14880                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14881             }
14882             transformToApply = parent.getChildTransformation();
14883         } else {
14884             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
14885                 // No longer animating: clear out old animation matrix
14886                 mRenderNode.setAnimationMatrix(null);
14887                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14888             }
14889             if (!usingRenderNodeProperties &&
14890                     (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14891                 final Transformation t = parent.getChildTransformation();
14892                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
14893                 if (hasTransform) {
14894                     final int transformType = t.getTransformationType();
14895                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
14896                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
14897                 }
14898             }
14899         }
14900 
14901         concatMatrix |= !childHasIdentityMatrix;
14902 
14903         // Sets the flag as early as possible to allow draw() implementations
14904         // to call invalidate() successfully when doing animations
14905         mPrivateFlags |= PFLAG_DRAWN;
14906 
14907         if (!concatMatrix &&
14908                 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
14909                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
14910                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
14911                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
14912             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
14913             return more;
14914         }
14915         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
14916 
14917         if (hardwareAccelerated) {
14918             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
14919             // retain the flag's value temporarily in the mRecreateDisplayList flag
14920             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
14921             mPrivateFlags &= ~PFLAG_INVALIDATED;
14922         }
14923 
14924         RenderNode renderNode = null;
14925         Bitmap cache = null;
14926         boolean hasDisplayList = false;
14927         if (caching) {
14928             if (!hardwareAccelerated) {
14929                 if (layerType != LAYER_TYPE_NONE) {
14930                     layerType = LAYER_TYPE_SOFTWARE;
14931                     buildDrawingCache(true);
14932                 }
14933                 cache = getDrawingCache(true);
14934             } else {
14935                 switch (layerType) {
14936                     case LAYER_TYPE_SOFTWARE:
14937                         if (usingRenderNodeProperties) {
14938                             hasDisplayList = canHaveDisplayList();
14939                         } else {
14940                             buildDrawingCache(true);
14941                             cache = getDrawingCache(true);
14942                         }
14943                         break;
14944                     case LAYER_TYPE_HARDWARE:
14945                         if (usingRenderNodeProperties) {
14946                             hasDisplayList = canHaveDisplayList();
14947                         }
14948                         break;
14949                     case LAYER_TYPE_NONE:
14950                         // Delay getting the display list until animation-driven alpha values are
14951                         // set up and possibly passed on to the view
14952                         hasDisplayList = canHaveDisplayList();
14953                         break;
14954                 }
14955             }
14956         }
14957         usingRenderNodeProperties &= hasDisplayList;
14958         if (usingRenderNodeProperties) {
14959             renderNode = getDisplayList();
14960             if (!renderNode.isValid()) {
14961                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
14962                 // to getDisplayList(), the display list will be marked invalid and we should not
14963                 // try to use it again.
14964                 renderNode = null;
14965                 hasDisplayList = false;
14966                 usingRenderNodeProperties = false;
14967             }
14968         }
14969 
14970         int sx = 0;
14971         int sy = 0;
14972         if (!hasDisplayList) {
14973             computeScroll();
14974             sx = mScrollX;
14975             sy = mScrollY;
14976         }
14977 
14978         final boolean hasNoCache = cache == null || hasDisplayList;
14979         final boolean offsetForScroll = cache == null && !hasDisplayList &&
14980                 layerType != LAYER_TYPE_HARDWARE;
14981 
14982         int restoreTo = -1;
14983         if (!usingRenderNodeProperties || transformToApply != null) {
14984             restoreTo = canvas.save();
14985         }
14986         if (offsetForScroll) {
14987             canvas.translate(mLeft - sx, mTop - sy);
14988         } else {
14989             if (!usingRenderNodeProperties) {
14990                 canvas.translate(mLeft, mTop);
14991             }
14992             if (scalingRequired) {
14993                 if (usingRenderNodeProperties) {
14994                     // TODO: Might not need this if we put everything inside the DL
14995                     restoreTo = canvas.save();
14996                 }
14997                 // mAttachInfo cannot be null, otherwise scalingRequired == false
14998                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
14999                 canvas.scale(scale, scale);
15000             }
15001         }
15002 
15003         float alpha = usingRenderNodeProperties ? 1 : (getAlpha() * getTransitionAlpha());
15004         if (transformToApply != null || alpha < 1 ||  !hasIdentityMatrix() ||
15005                 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15006             if (transformToApply != null || !childHasIdentityMatrix) {
15007                 int transX = 0;
15008                 int transY = 0;
15009 
15010                 if (offsetForScroll) {
15011                     transX = -sx;
15012                     transY = -sy;
15013                 }
15014 
15015                 if (transformToApply != null) {
15016                     if (concatMatrix) {
15017                         if (usingRenderNodeProperties) {
15018                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
15019                         } else {
15020                             // Undo the scroll translation, apply the transformation matrix,
15021                             // then redo the scroll translate to get the correct result.
15022                             canvas.translate(-transX, -transY);
15023                             canvas.concat(transformToApply.getMatrix());
15024                             canvas.translate(transX, transY);
15025                         }
15026                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15027                     }
15028 
15029                     float transformAlpha = transformToApply.getAlpha();
15030                     if (transformAlpha < 1) {
15031                         alpha *= transformAlpha;
15032                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15033                     }
15034                 }
15035 
15036                 if (!childHasIdentityMatrix && !usingRenderNodeProperties) {
15037                     canvas.translate(-transX, -transY);
15038                     canvas.concat(getMatrix());
15039                     canvas.translate(transX, transY);
15040                 }
15041             }
15042 
15043             // Deal with alpha if it is or used to be <1
15044             if (alpha < 1 ||
15045                     (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15046                 if (alpha < 1) {
15047                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15048                 } else {
15049                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15050                 }
15051                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15052                 if (hasNoCache) {
15053                     final int multipliedAlpha = (int) (255 * alpha);
15054                     if (!onSetAlpha(multipliedAlpha)) {
15055                         int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15056                         if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
15057                                 layerType != LAYER_TYPE_NONE) {
15058                             layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
15059                         }
15060                         if (usingRenderNodeProperties) {
15061                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
15062                         } else  if (layerType == LAYER_TYPE_NONE) {
15063                             final int scrollX = hasDisplayList ? 0 : sx;
15064                             final int scrollY = hasDisplayList ? 0 : sy;
15065                             canvas.saveLayerAlpha(scrollX, scrollY,
15066                                     scrollX + (mRight - mLeft), scrollY + (mBottom - mTop),
15067                                     multipliedAlpha, layerFlags);
15068                         }
15069                     } else {
15070                         // Alpha is handled by the child directly, clobber the layer's alpha
15071                         mPrivateFlags |= PFLAG_ALPHA_SET;
15072                     }
15073                 }
15074             }
15075         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15076             onSetAlpha(255);
15077             mPrivateFlags &= ~PFLAG_ALPHA_SET;
15078         }
15079 
15080         if (!usingRenderNodeProperties) {
15081             // apply clips directly, since RenderNode won't do it for this draw
15082             if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN
15083                     && cache == null) {
15084                 if (offsetForScroll) {
15085                     canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
15086                 } else {
15087                     if (!scalingRequired || cache == null) {
15088                         canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
15089                     } else {
15090                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
15091                     }
15092                 }
15093             }
15094 
15095             if (mClipBounds != null) {
15096                 // clip bounds ignore scroll
15097                 canvas.clipRect(mClipBounds);
15098             }
15099         }
15100 
15101 
15102 
15103         if (!usingRenderNodeProperties && hasDisplayList) {
15104             renderNode = getDisplayList();
15105             if (!renderNode.isValid()) {
15106                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
15107                 // to getDisplayList(), the display list will be marked invalid and we should not
15108                 // try to use it again.
15109                 renderNode = null;
15110                 hasDisplayList = false;
15111             }
15112         }
15113 
15114         if (hasNoCache) {
15115             boolean layerRendered = false;
15116             if (layerType == LAYER_TYPE_HARDWARE && !usingRenderNodeProperties) {
15117                 final HardwareLayer layer = getHardwareLayer();
15118                 if (layer != null && layer.isValid()) {
15119                     int restoreAlpha = mLayerPaint.getAlpha();
15120                     mLayerPaint.setAlpha((int) (alpha * 255));
15121                     ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
15122                     mLayerPaint.setAlpha(restoreAlpha);
15123                     layerRendered = true;
15124                 } else {
15125                     final int scrollX = hasDisplayList ? 0 : sx;
15126                     final int scrollY = hasDisplayList ? 0 : sy;
15127                     canvas.saveLayer(scrollX, scrollY,
15128                             scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
15129                             Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
15130                 }
15131             }
15132 
15133             if (!layerRendered) {
15134                 if (!hasDisplayList) {
15135                     // Fast path for layouts with no backgrounds
15136                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15137                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15138                         dispatchDraw(canvas);
15139                     } else {
15140                         draw(canvas);
15141                     }
15142                 } else {
15143                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15144                     ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
15145                 }
15146             }
15147         } else if (cache != null) {
15148             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15149             Paint cachePaint;
15150             int restoreAlpha = 0;
15151 
15152             if (layerType == LAYER_TYPE_NONE) {
15153                 cachePaint = parent.mCachePaint;
15154                 if (cachePaint == null) {
15155                     cachePaint = new Paint();
15156                     cachePaint.setDither(false);
15157                     parent.mCachePaint = cachePaint;
15158                 }
15159             } else {
15160                 cachePaint = mLayerPaint;
15161                 restoreAlpha = mLayerPaint.getAlpha();
15162             }
15163             cachePaint.setAlpha((int) (alpha * 255));
15164             canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
15165             cachePaint.setAlpha(restoreAlpha);
15166         }
15167 
15168         if (restoreTo >= 0) {
15169             canvas.restoreToCount(restoreTo);
15170         }
15171 
15172         if (a != null && !more) {
15173             if (!hardwareAccelerated && !a.getFillAfter()) {
15174                 onSetAlpha(255);
15175             }
15176             parent.finishAnimatingView(this, a);
15177         }
15178 
15179         if (more && hardwareAccelerated) {
15180             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15181                 // alpha animations should cause the child to recreate its display list
15182                 invalidate(true);
15183             }
15184         }
15185 
15186         mRecreateDisplayList = false;
15187 
15188         return more;
15189     }
15190 
15191     /**
15192      * Manually render this view (and all of its children) to the given Canvas.
15193      * The view must have already done a full layout before this function is
15194      * called.  When implementing a view, implement
15195      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15196      * If you do need to override this method, call the superclass version.
15197      *
15198      * @param canvas The Canvas to which the View is rendered.
15199      */
15200     public void draw(Canvas canvas) {
15201         final int privateFlags = mPrivateFlags;
15202         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15203                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15204         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15205 
15206         /*
15207          * Draw traversal performs several drawing steps which must be executed
15208          * in the appropriate order:
15209          *
15210          *      1. Draw the background
15211          *      2. If necessary, save the canvas' layers to prepare for fading
15212          *      3. Draw view's content
15213          *      4. Draw children
15214          *      5. If necessary, draw the fading edges and restore layers
15215          *      6. Draw decorations (scrollbars for instance)
15216          */
15217 
15218         // Step 1, draw the background, if needed
15219         int saveCount;
15220 
15221         if (!dirtyOpaque) {
15222             drawBackground(canvas);
15223         }
15224 
15225         // skip step 2 & 5 if possible (common case)
15226         final int viewFlags = mViewFlags;
15227         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15228         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15229         if (!verticalEdges && !horizontalEdges) {
15230             // Step 3, draw the content
15231             if (!dirtyOpaque) onDraw(canvas);
15232 
15233             // Step 4, draw the children
15234             dispatchDraw(canvas);
15235 
15236             // Step 6, draw decorations (scrollbars)
15237             onDrawScrollBars(canvas);
15238 
15239             if (mOverlay != null && !mOverlay.isEmpty()) {
15240                 mOverlay.getOverlayView().dispatchDraw(canvas);
15241             }
15242 
15243             // we're done...
15244             return;
15245         }
15246 
15247         /*
15248          * Here we do the full fledged routine...
15249          * (this is an uncommon case where speed matters less,
15250          * this is why we repeat some of the tests that have been
15251          * done above)
15252          */
15253 
15254         boolean drawTop = false;
15255         boolean drawBottom = false;
15256         boolean drawLeft = false;
15257         boolean drawRight = false;
15258 
15259         float topFadeStrength = 0.0f;
15260         float bottomFadeStrength = 0.0f;
15261         float leftFadeStrength = 0.0f;
15262         float rightFadeStrength = 0.0f;
15263 
15264         // Step 2, save the canvas' layers
15265         int paddingLeft = mPaddingLeft;
15266 
15267         final boolean offsetRequired = isPaddingOffsetRequired();
15268         if (offsetRequired) {
15269             paddingLeft += getLeftPaddingOffset();
15270         }
15271 
15272         int left = mScrollX + paddingLeft;
15273         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15274         int top = mScrollY + getFadeTop(offsetRequired);
15275         int bottom = top + getFadeHeight(offsetRequired);
15276 
15277         if (offsetRequired) {
15278             right += getRightPaddingOffset();
15279             bottom += getBottomPaddingOffset();
15280         }
15281 
15282         final ScrollabilityCache scrollabilityCache = mScrollCache;
15283         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15284         int length = (int) fadeHeight;
15285 
15286         // clip the fade length if top and bottom fades overlap
15287         // overlapping fades produce odd-looking artifacts
15288         if (verticalEdges && (top + length > bottom - length)) {
15289             length = (bottom - top) / 2;
15290         }
15291 
15292         // also clip horizontal fades if necessary
15293         if (horizontalEdges && (left + length > right - length)) {
15294             length = (right - left) / 2;
15295         }
15296 
15297         if (verticalEdges) {
15298             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15299             drawTop = topFadeStrength * fadeHeight > 1.0f;
15300             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15301             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15302         }
15303 
15304         if (horizontalEdges) {
15305             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15306             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15307             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15308             drawRight = rightFadeStrength * fadeHeight > 1.0f;
15309         }
15310 
15311         saveCount = canvas.getSaveCount();
15312 
15313         int solidColor = getSolidColor();
15314         if (solidColor == 0) {
15315             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15316 
15317             if (drawTop) {
15318                 canvas.saveLayer(left, top, right, top + length, null, flags);
15319             }
15320 
15321             if (drawBottom) {
15322                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15323             }
15324 
15325             if (drawLeft) {
15326                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
15327             }
15328 
15329             if (drawRight) {
15330                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
15331             }
15332         } else {
15333             scrollabilityCache.setFadeColor(solidColor);
15334         }
15335 
15336         // Step 3, draw the content
15337         if (!dirtyOpaque) onDraw(canvas);
15338 
15339         // Step 4, draw the children
15340         dispatchDraw(canvas);
15341 
15342         // Step 5, draw the fade effect and restore layers
15343         final Paint p = scrollabilityCache.paint;
15344         final Matrix matrix = scrollabilityCache.matrix;
15345         final Shader fade = scrollabilityCache.shader;
15346 
15347         if (drawTop) {
15348             matrix.setScale(1, fadeHeight * topFadeStrength);
15349             matrix.postTranslate(left, top);
15350             fade.setLocalMatrix(matrix);
15351             p.setShader(fade);
15352             canvas.drawRect(left, top, right, top + length, p);
15353         }
15354 
15355         if (drawBottom) {
15356             matrix.setScale(1, fadeHeight * bottomFadeStrength);
15357             matrix.postRotate(180);
15358             matrix.postTranslate(left, bottom);
15359             fade.setLocalMatrix(matrix);
15360             p.setShader(fade);
15361             canvas.drawRect(left, bottom - length, right, bottom, p);
15362         }
15363 
15364         if (drawLeft) {
15365             matrix.setScale(1, fadeHeight * leftFadeStrength);
15366             matrix.postRotate(-90);
15367             matrix.postTranslate(left, top);
15368             fade.setLocalMatrix(matrix);
15369             p.setShader(fade);
15370             canvas.drawRect(left, top, left + length, bottom, p);
15371         }
15372 
15373         if (drawRight) {
15374             matrix.setScale(1, fadeHeight * rightFadeStrength);
15375             matrix.postRotate(90);
15376             matrix.postTranslate(right, top);
15377             fade.setLocalMatrix(matrix);
15378             p.setShader(fade);
15379             canvas.drawRect(right - length, top, right, bottom, p);
15380         }
15381 
15382         canvas.restoreToCount(saveCount);
15383 
15384         // Step 6, draw decorations (scrollbars)
15385         onDrawScrollBars(canvas);
15386 
15387         if (mOverlay != null && !mOverlay.isEmpty()) {
15388             mOverlay.getOverlayView().dispatchDraw(canvas);
15389         }
15390     }
15391 
15392     /**
15393      * Draws the background onto the specified canvas.
15394      *
15395      * @param canvas Canvas on which to draw the background
15396      */
15397     private void drawBackground(Canvas canvas) {
15398         final Drawable background = mBackground;
15399         if (background == null) {
15400             return;
15401         }
15402 
15403         if (mBackgroundSizeChanged) {
15404             background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
15405             mBackgroundSizeChanged = false;
15406             rebuildOutline();
15407         }
15408 
15409         // Attempt to use a display list if requested.
15410         if (canvas.isHardwareAccelerated() && mAttachInfo != null
15411                 && mAttachInfo.mHardwareRenderer != null) {
15412             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15413 
15414             final RenderNode renderNode = mBackgroundRenderNode;
15415             if (renderNode != null && renderNode.isValid()) {
15416                 setBackgroundRenderNodeProperties(renderNode);
15417                 ((HardwareCanvas) canvas).drawRenderNode(renderNode);
15418                 return;
15419             }
15420         }
15421 
15422         final int scrollX = mScrollX;
15423         final int scrollY = mScrollY;
15424         if ((scrollX | scrollY) == 0) {
15425             background.draw(canvas);
15426         } else {
15427             canvas.translate(scrollX, scrollY);
15428             background.draw(canvas);
15429             canvas.translate(-scrollX, -scrollY);
15430         }
15431     }
15432 
15433     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
15434         renderNode.setTranslationX(mScrollX);
15435         renderNode.setTranslationY(mScrollY);
15436     }
15437 
15438     /**
15439      * Creates a new display list or updates the existing display list for the
15440      * specified Drawable.
15441      *
15442      * @param drawable Drawable for which to create a display list
15443      * @param renderNode Existing RenderNode, or {@code null}
15444      * @return A valid display list for the specified drawable
15445      */
15446     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15447         if (renderNode == null) {
15448             renderNode = RenderNode.create(drawable.getClass().getName(), this);
15449         }
15450 
15451         final Rect bounds = drawable.getBounds();
15452         final int width = bounds.width();
15453         final int height = bounds.height();
15454         final HardwareCanvas canvas = renderNode.start(width, height);
15455 
15456         // Reverse left/top translation done by drawable canvas, which will
15457         // instead be applied by rendernode's LTRB bounds below. This way, the
15458         // drawable's bounds match with its rendernode bounds and its content
15459         // will lie within those bounds in the rendernode tree.
15460         canvas.translate(-bounds.left, -bounds.top);
15461 
15462         try {
15463             drawable.draw(canvas);
15464         } finally {
15465             renderNode.end(canvas);
15466         }
15467 
15468         // Set up drawable properties that are view-independent.
15469         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15470         renderNode.setProjectBackwards(drawable.isProjected());
15471         renderNode.setProjectionReceiver(true);
15472         renderNode.setClipToBounds(false);
15473         return renderNode;
15474     }
15475 
15476     /**
15477      * Returns the overlay for this view, creating it if it does not yet exist.
15478      * Adding drawables to the overlay will cause them to be displayed whenever
15479      * the view itself is redrawn. Objects in the overlay should be actively
15480      * managed: remove them when they should not be displayed anymore. The
15481      * overlay will always have the same size as its host view.
15482      *
15483      * <p>Note: Overlays do not currently work correctly with {@link
15484      * SurfaceView} or {@link TextureView}; contents in overlays for these
15485      * types of views may not display correctly.</p>
15486      *
15487      * @return The ViewOverlay object for this view.
15488      * @see ViewOverlay
15489      */
15490     public ViewOverlay getOverlay() {
15491         if (mOverlay == null) {
15492             mOverlay = new ViewOverlay(mContext, this);
15493         }
15494         return mOverlay;
15495     }
15496 
15497     /**
15498      * Override this if your view is known to always be drawn on top of a solid color background,
15499      * and needs to draw fading edges. Returning a non-zero color enables the view system to
15500      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15501      * should be set to 0xFF.
15502      *
15503      * @see #setVerticalFadingEdgeEnabled(boolean)
15504      * @see #setHorizontalFadingEdgeEnabled(boolean)
15505      *
15506      * @return The known solid color background for this view, or 0 if the color may vary
15507      */
15508     @ViewDebug.ExportedProperty(category = "drawing")
15509     public int getSolidColor() {
15510         return 0;
15511     }
15512 
15513     /**
15514      * Build a human readable string representation of the specified view flags.
15515      *
15516      * @param flags the view flags to convert to a string
15517      * @return a String representing the supplied flags
15518      */
15519     private static String printFlags(int flags) {
15520         String output = "";
15521         int numFlags = 0;
15522         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15523             output += "TAKES_FOCUS";
15524             numFlags++;
15525         }
15526 
15527         switch (flags & VISIBILITY_MASK) {
15528         case INVISIBLE:
15529             if (numFlags > 0) {
15530                 output += " ";
15531             }
15532             output += "INVISIBLE";
15533             // USELESS HERE numFlags++;
15534             break;
15535         case GONE:
15536             if (numFlags > 0) {
15537                 output += " ";
15538             }
15539             output += "GONE";
15540             // USELESS HERE numFlags++;
15541             break;
15542         default:
15543             break;
15544         }
15545         return output;
15546     }
15547 
15548     /**
15549      * Build a human readable string representation of the specified private
15550      * view flags.
15551      *
15552      * @param privateFlags the private view flags to convert to a string
15553      * @return a String representing the supplied flags
15554      */
15555     private static String printPrivateFlags(int privateFlags) {
15556         String output = "";
15557         int numFlags = 0;
15558 
15559         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15560             output += "WANTS_FOCUS";
15561             numFlags++;
15562         }
15563 
15564         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15565             if (numFlags > 0) {
15566                 output += " ";
15567             }
15568             output += "FOCUSED";
15569             numFlags++;
15570         }
15571 
15572         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15573             if (numFlags > 0) {
15574                 output += " ";
15575             }
15576             output += "SELECTED";
15577             numFlags++;
15578         }
15579 
15580         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15581             if (numFlags > 0) {
15582                 output += " ";
15583             }
15584             output += "IS_ROOT_NAMESPACE";
15585             numFlags++;
15586         }
15587 
15588         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15589             if (numFlags > 0) {
15590                 output += " ";
15591             }
15592             output += "HAS_BOUNDS";
15593             numFlags++;
15594         }
15595 
15596         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15597             if (numFlags > 0) {
15598                 output += " ";
15599             }
15600             output += "DRAWN";
15601             // USELESS HERE numFlags++;
15602         }
15603         return output;
15604     }
15605 
15606     /**
15607      * <p>Indicates whether or not this view's layout will be requested during
15608      * the next hierarchy layout pass.</p>
15609      *
15610      * @return true if the layout will be forced during next layout pass
15611      */
15612     public boolean isLayoutRequested() {
15613         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15614     }
15615 
15616     /**
15617      * Return true if o is a ViewGroup that is laying out using optical bounds.
15618      * @hide
15619      */
15620     public static boolean isLayoutModeOptical(Object o) {
15621         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15622     }
15623 
15624     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15625         Insets parentInsets = mParent instanceof View ?
15626                 ((View) mParent).getOpticalInsets() : Insets.NONE;
15627         Insets childInsets = getOpticalInsets();
15628         return setFrame(
15629                 left   + parentInsets.left - childInsets.left,
15630                 top    + parentInsets.top  - childInsets.top,
15631                 right  + parentInsets.left + childInsets.right,
15632                 bottom + parentInsets.top  + childInsets.bottom);
15633     }
15634 
15635     /**
15636      * Assign a size and position to a view and all of its
15637      * descendants
15638      *
15639      * <p>This is the second phase of the layout mechanism.
15640      * (The first is measuring). In this phase, each parent calls
15641      * layout on all of its children to position them.
15642      * This is typically done using the child measurements
15643      * that were stored in the measure pass().</p>
15644      *
15645      * <p>Derived classes should not override this method.
15646      * Derived classes with children should override
15647      * onLayout. In that method, they should
15648      * call layout on each of their children.</p>
15649      *
15650      * @param l Left position, relative to parent
15651      * @param t Top position, relative to parent
15652      * @param r Right position, relative to parent
15653      * @param b Bottom position, relative to parent
15654      */
15655     @SuppressWarnings({"unchecked"})
15656     public void layout(int l, int t, int r, int b) {
15657         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15658             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15659             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15660         }
15661 
15662         int oldL = mLeft;
15663         int oldT = mTop;
15664         int oldB = mBottom;
15665         int oldR = mRight;
15666 
15667         boolean changed = isLayoutModeOptical(mParent) ?
15668                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15669 
15670         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15671             onLayout(changed, l, t, r, b);
15672             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15673 
15674             ListenerInfo li = mListenerInfo;
15675             if (li != null && li.mOnLayoutChangeListeners != null) {
15676                 ArrayList<OnLayoutChangeListener> listenersCopy =
15677                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15678                 int numListeners = listenersCopy.size();
15679                 for (int i = 0; i < numListeners; ++i) {
15680                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15681                 }
15682             }
15683         }
15684 
15685         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15686         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15687     }
15688 
15689     /**
15690      * Called from layout when this view should
15691      * assign a size and position to each of its children.
15692      *
15693      * Derived classes with children should override
15694      * this method and call layout on each of
15695      * their children.
15696      * @param changed This is a new size or position for this view
15697      * @param left Left position, relative to parent
15698      * @param top Top position, relative to parent
15699      * @param right Right position, relative to parent
15700      * @param bottom Bottom position, relative to parent
15701      */
15702     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15703     }
15704 
15705     /**
15706      * Assign a size and position to this view.
15707      *
15708      * This is called from layout.
15709      *
15710      * @param left Left position, relative to parent
15711      * @param top Top position, relative to parent
15712      * @param right Right position, relative to parent
15713      * @param bottom Bottom position, relative to parent
15714      * @return true if the new size and position are different than the
15715      *         previous ones
15716      * {@hide}
15717      */
15718     protected boolean setFrame(int left, int top, int right, int bottom) {
15719         boolean changed = false;
15720 
15721         if (DBG) {
15722             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
15723                     + right + "," + bottom + ")");
15724         }
15725 
15726         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
15727             changed = true;
15728 
15729             // Remember our drawn bit
15730             int drawn = mPrivateFlags & PFLAG_DRAWN;
15731 
15732             int oldWidth = mRight - mLeft;
15733             int oldHeight = mBottom - mTop;
15734             int newWidth = right - left;
15735             int newHeight = bottom - top;
15736             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
15737 
15738             // Invalidate our old position
15739             invalidate(sizeChanged);
15740 
15741             mLeft = left;
15742             mTop = top;
15743             mRight = right;
15744             mBottom = bottom;
15745             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
15746 
15747             mPrivateFlags |= PFLAG_HAS_BOUNDS;
15748 
15749 
15750             if (sizeChanged) {
15751                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
15752             }
15753 
15754             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
15755                 // If we are visible, force the DRAWN bit to on so that
15756                 // this invalidate will go through (at least to our parent).
15757                 // This is because someone may have invalidated this view
15758                 // before this call to setFrame came in, thereby clearing
15759                 // the DRAWN bit.
15760                 mPrivateFlags |= PFLAG_DRAWN;
15761                 invalidate(sizeChanged);
15762                 // parent display list may need to be recreated based on a change in the bounds
15763                 // of any child
15764                 invalidateParentCaches();
15765             }
15766 
15767             // Reset drawn bit to original value (invalidate turns it off)
15768             mPrivateFlags |= drawn;
15769 
15770             mBackgroundSizeChanged = true;
15771 
15772             notifySubtreeAccessibilityStateChangedIfNeeded();
15773         }
15774         return changed;
15775     }
15776 
15777     /**
15778      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
15779      * @hide
15780      */
15781     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
15782         setFrame(left, top, right, bottom);
15783     }
15784 
15785     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
15786         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
15787         if (mOverlay != null) {
15788             mOverlay.getOverlayView().setRight(newWidth);
15789             mOverlay.getOverlayView().setBottom(newHeight);
15790         }
15791         rebuildOutline();
15792     }
15793 
15794     /**
15795      * Finalize inflating a view from XML.  This is called as the last phase
15796      * of inflation, after all child views have been added.
15797      *
15798      * <p>Even if the subclass overrides onFinishInflate, they should always be
15799      * sure to call the super method, so that we get called.
15800      */
15801     protected void onFinishInflate() {
15802     }
15803 
15804     /**
15805      * Returns the resources associated with this view.
15806      *
15807      * @return Resources object.
15808      */
15809     public Resources getResources() {
15810         return mResources;
15811     }
15812 
15813     /**
15814      * Invalidates the specified Drawable.
15815      *
15816      * @param drawable the drawable to invalidate
15817      */
15818     @Override
15819     public void invalidateDrawable(@NonNull Drawable drawable) {
15820         if (verifyDrawable(drawable)) {
15821             final Rect dirty = drawable.getDirtyBounds();
15822             final int scrollX = mScrollX;
15823             final int scrollY = mScrollY;
15824 
15825             invalidate(dirty.left + scrollX, dirty.top + scrollY,
15826                     dirty.right + scrollX, dirty.bottom + scrollY);
15827             rebuildOutline();
15828         }
15829     }
15830 
15831     /**
15832      * Schedules an action on a drawable to occur at a specified time.
15833      *
15834      * @param who the recipient of the action
15835      * @param what the action to run on the drawable
15836      * @param when the time at which the action must occur. Uses the
15837      *        {@link SystemClock#uptimeMillis} timebase.
15838      */
15839     @Override
15840     public void scheduleDrawable(Drawable who, Runnable what, long when) {
15841         if (verifyDrawable(who) && what != null) {
15842             final long delay = when - SystemClock.uptimeMillis();
15843             if (mAttachInfo != null) {
15844                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15845                         Choreographer.CALLBACK_ANIMATION, what, who,
15846                         Choreographer.subtractFrameDelay(delay));
15847             } else {
15848                 ViewRootImpl.getRunQueue().postDelayed(what, delay);
15849             }
15850         }
15851     }
15852 
15853     /**
15854      * Cancels a scheduled action on a drawable.
15855      *
15856      * @param who the recipient of the action
15857      * @param what the action to cancel
15858      */
15859     @Override
15860     public void unscheduleDrawable(Drawable who, Runnable what) {
15861         if (verifyDrawable(who) && what != null) {
15862             if (mAttachInfo != null) {
15863                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15864                         Choreographer.CALLBACK_ANIMATION, what, who);
15865             }
15866             ViewRootImpl.getRunQueue().removeCallbacks(what);
15867         }
15868     }
15869 
15870     /**
15871      * Unschedule any events associated with the given Drawable.  This can be
15872      * used when selecting a new Drawable into a view, so that the previous
15873      * one is completely unscheduled.
15874      *
15875      * @param who The Drawable to unschedule.
15876      *
15877      * @see #drawableStateChanged
15878      */
15879     public void unscheduleDrawable(Drawable who) {
15880         if (mAttachInfo != null && who != null) {
15881             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15882                     Choreographer.CALLBACK_ANIMATION, null, who);
15883         }
15884     }
15885 
15886     /**
15887      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
15888      * that the View directionality can and will be resolved before its Drawables.
15889      *
15890      * Will call {@link View#onResolveDrawables} when resolution is done.
15891      *
15892      * @hide
15893      */
15894     protected void resolveDrawables() {
15895         // Drawables resolution may need to happen before resolving the layout direction (which is
15896         // done only during the measure() call).
15897         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
15898         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
15899         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
15900         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
15901         // direction to be resolved as its resolved value will be the same as its raw value.
15902         if (!isLayoutDirectionResolved() &&
15903                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
15904             return;
15905         }
15906 
15907         final int layoutDirection = isLayoutDirectionResolved() ?
15908                 getLayoutDirection() : getRawLayoutDirection();
15909 
15910         if (mBackground != null) {
15911             mBackground.setLayoutDirection(layoutDirection);
15912         }
15913         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
15914         onResolveDrawables(layoutDirection);
15915     }
15916 
15917     boolean areDrawablesResolved() {
15918         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
15919     }
15920 
15921     /**
15922      * Called when layout direction has been resolved.
15923      *
15924      * The default implementation does nothing.
15925      *
15926      * @param layoutDirection The resolved layout direction.
15927      *
15928      * @see #LAYOUT_DIRECTION_LTR
15929      * @see #LAYOUT_DIRECTION_RTL
15930      *
15931      * @hide
15932      */
15933     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
15934     }
15935 
15936     /**
15937      * @hide
15938      */
15939     protected void resetResolvedDrawables() {
15940         resetResolvedDrawablesInternal();
15941     }
15942 
15943     void resetResolvedDrawablesInternal() {
15944         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
15945     }
15946 
15947     /**
15948      * If your view subclass is displaying its own Drawable objects, it should
15949      * override this function and return true for any Drawable it is
15950      * displaying.  This allows animations for those drawables to be
15951      * scheduled.
15952      *
15953      * <p>Be sure to call through to the super class when overriding this
15954      * function.
15955      *
15956      * @param who The Drawable to verify.  Return true if it is one you are
15957      *            displaying, else return the result of calling through to the
15958      *            super class.
15959      *
15960      * @return boolean If true than the Drawable is being displayed in the
15961      *         view; else false and it is not allowed to animate.
15962      *
15963      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
15964      * @see #drawableStateChanged()
15965      */
15966     protected boolean verifyDrawable(Drawable who) {
15967         return who == mBackground;
15968     }
15969 
15970     /**
15971      * This function is called whenever the state of the view changes in such
15972      * a way that it impacts the state of drawables being shown.
15973      * <p>
15974      * If the View has a StateListAnimator, it will also be called to run necessary state
15975      * change animations.
15976      * <p>
15977      * Be sure to call through to the superclass when overriding this function.
15978      *
15979      * @see Drawable#setState(int[])
15980      */
15981     protected void drawableStateChanged() {
15982         final Drawable d = mBackground;
15983         if (d != null && d.isStateful()) {
15984             d.setState(getDrawableState());
15985         }
15986 
15987         if (mStateListAnimator != null) {
15988             mStateListAnimator.setState(getDrawableState());
15989         }
15990     }
15991 
15992     /**
15993      * This function is called whenever the view hotspot changes and needs to
15994      * be propagated to drawables or child views managed by the view.
15995      * <p>
15996      * Dispatching to child views is handled by
15997      * {@link #dispatchDrawableHotspotChanged(float, float)}.
15998      * <p>
15999      * Be sure to call through to the superclass when overriding this function.
16000      *
16001      * @param x hotspot x coordinate
16002      * @param y hotspot y coordinate
16003      */
16004     public void drawableHotspotChanged(float x, float y) {
16005         if (mBackground != null) {
16006             mBackground.setHotspot(x, y);
16007         }
16008 
16009         dispatchDrawableHotspotChanged(x, y);
16010     }
16011 
16012     /**
16013      * Dispatches drawableHotspotChanged to all of this View's children.
16014      *
16015      * @param x hotspot x coordinate
16016      * @param y hotspot y coordinate
16017      * @see #drawableHotspotChanged(float, float)
16018      */
16019     public void dispatchDrawableHotspotChanged(float x, float y) {
16020     }
16021 
16022     /**
16023      * Call this to force a view to update its drawable state. This will cause
16024      * drawableStateChanged to be called on this view. Views that are interested
16025      * in the new state should call getDrawableState.
16026      *
16027      * @see #drawableStateChanged
16028      * @see #getDrawableState
16029      */
16030     public void refreshDrawableState() {
16031         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16032         drawableStateChanged();
16033 
16034         ViewParent parent = mParent;
16035         if (parent != null) {
16036             parent.childDrawableStateChanged(this);
16037         }
16038     }
16039 
16040     /**
16041      * Return an array of resource IDs of the drawable states representing the
16042      * current state of the view.
16043      *
16044      * @return The current drawable state
16045      *
16046      * @see Drawable#setState(int[])
16047      * @see #drawableStateChanged()
16048      * @see #onCreateDrawableState(int)
16049      */
16050     public final int[] getDrawableState() {
16051         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
16052             return mDrawableState;
16053         } else {
16054             mDrawableState = onCreateDrawableState(0);
16055             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
16056             return mDrawableState;
16057         }
16058     }
16059 
16060     /**
16061      * Generate the new {@link android.graphics.drawable.Drawable} state for
16062      * this view. This is called by the view
16063      * system when the cached Drawable state is determined to be invalid.  To
16064      * retrieve the current state, you should use {@link #getDrawableState}.
16065      *
16066      * @param extraSpace if non-zero, this is the number of extra entries you
16067      * would like in the returned array in which you can place your own
16068      * states.
16069      *
16070      * @return Returns an array holding the current {@link Drawable} state of
16071      * the view.
16072      *
16073      * @see #mergeDrawableStates(int[], int[])
16074      */
16075     protected int[] onCreateDrawableState(int extraSpace) {
16076         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
16077                 mParent instanceof View) {
16078             return ((View) mParent).onCreateDrawableState(extraSpace);
16079         }
16080 
16081         int[] drawableState;
16082 
16083         int privateFlags = mPrivateFlags;
16084 
16085         int viewStateIndex = 0;
16086         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
16087         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
16088         if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
16089         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
16090         if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
16091         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
16092         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
16093                 HardwareRenderer.isAvailable()) {
16094             // This is set if HW acceleration is requested, even if the current
16095             // process doesn't allow it.  This is just to allow app preview
16096             // windows to better match their app.
16097             viewStateIndex |= VIEW_STATE_ACCELERATED;
16098         }
16099         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
16100 
16101         final int privateFlags2 = mPrivateFlags2;
16102         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
16103         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
16104 
16105         drawableState = VIEW_STATE_SETS[viewStateIndex];
16106 
16107         //noinspection ConstantIfStatement
16108         if (false) {
16109             Log.i("View", "drawableStateIndex=" + viewStateIndex);
16110             Log.i("View", toString()
16111                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
16112                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
16113                     + " fo=" + hasFocus()
16114                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
16115                     + " wf=" + hasWindowFocus()
16116                     + ": " + Arrays.toString(drawableState));
16117         }
16118 
16119         if (extraSpace == 0) {
16120             return drawableState;
16121         }
16122 
16123         final int[] fullState;
16124         if (drawableState != null) {
16125             fullState = new int[drawableState.length + extraSpace];
16126             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
16127         } else {
16128             fullState = new int[extraSpace];
16129         }
16130 
16131         return fullState;
16132     }
16133 
16134     /**
16135      * Merge your own state values in <var>additionalState</var> into the base
16136      * state values <var>baseState</var> that were returned by
16137      * {@link #onCreateDrawableState(int)}.
16138      *
16139      * @param baseState The base state values returned by
16140      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
16141      * own additional state values.
16142      *
16143      * @param additionalState The additional state values you would like
16144      * added to <var>baseState</var>; this array is not modified.
16145      *
16146      * @return As a convenience, the <var>baseState</var> array you originally
16147      * passed into the function is returned.
16148      *
16149      * @see #onCreateDrawableState(int)
16150      */
16151     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
16152         final int N = baseState.length;
16153         int i = N - 1;
16154         while (i >= 0 && baseState[i] == 0) {
16155             i--;
16156         }
16157         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
16158         return baseState;
16159     }
16160 
16161     /**
16162      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
16163      * on all Drawable objects associated with this view.
16164      * <p>
16165      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16166      * attached to this view.
16167      */
16168     public void jumpDrawablesToCurrentState() {
16169         if (mBackground != null) {
16170             mBackground.jumpToCurrentState();
16171         }
16172         if (mStateListAnimator != null) {
16173             mStateListAnimator.jumpToCurrentState();
16174         }
16175     }
16176 
16177     /**
16178      * Sets the background color for this view.
16179      * @param color the color of the background
16180      */
16181     @RemotableViewMethod
16182     public void setBackgroundColor(int color) {
16183         if (mBackground instanceof ColorDrawable) {
16184             ((ColorDrawable) mBackground.mutate()).setColor(color);
16185             computeOpaqueFlags();
16186             mBackgroundResource = 0;
16187         } else {
16188             setBackground(new ColorDrawable(color));
16189         }
16190     }
16191 
16192     /**
16193      * Set the background to a given resource. The resource should refer to
16194      * a Drawable object or 0 to remove the background.
16195      * @param resid The identifier of the resource.
16196      *
16197      * @attr ref android.R.styleable#View_background
16198      */
16199     @RemotableViewMethod
16200     public void setBackgroundResource(int resid) {
16201         if (resid != 0 && resid == mBackgroundResource) {
16202             return;
16203         }
16204 
16205         Drawable d = null;
16206         if (resid != 0) {
16207             d = mContext.getDrawable(resid);
16208         }
16209         setBackground(d);
16210 
16211         mBackgroundResource = resid;
16212     }
16213 
16214     /**
16215      * Set the background to a given Drawable, or remove the background. If the
16216      * background has padding, this View's padding is set to the background's
16217      * padding. However, when a background is removed, this View's padding isn't
16218      * touched. If setting the padding is desired, please use
16219      * {@link #setPadding(int, int, int, int)}.
16220      *
16221      * @param background The Drawable to use as the background, or null to remove the
16222      *        background
16223      */
16224     public void setBackground(Drawable background) {
16225         //noinspection deprecation
16226         setBackgroundDrawable(background);
16227     }
16228 
16229     /**
16230      * @deprecated use {@link #setBackground(Drawable)} instead
16231      */
16232     @Deprecated
16233     public void setBackgroundDrawable(Drawable background) {
16234         computeOpaqueFlags();
16235 
16236         if (background == mBackground) {
16237             return;
16238         }
16239 
16240         boolean requestLayout = false;
16241 
16242         mBackgroundResource = 0;
16243 
16244         /*
16245          * Regardless of whether we're setting a new background or not, we want
16246          * to clear the previous drawable.
16247          */
16248         if (mBackground != null) {
16249             mBackground.setCallback(null);
16250             unscheduleDrawable(mBackground);
16251         }
16252 
16253         if (background != null) {
16254             Rect padding = sThreadLocal.get();
16255             if (padding == null) {
16256                 padding = new Rect();
16257                 sThreadLocal.set(padding);
16258             }
16259             resetResolvedDrawablesInternal();
16260             background.setLayoutDirection(getLayoutDirection());
16261             if (background.getPadding(padding)) {
16262                 resetResolvedPaddingInternal();
16263                 switch (background.getLayoutDirection()) {
16264                     case LAYOUT_DIRECTION_RTL:
16265                         mUserPaddingLeftInitial = padding.right;
16266                         mUserPaddingRightInitial = padding.left;
16267                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16268                         break;
16269                     case LAYOUT_DIRECTION_LTR:
16270                     default:
16271                         mUserPaddingLeftInitial = padding.left;
16272                         mUserPaddingRightInitial = padding.right;
16273                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16274                 }
16275                 mLeftPaddingDefined = false;
16276                 mRightPaddingDefined = false;
16277             }
16278 
16279             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
16280             // if it has a different minimum size, we should layout again
16281             if (mBackground == null
16282                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
16283                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16284                 requestLayout = true;
16285             }
16286 
16287             background.setCallback(this);
16288             if (background.isStateful()) {
16289                 background.setState(getDrawableState());
16290             }
16291             background.setVisible(getVisibility() == VISIBLE, false);
16292             mBackground = background;
16293 
16294             applyBackgroundTint();
16295 
16296             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16297                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16298                 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16299                 requestLayout = true;
16300             }
16301         } else {
16302             /* Remove the background */
16303             mBackground = null;
16304 
16305             if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16306                 /*
16307                  * This view ONLY drew the background before and we're removing
16308                  * the background, so now it won't draw anything
16309                  * (hence we SKIP_DRAW)
16310                  */
16311                 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16312                 mPrivateFlags |= PFLAG_SKIP_DRAW;
16313             }
16314 
16315             /*
16316              * When the background is set, we try to apply its padding to this
16317              * View. When the background is removed, we don't touch this View's
16318              * padding. This is noted in the Javadocs. Hence, we don't need to
16319              * requestLayout(), the invalidate() below is sufficient.
16320              */
16321 
16322             // The old background's minimum size could have affected this
16323             // View's layout, so let's requestLayout
16324             requestLayout = true;
16325         }
16326 
16327         computeOpaqueFlags();
16328 
16329         if (requestLayout) {
16330             requestLayout();
16331         }
16332 
16333         mBackgroundSizeChanged = true;
16334         invalidate(true);
16335     }
16336 
16337     /**
16338      * Gets the background drawable
16339      *
16340      * @return The drawable used as the background for this view, if any.
16341      *
16342      * @see #setBackground(Drawable)
16343      *
16344      * @attr ref android.R.styleable#View_background
16345      */
16346     public Drawable getBackground() {
16347         return mBackground;
16348     }
16349 
16350     /**
16351      * Applies a tint to the background drawable. Does not modify the current tint
16352      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16353      * <p>
16354      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16355      * mutate the drawable and apply the specified tint and tint mode using
16356      * {@link Drawable#setTintList(ColorStateList)}.
16357      *
16358      * @param tint the tint to apply, may be {@code null} to clear tint
16359      *
16360      * @attr ref android.R.styleable#View_backgroundTint
16361      * @see #getBackgroundTintList()
16362      * @see Drawable#setTintList(ColorStateList)
16363      */
16364     public void setBackgroundTintList(@Nullable ColorStateList tint) {
16365         if (mBackgroundTint == null) {
16366             mBackgroundTint = new TintInfo();
16367         }
16368         mBackgroundTint.mTintList = tint;
16369         mBackgroundTint.mHasTintList = true;
16370 
16371         applyBackgroundTint();
16372     }
16373 
16374     /**
16375      * Return the tint applied to the background drawable, if specified.
16376      *
16377      * @return the tint applied to the background drawable
16378      * @attr ref android.R.styleable#View_backgroundTint
16379      * @see #setBackgroundTintList(ColorStateList)
16380      */
16381     @Nullable
16382     public ColorStateList getBackgroundTintList() {
16383         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
16384     }
16385 
16386     /**
16387      * Specifies the blending mode used to apply the tint specified by
16388      * {@link #setBackgroundTintList(ColorStateList)}} to the background
16389      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16390      *
16391      * @param tintMode the blending mode used to apply the tint, may be
16392      *                 {@code null} to clear tint
16393      * @attr ref android.R.styleable#View_backgroundTintMode
16394      * @see #getBackgroundTintMode()
16395      * @see Drawable#setTintMode(PorterDuff.Mode)
16396      */
16397     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16398         if (mBackgroundTint == null) {
16399             mBackgroundTint = new TintInfo();
16400         }
16401         mBackgroundTint.mTintMode = tintMode;
16402         mBackgroundTint.mHasTintMode = true;
16403 
16404         applyBackgroundTint();
16405     }
16406 
16407     /**
16408      * Return the blending mode used to apply the tint to the background
16409      * drawable, if specified.
16410      *
16411      * @return the blending mode used to apply the tint to the background
16412      *         drawable
16413      * @attr ref android.R.styleable#View_backgroundTintMode
16414      * @see #setBackgroundTintMode(PorterDuff.Mode)
16415      */
16416     @Nullable
16417     public PorterDuff.Mode getBackgroundTintMode() {
16418         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
16419     }
16420 
16421     private void applyBackgroundTint() {
16422         if (mBackground != null && mBackgroundTint != null) {
16423             final TintInfo tintInfo = mBackgroundTint;
16424             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16425                 mBackground = mBackground.mutate();
16426 
16427                 if (tintInfo.mHasTintList) {
16428                     mBackground.setTintList(tintInfo.mTintList);
16429                 }
16430 
16431                 if (tintInfo.mHasTintMode) {
16432                     mBackground.setTintMode(tintInfo.mTintMode);
16433                 }
16434 
16435                 // The drawable (or one of its children) may not have been
16436                 // stateful before applying the tint, so let's try again.
16437                 if (mBackground.isStateful()) {
16438                     mBackground.setState(getDrawableState());
16439                 }
16440             }
16441         }
16442     }
16443 
16444     /**
16445      * Sets the padding. The view may add on the space required to display
16446      * the scrollbars, depending on the style and visibility of the scrollbars.
16447      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
16448      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
16449      * from the values set in this call.
16450      *
16451      * @attr ref android.R.styleable#View_padding
16452      * @attr ref android.R.styleable#View_paddingBottom
16453      * @attr ref android.R.styleable#View_paddingLeft
16454      * @attr ref android.R.styleable#View_paddingRight
16455      * @attr ref android.R.styleable#View_paddingTop
16456      * @param left the left padding in pixels
16457      * @param top the top padding in pixels
16458      * @param right the right padding in pixels
16459      * @param bottom the bottom padding in pixels
16460      */
16461     public void setPadding(int left, int top, int right, int bottom) {
16462         resetResolvedPaddingInternal();
16463 
16464         mUserPaddingStart = UNDEFINED_PADDING;
16465         mUserPaddingEnd = UNDEFINED_PADDING;
16466 
16467         mUserPaddingLeftInitial = left;
16468         mUserPaddingRightInitial = right;
16469 
16470         mLeftPaddingDefined = true;
16471         mRightPaddingDefined = true;
16472 
16473         internalSetPadding(left, top, right, bottom);
16474     }
16475 
16476     /**
16477      * @hide
16478      */
16479     protected void internalSetPadding(int left, int top, int right, int bottom) {
16480         mUserPaddingLeft = left;
16481         mUserPaddingRight = right;
16482         mUserPaddingBottom = bottom;
16483 
16484         final int viewFlags = mViewFlags;
16485         boolean changed = false;
16486 
16487         // Common case is there are no scroll bars.
16488         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
16489             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
16490                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
16491                         ? 0 : getVerticalScrollbarWidth();
16492                 switch (mVerticalScrollbarPosition) {
16493                     case SCROLLBAR_POSITION_DEFAULT:
16494                         if (isLayoutRtl()) {
16495                             left += offset;
16496                         } else {
16497                             right += offset;
16498                         }
16499                         break;
16500                     case SCROLLBAR_POSITION_RIGHT:
16501                         right += offset;
16502                         break;
16503                     case SCROLLBAR_POSITION_LEFT:
16504                         left += offset;
16505                         break;
16506                 }
16507             }
16508             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
16509                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
16510                         ? 0 : getHorizontalScrollbarHeight();
16511             }
16512         }
16513 
16514         if (mPaddingLeft != left) {
16515             changed = true;
16516             mPaddingLeft = left;
16517         }
16518         if (mPaddingTop != top) {
16519             changed = true;
16520             mPaddingTop = top;
16521         }
16522         if (mPaddingRight != right) {
16523             changed = true;
16524             mPaddingRight = right;
16525         }
16526         if (mPaddingBottom != bottom) {
16527             changed = true;
16528             mPaddingBottom = bottom;
16529         }
16530 
16531         if (changed) {
16532             requestLayout();
16533             invalidateOutline();
16534         }
16535     }
16536 
16537     /**
16538      * Sets the relative padding. The view may add on the space required to display
16539      * the scrollbars, depending on the style and visibility of the scrollbars.
16540      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
16541      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
16542      * from the values set in this call.
16543      *
16544      * @attr ref android.R.styleable#View_padding
16545      * @attr ref android.R.styleable#View_paddingBottom
16546      * @attr ref android.R.styleable#View_paddingStart
16547      * @attr ref android.R.styleable#View_paddingEnd
16548      * @attr ref android.R.styleable#View_paddingTop
16549      * @param start the start padding in pixels
16550      * @param top the top padding in pixels
16551      * @param end the end padding in pixels
16552      * @param bottom the bottom padding in pixels
16553      */
16554     public void setPaddingRelative(int start, int top, int end, int bottom) {
16555         resetResolvedPaddingInternal();
16556 
16557         mUserPaddingStart = start;
16558         mUserPaddingEnd = end;
16559         mLeftPaddingDefined = true;
16560         mRightPaddingDefined = true;
16561 
16562         switch(getLayoutDirection()) {
16563             case LAYOUT_DIRECTION_RTL:
16564                 mUserPaddingLeftInitial = end;
16565                 mUserPaddingRightInitial = start;
16566                 internalSetPadding(end, top, start, bottom);
16567                 break;
16568             case LAYOUT_DIRECTION_LTR:
16569             default:
16570                 mUserPaddingLeftInitial = start;
16571                 mUserPaddingRightInitial = end;
16572                 internalSetPadding(start, top, end, bottom);
16573         }
16574     }
16575 
16576     /**
16577      * Returns the top padding of this view.
16578      *
16579      * @return the top padding in pixels
16580      */
16581     public int getPaddingTop() {
16582         return mPaddingTop;
16583     }
16584 
16585     /**
16586      * Returns the bottom padding of this view. If there are inset and enabled
16587      * scrollbars, this value may include the space required to display the
16588      * scrollbars as well.
16589      *
16590      * @return the bottom padding in pixels
16591      */
16592     public int getPaddingBottom() {
16593         return mPaddingBottom;
16594     }
16595 
16596     /**
16597      * Returns the left padding of this view. If there are inset and enabled
16598      * scrollbars, this value may include the space required to display the
16599      * scrollbars as well.
16600      *
16601      * @return the left padding in pixels
16602      */
16603     public int getPaddingLeft() {
16604         if (!isPaddingResolved()) {
16605             resolvePadding();
16606         }
16607         return mPaddingLeft;
16608     }
16609 
16610     /**
16611      * Returns the start padding of this view depending on its resolved layout direction.
16612      * If there are inset and enabled scrollbars, this value may include the space
16613      * required to display the scrollbars as well.
16614      *
16615      * @return the start padding in pixels
16616      */
16617     public int getPaddingStart() {
16618         if (!isPaddingResolved()) {
16619             resolvePadding();
16620         }
16621         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16622                 mPaddingRight : mPaddingLeft;
16623     }
16624 
16625     /**
16626      * Returns the right padding of this view. If there are inset and enabled
16627      * scrollbars, this value may include the space required to display the
16628      * scrollbars as well.
16629      *
16630      * @return the right padding in pixels
16631      */
16632     public int getPaddingRight() {
16633         if (!isPaddingResolved()) {
16634             resolvePadding();
16635         }
16636         return mPaddingRight;
16637     }
16638 
16639     /**
16640      * Returns the end padding of this view depending on its resolved layout direction.
16641      * If there are inset and enabled scrollbars, this value may include the space
16642      * required to display the scrollbars as well.
16643      *
16644      * @return the end padding in pixels
16645      */
16646     public int getPaddingEnd() {
16647         if (!isPaddingResolved()) {
16648             resolvePadding();
16649         }
16650         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16651                 mPaddingLeft : mPaddingRight;
16652     }
16653 
16654     /**
16655      * Return if the padding as been set thru relative values
16656      * {@link #setPaddingRelative(int, int, int, int)} or thru
16657      * @attr ref android.R.styleable#View_paddingStart or
16658      * @attr ref android.R.styleable#View_paddingEnd
16659      *
16660      * @return true if the padding is relative or false if it is not.
16661      */
16662     public boolean isPaddingRelative() {
16663         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
16664     }
16665 
16666     Insets computeOpticalInsets() {
16667         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
16668     }
16669 
16670     /**
16671      * @hide
16672      */
16673     public void resetPaddingToInitialValues() {
16674         if (isRtlCompatibilityMode()) {
16675             mPaddingLeft = mUserPaddingLeftInitial;
16676             mPaddingRight = mUserPaddingRightInitial;
16677             return;
16678         }
16679         if (isLayoutRtl()) {
16680             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
16681             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
16682         } else {
16683             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
16684             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
16685         }
16686     }
16687 
16688     /**
16689      * @hide
16690      */
16691     public Insets getOpticalInsets() {
16692         if (mLayoutInsets == null) {
16693             mLayoutInsets = computeOpticalInsets();
16694         }
16695         return mLayoutInsets;
16696     }
16697 
16698     /**
16699      * Set this view's optical insets.
16700      *
16701      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
16702      * property. Views that compute their own optical insets should call it as part of measurement.
16703      * This method does not request layout. If you are setting optical insets outside of
16704      * measure/layout itself you will want to call requestLayout() yourself.
16705      * </p>
16706      * @hide
16707      */
16708     public void setOpticalInsets(Insets insets) {
16709         mLayoutInsets = insets;
16710     }
16711 
16712     /**
16713      * Changes the selection state of this view. A view can be selected or not.
16714      * Note that selection is not the same as focus. Views are typically
16715      * selected in the context of an AdapterView like ListView or GridView;
16716      * the selected view is the view that is highlighted.
16717      *
16718      * @param selected true if the view must be selected, false otherwise
16719      */
16720     public void setSelected(boolean selected) {
16721         //noinspection DoubleNegation
16722         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
16723             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
16724             if (!selected) resetPressedState();
16725             invalidate(true);
16726             refreshDrawableState();
16727             dispatchSetSelected(selected);
16728             if (selected) {
16729                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
16730             } else {
16731                 notifyViewAccessibilityStateChangedIfNeeded(
16732                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16733             }
16734         }
16735     }
16736 
16737     /**
16738      * Dispatch setSelected to all of this View's children.
16739      *
16740      * @see #setSelected(boolean)
16741      *
16742      * @param selected The new selected state
16743      */
16744     protected void dispatchSetSelected(boolean selected) {
16745     }
16746 
16747     /**
16748      * Indicates the selection state of this view.
16749      *
16750      * @return true if the view is selected, false otherwise
16751      */
16752     @ViewDebug.ExportedProperty
16753     public boolean isSelected() {
16754         return (mPrivateFlags & PFLAG_SELECTED) != 0;
16755     }
16756 
16757     /**
16758      * Changes the activated state of this view. A view can be activated or not.
16759      * Note that activation is not the same as selection.  Selection is
16760      * a transient property, representing the view (hierarchy) the user is
16761      * currently interacting with.  Activation is a longer-term state that the
16762      * user can move views in and out of.  For example, in a list view with
16763      * single or multiple selection enabled, the views in the current selection
16764      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
16765      * here.)  The activated state is propagated down to children of the view it
16766      * is set on.
16767      *
16768      * @param activated true if the view must be activated, false otherwise
16769      */
16770     public void setActivated(boolean activated) {
16771         //noinspection DoubleNegation
16772         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
16773             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
16774             invalidate(true);
16775             refreshDrawableState();
16776             dispatchSetActivated(activated);
16777         }
16778     }
16779 
16780     /**
16781      * Dispatch setActivated to all of this View's children.
16782      *
16783      * @see #setActivated(boolean)
16784      *
16785      * @param activated The new activated state
16786      */
16787     protected void dispatchSetActivated(boolean activated) {
16788     }
16789 
16790     /**
16791      * Indicates the activation state of this view.
16792      *
16793      * @return true if the view is activated, false otherwise
16794      */
16795     @ViewDebug.ExportedProperty
16796     public boolean isActivated() {
16797         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
16798     }
16799 
16800     /**
16801      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
16802      * observer can be used to get notifications when global events, like
16803      * layout, happen.
16804      *
16805      * The returned ViewTreeObserver observer is not guaranteed to remain
16806      * valid for the lifetime of this View. If the caller of this method keeps
16807      * a long-lived reference to ViewTreeObserver, it should always check for
16808      * the return value of {@link ViewTreeObserver#isAlive()}.
16809      *
16810      * @return The ViewTreeObserver for this view's hierarchy.
16811      */
16812     public ViewTreeObserver getViewTreeObserver() {
16813         if (mAttachInfo != null) {
16814             return mAttachInfo.mTreeObserver;
16815         }
16816         if (mFloatingTreeObserver == null) {
16817             mFloatingTreeObserver = new ViewTreeObserver();
16818         }
16819         return mFloatingTreeObserver;
16820     }
16821 
16822     /**
16823      * <p>Finds the topmost view in the current view hierarchy.</p>
16824      *
16825      * @return the topmost view containing this view
16826      */
16827     public View getRootView() {
16828         if (mAttachInfo != null) {
16829             final View v = mAttachInfo.mRootView;
16830             if (v != null) {
16831                 return v;
16832             }
16833         }
16834 
16835         View parent = this;
16836 
16837         while (parent.mParent != null && parent.mParent instanceof View) {
16838             parent = (View) parent.mParent;
16839         }
16840 
16841         return parent;
16842     }
16843 
16844     /**
16845      * Transforms a motion event from view-local coordinates to on-screen
16846      * coordinates.
16847      *
16848      * @param ev the view-local motion event
16849      * @return false if the transformation could not be applied
16850      * @hide
16851      */
16852     public boolean toGlobalMotionEvent(MotionEvent ev) {
16853         final AttachInfo info = mAttachInfo;
16854         if (info == null) {
16855             return false;
16856         }
16857 
16858         final Matrix m = info.mTmpMatrix;
16859         m.set(Matrix.IDENTITY_MATRIX);
16860         transformMatrixToGlobal(m);
16861         ev.transform(m);
16862         return true;
16863     }
16864 
16865     /**
16866      * Transforms a motion event from on-screen coordinates to view-local
16867      * coordinates.
16868      *
16869      * @param ev the on-screen motion event
16870      * @return false if the transformation could not be applied
16871      * @hide
16872      */
16873     public boolean toLocalMotionEvent(MotionEvent ev) {
16874         final AttachInfo info = mAttachInfo;
16875         if (info == null) {
16876             return false;
16877         }
16878 
16879         final Matrix m = info.mTmpMatrix;
16880         m.set(Matrix.IDENTITY_MATRIX);
16881         transformMatrixToLocal(m);
16882         ev.transform(m);
16883         return true;
16884     }
16885 
16886     /**
16887      * Modifies the input matrix such that it maps view-local coordinates to
16888      * on-screen coordinates.
16889      *
16890      * @param m input matrix to modify
16891      * @hide
16892      */
16893     public void transformMatrixToGlobal(Matrix m) {
16894         final ViewParent parent = mParent;
16895         if (parent instanceof View) {
16896             final View vp = (View) parent;
16897             vp.transformMatrixToGlobal(m);
16898             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
16899         } else if (parent instanceof ViewRootImpl) {
16900             final ViewRootImpl vr = (ViewRootImpl) parent;
16901             vr.transformMatrixToGlobal(m);
16902             m.preTranslate(0, -vr.mCurScrollY);
16903         }
16904 
16905         m.preTranslate(mLeft, mTop);
16906 
16907         if (!hasIdentityMatrix()) {
16908             m.preConcat(getMatrix());
16909         }
16910     }
16911 
16912     /**
16913      * Modifies the input matrix such that it maps on-screen coordinates to
16914      * view-local coordinates.
16915      *
16916      * @param m input matrix to modify
16917      * @hide
16918      */
16919     public void transformMatrixToLocal(Matrix m) {
16920         final ViewParent parent = mParent;
16921         if (parent instanceof View) {
16922             final View vp = (View) parent;
16923             vp.transformMatrixToLocal(m);
16924             m.postTranslate(vp.mScrollX, vp.mScrollY);
16925         } else if (parent instanceof ViewRootImpl) {
16926             final ViewRootImpl vr = (ViewRootImpl) parent;
16927             vr.transformMatrixToLocal(m);
16928             m.postTranslate(0, vr.mCurScrollY);
16929         }
16930 
16931         m.postTranslate(-mLeft, -mTop);
16932 
16933         if (!hasIdentityMatrix()) {
16934             m.postConcat(getInverseMatrix());
16935         }
16936     }
16937 
16938     /**
16939      * @hide
16940      */
16941     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
16942             @ViewDebug.IntToString(from = 0, to = "x"),
16943             @ViewDebug.IntToString(from = 1, to = "y")
16944     })
16945     public int[] getLocationOnScreen() {
16946         int[] location = new int[2];
16947         getLocationOnScreen(location);
16948         return location;
16949     }
16950 
16951     /**
16952      * <p>Computes the coordinates of this view on the screen. The argument
16953      * must be an array of two integers. After the method returns, the array
16954      * contains the x and y location in that order.</p>
16955      *
16956      * @param location an array of two integers in which to hold the coordinates
16957      */
16958     public void getLocationOnScreen(int[] location) {
16959         getLocationInWindow(location);
16960 
16961         final AttachInfo info = mAttachInfo;
16962         if (info != null) {
16963             location[0] += info.mWindowLeft;
16964             location[1] += info.mWindowTop;
16965         }
16966     }
16967 
16968     /**
16969      * <p>Computes the coordinates of this view in its window. The argument
16970      * must be an array of two integers. After the method returns, the array
16971      * contains the x and y location in that order.</p>
16972      *
16973      * @param location an array of two integers in which to hold the coordinates
16974      */
16975     public void getLocationInWindow(int[] location) {
16976         if (location == null || location.length < 2) {
16977             throw new IllegalArgumentException("location must be an array of two integers");
16978         }
16979 
16980         if (mAttachInfo == null) {
16981             // When the view is not attached to a window, this method does not make sense
16982             location[0] = location[1] = 0;
16983             return;
16984         }
16985 
16986         float[] position = mAttachInfo.mTmpTransformLocation;
16987         position[0] = position[1] = 0.0f;
16988 
16989         if (!hasIdentityMatrix()) {
16990             getMatrix().mapPoints(position);
16991         }
16992 
16993         position[0] += mLeft;
16994         position[1] += mTop;
16995 
16996         ViewParent viewParent = mParent;
16997         while (viewParent instanceof View) {
16998             final View view = (View) viewParent;
16999 
17000             position[0] -= view.mScrollX;
17001             position[1] -= view.mScrollY;
17002 
17003             if (!view.hasIdentityMatrix()) {
17004                 view.getMatrix().mapPoints(position);
17005             }
17006 
17007             position[0] += view.mLeft;
17008             position[1] += view.mTop;
17009 
17010             viewParent = view.mParent;
17011          }
17012 
17013         if (viewParent instanceof ViewRootImpl) {
17014             // *cough*
17015             final ViewRootImpl vr = (ViewRootImpl) viewParent;
17016             position[1] -= vr.mCurScrollY;
17017         }
17018 
17019         location[0] = (int) (position[0] + 0.5f);
17020         location[1] = (int) (position[1] + 0.5f);
17021     }
17022 
17023     /**
17024      * {@hide}
17025      * @param id the id of the view to be found
17026      * @return the view of the specified id, null if cannot be found
17027      */
17028     protected View findViewTraversal(int id) {
17029         if (id == mID) {
17030             return this;
17031         }
17032         return null;
17033     }
17034 
17035     /**
17036      * {@hide}
17037      * @param tag the tag of the view to be found
17038      * @return the view of specified tag, null if cannot be found
17039      */
17040     protected View findViewWithTagTraversal(Object tag) {
17041         if (tag != null && tag.equals(mTag)) {
17042             return this;
17043         }
17044         return null;
17045     }
17046 
17047     /**
17048      * {@hide}
17049      * @param predicate The predicate to evaluate.
17050      * @param childToSkip If not null, ignores this child during the recursive traversal.
17051      * @return The first view that matches the predicate or null.
17052      */
17053     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
17054         if (predicate.apply(this)) {
17055             return this;
17056         }
17057         return null;
17058     }
17059 
17060     /**
17061      * Look for a child view with the given id.  If this view has the given
17062      * id, return this view.
17063      *
17064      * @param id The id to search for.
17065      * @return The view that has the given id in the hierarchy or null
17066      */
17067     public final View findViewById(int id) {
17068         if (id < 0) {
17069             return null;
17070         }
17071         return findViewTraversal(id);
17072     }
17073 
17074     /**
17075      * Finds a view by its unuque and stable accessibility id.
17076      *
17077      * @param accessibilityId The searched accessibility id.
17078      * @return The found view.
17079      */
17080     final View findViewByAccessibilityId(int accessibilityId) {
17081         if (accessibilityId < 0) {
17082             return null;
17083         }
17084         return findViewByAccessibilityIdTraversal(accessibilityId);
17085     }
17086 
17087     /**
17088      * Performs the traversal to find a view by its unuque and stable accessibility id.
17089      *
17090      * <strong>Note:</strong>This method does not stop at the root namespace
17091      * boundary since the user can touch the screen at an arbitrary location
17092      * potentially crossing the root namespace bounday which will send an
17093      * accessibility event to accessibility services and they should be able
17094      * to obtain the event source. Also accessibility ids are guaranteed to be
17095      * unique in the window.
17096      *
17097      * @param accessibilityId The accessibility id.
17098      * @return The found view.
17099      *
17100      * @hide
17101      */
17102     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
17103         if (getAccessibilityViewId() == accessibilityId) {
17104             return this;
17105         }
17106         return null;
17107     }
17108 
17109     /**
17110      * Look for a child view with the given tag.  If this view has the given
17111      * tag, return this view.
17112      *
17113      * @param tag The tag to search for, using "tag.equals(getTag())".
17114      * @return The View that has the given tag in the hierarchy or null
17115      */
17116     public final View findViewWithTag(Object tag) {
17117         if (tag == null) {
17118             return null;
17119         }
17120         return findViewWithTagTraversal(tag);
17121     }
17122 
17123     /**
17124      * {@hide}
17125      * Look for a child view that matches the specified predicate.
17126      * If this view matches the predicate, return this view.
17127      *
17128      * @param predicate The predicate to evaluate.
17129      * @return The first view that matches the predicate or null.
17130      */
17131     public final View findViewByPredicate(Predicate<View> predicate) {
17132         return findViewByPredicateTraversal(predicate, null);
17133     }
17134 
17135     /**
17136      * {@hide}
17137      * Look for a child view that matches the specified predicate,
17138      * starting with the specified view and its descendents and then
17139      * recusively searching the ancestors and siblings of that view
17140      * until this view is reached.
17141      *
17142      * This method is useful in cases where the predicate does not match
17143      * a single unique view (perhaps multiple views use the same id)
17144      * and we are trying to find the view that is "closest" in scope to the
17145      * starting view.
17146      *
17147      * @param start The view to start from.
17148      * @param predicate The predicate to evaluate.
17149      * @return The first view that matches the predicate or null.
17150      */
17151     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
17152         View childToSkip = null;
17153         for (;;) {
17154             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
17155             if (view != null || start == this) {
17156                 return view;
17157             }
17158 
17159             ViewParent parent = start.getParent();
17160             if (parent == null || !(parent instanceof View)) {
17161                 return null;
17162             }
17163 
17164             childToSkip = start;
17165             start = (View) parent;
17166         }
17167     }
17168 
17169     /**
17170      * Sets the identifier for this view. The identifier does not have to be
17171      * unique in this view's hierarchy. The identifier should be a positive
17172      * number.
17173      *
17174      * @see #NO_ID
17175      * @see #getId()
17176      * @see #findViewById(int)
17177      *
17178      * @param id a number used to identify the view
17179      *
17180      * @attr ref android.R.styleable#View_id
17181      */
17182     public void setId(int id) {
17183         mID = id;
17184         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
17185             mID = generateViewId();
17186         }
17187     }
17188 
17189     /**
17190      * {@hide}
17191      *
17192      * @param isRoot true if the view belongs to the root namespace, false
17193      *        otherwise
17194      */
17195     public void setIsRootNamespace(boolean isRoot) {
17196         if (isRoot) {
17197             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17198         } else {
17199             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17200         }
17201     }
17202 
17203     /**
17204      * {@hide}
17205      *
17206      * @return true if the view belongs to the root namespace, false otherwise
17207      */
17208     public boolean isRootNamespace() {
17209         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17210     }
17211 
17212     /**
17213      * Returns this view's identifier.
17214      *
17215      * @return a positive integer used to identify the view or {@link #NO_ID}
17216      *         if the view has no ID
17217      *
17218      * @see #setId(int)
17219      * @see #findViewById(int)
17220      * @attr ref android.R.styleable#View_id
17221      */
17222     @ViewDebug.CapturedViewProperty
17223     public int getId() {
17224         return mID;
17225     }
17226 
17227     /**
17228      * Returns this view's tag.
17229      *
17230      * @return the Object stored in this view as a tag, or {@code null} if not
17231      *         set
17232      *
17233      * @see #setTag(Object)
17234      * @see #getTag(int)
17235      */
17236     @ViewDebug.ExportedProperty
17237     public Object getTag() {
17238         return mTag;
17239     }
17240 
17241     /**
17242      * Sets the tag associated with this view. A tag can be used to mark
17243      * a view in its hierarchy and does not have to be unique within the
17244      * hierarchy. Tags can also be used to store data within a view without
17245      * resorting to another data structure.
17246      *
17247      * @param tag an Object to tag the view with
17248      *
17249      * @see #getTag()
17250      * @see #setTag(int, Object)
17251      */
17252     public void setTag(final Object tag) {
17253         mTag = tag;
17254     }
17255 
17256     /**
17257      * Returns the tag associated with this view and the specified key.
17258      *
17259      * @param key The key identifying the tag
17260      *
17261      * @return the Object stored in this view as a tag, or {@code null} if not
17262      *         set
17263      *
17264      * @see #setTag(int, Object)
17265      * @see #getTag()
17266      */
17267     public Object getTag(int key) {
17268         if (mKeyedTags != null) return mKeyedTags.get(key);
17269         return null;
17270     }
17271 
17272     /**
17273      * Sets a tag associated with this view and a key. A tag can be used
17274      * to mark a view in its hierarchy and does not have to be unique within
17275      * the hierarchy. Tags can also be used to store data within a view
17276      * without resorting to another data structure.
17277      *
17278      * The specified key should be an id declared in the resources of the
17279      * application to ensure it is unique (see the <a
17280      * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17281      * Keys identified as belonging to
17282      * the Android framework or not associated with any package will cause
17283      * an {@link IllegalArgumentException} to be thrown.
17284      *
17285      * @param key The key identifying the tag
17286      * @param tag An Object to tag the view with
17287      *
17288      * @throws IllegalArgumentException If they specified key is not valid
17289      *
17290      * @see #setTag(Object)
17291      * @see #getTag(int)
17292      */
17293     public void setTag(int key, final Object tag) {
17294         // If the package id is 0x00 or 0x01, it's either an undefined package
17295         // or a framework id
17296         if ((key >>> 24) < 2) {
17297             throw new IllegalArgumentException("The key must be an application-specific "
17298                     + "resource id.");
17299         }
17300 
17301         setKeyedTag(key, tag);
17302     }
17303 
17304     /**
17305      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
17306      * framework id.
17307      *
17308      * @hide
17309      */
17310     public void setTagInternal(int key, Object tag) {
17311         if ((key >>> 24) != 0x1) {
17312             throw new IllegalArgumentException("The key must be a framework-specific "
17313                     + "resource id.");
17314         }
17315 
17316         setKeyedTag(key, tag);
17317     }
17318 
17319     private void setKeyedTag(int key, Object tag) {
17320         if (mKeyedTags == null) {
17321             mKeyedTags = new SparseArray<Object>(2);
17322         }
17323 
17324         mKeyedTags.put(key, tag);
17325     }
17326 
17327     /**
17328      * Prints information about this view in the log output, with the tag
17329      * {@link #VIEW_LOG_TAG}.
17330      *
17331      * @hide
17332      */
17333     public void debug() {
17334         debug(0);
17335     }
17336 
17337     /**
17338      * Prints information about this view in the log output, with the tag
17339      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
17340      * indentation defined by the <code>depth</code>.
17341      *
17342      * @param depth the indentation level
17343      *
17344      * @hide
17345      */
17346     protected void debug(int depth) {
17347         String output = debugIndent(depth - 1);
17348 
17349         output += "+ " + this;
17350         int id = getId();
17351         if (id != -1) {
17352             output += " (id=" + id + ")";
17353         }
17354         Object tag = getTag();
17355         if (tag != null) {
17356             output += " (tag=" + tag + ")";
17357         }
17358         Log.d(VIEW_LOG_TAG, output);
17359 
17360         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
17361             output = debugIndent(depth) + " FOCUSED";
17362             Log.d(VIEW_LOG_TAG, output);
17363         }
17364 
17365         output = debugIndent(depth);
17366         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
17367                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
17368                 + "} ";
17369         Log.d(VIEW_LOG_TAG, output);
17370 
17371         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
17372                 || mPaddingBottom != 0) {
17373             output = debugIndent(depth);
17374             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
17375                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
17376             Log.d(VIEW_LOG_TAG, output);
17377         }
17378 
17379         output = debugIndent(depth);
17380         output += "mMeasureWidth=" + mMeasuredWidth +
17381                 " mMeasureHeight=" + mMeasuredHeight;
17382         Log.d(VIEW_LOG_TAG, output);
17383 
17384         output = debugIndent(depth);
17385         if (mLayoutParams == null) {
17386             output += "BAD! no layout params";
17387         } else {
17388             output = mLayoutParams.debug(output);
17389         }
17390         Log.d(VIEW_LOG_TAG, output);
17391 
17392         output = debugIndent(depth);
17393         output += "flags={";
17394         output += View.printFlags(mViewFlags);
17395         output += "}";
17396         Log.d(VIEW_LOG_TAG, output);
17397 
17398         output = debugIndent(depth);
17399         output += "privateFlags={";
17400         output += View.printPrivateFlags(mPrivateFlags);
17401         output += "}";
17402         Log.d(VIEW_LOG_TAG, output);
17403     }
17404 
17405     /**
17406      * Creates a string of whitespaces used for indentation.
17407      *
17408      * @param depth the indentation level
17409      * @return a String containing (depth * 2 + 3) * 2 white spaces
17410      *
17411      * @hide
17412      */
17413     protected static String debugIndent(int depth) {
17414         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
17415         for (int i = 0; i < (depth * 2) + 3; i++) {
17416             spaces.append(' ').append(' ');
17417         }
17418         return spaces.toString();
17419     }
17420 
17421     /**
17422      * <p>Return the offset of the widget's text baseline from the widget's top
17423      * boundary. If this widget does not support baseline alignment, this
17424      * method returns -1. </p>
17425      *
17426      * @return the offset of the baseline within the widget's bounds or -1
17427      *         if baseline alignment is not supported
17428      */
17429     @ViewDebug.ExportedProperty(category = "layout")
17430     public int getBaseline() {
17431         return -1;
17432     }
17433 
17434     /**
17435      * Returns whether the view hierarchy is currently undergoing a layout pass. This
17436      * information is useful to avoid situations such as calling {@link #requestLayout()} during
17437      * a layout pass.
17438      *
17439      * @return whether the view hierarchy is currently undergoing a layout pass
17440      */
17441     public boolean isInLayout() {
17442         ViewRootImpl viewRoot = getViewRootImpl();
17443         return (viewRoot != null && viewRoot.isInLayout());
17444     }
17445 
17446     /**
17447      * Call this when something has changed which has invalidated the
17448      * layout of this view. This will schedule a layout pass of the view
17449      * tree. This should not be called while the view hierarchy is currently in a layout
17450      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
17451      * end of the current layout pass (and then layout will run again) or after the current
17452      * frame is drawn and the next layout occurs.
17453      *
17454      * <p>Subclasses which override this method should call the superclass method to
17455      * handle possible request-during-layout errors correctly.</p>
17456      */
17457     public void requestLayout() {
17458         if (mMeasureCache != null) mMeasureCache.clear();
17459 
17460         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
17461             // Only trigger request-during-layout logic if this is the view requesting it,
17462             // not the views in its parent hierarchy
17463             ViewRootImpl viewRoot = getViewRootImpl();
17464             if (viewRoot != null && viewRoot.isInLayout()) {
17465                 if (!viewRoot.requestLayoutDuringLayout(this)) {
17466                     return;
17467                 }
17468             }
17469             mAttachInfo.mViewRequestingLayout = this;
17470         }
17471 
17472         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17473         mPrivateFlags |= PFLAG_INVALIDATED;
17474 
17475         if (mParent != null && !mParent.isLayoutRequested()) {
17476             mParent.requestLayout();
17477         }
17478         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
17479             mAttachInfo.mViewRequestingLayout = null;
17480         }
17481     }
17482 
17483     /**
17484      * Forces this view to be laid out during the next layout pass.
17485      * This method does not call requestLayout() or forceLayout()
17486      * on the parent.
17487      */
17488     public void forceLayout() {
17489         if (mMeasureCache != null) mMeasureCache.clear();
17490 
17491         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17492         mPrivateFlags |= PFLAG_INVALIDATED;
17493     }
17494 
17495     /**
17496      * <p>
17497      * This is called to find out how big a view should be. The parent
17498      * supplies constraint information in the width and height parameters.
17499      * </p>
17500      *
17501      * <p>
17502      * The actual measurement work of a view is performed in
17503      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
17504      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
17505      * </p>
17506      *
17507      *
17508      * @param widthMeasureSpec Horizontal space requirements as imposed by the
17509      *        parent
17510      * @param heightMeasureSpec Vertical space requirements as imposed by the
17511      *        parent
17512      *
17513      * @see #onMeasure(int, int)
17514      */
17515     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
17516         boolean optical = isLayoutModeOptical(this);
17517         if (optical != isLayoutModeOptical(mParent)) {
17518             Insets insets = getOpticalInsets();
17519             int oWidth  = insets.left + insets.right;
17520             int oHeight = insets.top  + insets.bottom;
17521             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
17522             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
17523         }
17524 
17525         // Suppress sign extension for the low bytes
17526         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
17527         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
17528 
17529         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17530         final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
17531                 MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
17532         final boolean matchingSize = isExactly &&
17533                 getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
17534                 getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
17535         if (forceLayout || !matchingSize &&
17536                 (widthMeasureSpec != mOldWidthMeasureSpec ||
17537                         heightMeasureSpec != mOldHeightMeasureSpec)) {
17538 
17539             // first clears the measured dimension flag
17540             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
17541 
17542             resolveRtlPropertiesIfNeeded();
17543 
17544             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
17545             if (cacheIndex < 0 || sIgnoreMeasureCache) {
17546                 // measure ourselves, this should set the measured dimension flag back
17547                 onMeasure(widthMeasureSpec, heightMeasureSpec);
17548                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17549             } else {
17550                 long value = mMeasureCache.valueAt(cacheIndex);
17551                 // Casting a long to int drops the high 32 bits, no mask needed
17552                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
17553                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17554             }
17555 
17556             // flag not set, setMeasuredDimension() was not invoked, we raise
17557             // an exception to warn the developer
17558             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
17559                 throw new IllegalStateException("onMeasure() did not set the"
17560                         + " measured dimension by calling"
17561                         + " setMeasuredDimension()");
17562             }
17563 
17564             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
17565         }
17566 
17567         mOldWidthMeasureSpec = widthMeasureSpec;
17568         mOldHeightMeasureSpec = heightMeasureSpec;
17569 
17570         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
17571                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
17572     }
17573 
17574     /**
17575      * <p>
17576      * Measure the view and its content to determine the measured width and the
17577      * measured height. This method is invoked by {@link #measure(int, int)} and
17578      * should be overriden by subclasses to provide accurate and efficient
17579      * measurement of their contents.
17580      * </p>
17581      *
17582      * <p>
17583      * <strong>CONTRACT:</strong> When overriding this method, you
17584      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
17585      * measured width and height of this view. Failure to do so will trigger an
17586      * <code>IllegalStateException</code>, thrown by
17587      * {@link #measure(int, int)}. Calling the superclass'
17588      * {@link #onMeasure(int, int)} is a valid use.
17589      * </p>
17590      *
17591      * <p>
17592      * The base class implementation of measure defaults to the background size,
17593      * unless a larger size is allowed by the MeasureSpec. Subclasses should
17594      * override {@link #onMeasure(int, int)} to provide better measurements of
17595      * their content.
17596      * </p>
17597      *
17598      * <p>
17599      * If this method is overridden, it is the subclass's responsibility to make
17600      * sure the measured height and width are at least the view's minimum height
17601      * and width ({@link #getSuggestedMinimumHeight()} and
17602      * {@link #getSuggestedMinimumWidth()}).
17603      * </p>
17604      *
17605      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
17606      *                         The requirements are encoded with
17607      *                         {@link android.view.View.MeasureSpec}.
17608      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
17609      *                         The requirements are encoded with
17610      *                         {@link android.view.View.MeasureSpec}.
17611      *
17612      * @see #getMeasuredWidth()
17613      * @see #getMeasuredHeight()
17614      * @see #setMeasuredDimension(int, int)
17615      * @see #getSuggestedMinimumHeight()
17616      * @see #getSuggestedMinimumWidth()
17617      * @see android.view.View.MeasureSpec#getMode(int)
17618      * @see android.view.View.MeasureSpec#getSize(int)
17619      */
17620     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
17621         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
17622                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
17623     }
17624 
17625     /**
17626      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
17627      * measured width and measured height. Failing to do so will trigger an
17628      * exception at measurement time.</p>
17629      *
17630      * @param measuredWidth The measured width of this view.  May be a complex
17631      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17632      * {@link #MEASURED_STATE_TOO_SMALL}.
17633      * @param measuredHeight The measured height of this view.  May be a complex
17634      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17635      * {@link #MEASURED_STATE_TOO_SMALL}.
17636      */
17637     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
17638         boolean optical = isLayoutModeOptical(this);
17639         if (optical != isLayoutModeOptical(mParent)) {
17640             Insets insets = getOpticalInsets();
17641             int opticalWidth  = insets.left + insets.right;
17642             int opticalHeight = insets.top  + insets.bottom;
17643 
17644             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
17645             measuredHeight += optical ? opticalHeight : -opticalHeight;
17646         }
17647         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
17648     }
17649 
17650     /**
17651      * Sets the measured dimension without extra processing for things like optical bounds.
17652      * Useful for reapplying consistent values that have already been cooked with adjustments
17653      * for optical bounds, etc. such as those from the measurement cache.
17654      *
17655      * @param measuredWidth The measured width of this view.  May be a complex
17656      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17657      * {@link #MEASURED_STATE_TOO_SMALL}.
17658      * @param measuredHeight The measured height of this view.  May be a complex
17659      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17660      * {@link #MEASURED_STATE_TOO_SMALL}.
17661      */
17662     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
17663         mMeasuredWidth = measuredWidth;
17664         mMeasuredHeight = measuredHeight;
17665 
17666         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
17667     }
17668 
17669     /**
17670      * Merge two states as returned by {@link #getMeasuredState()}.
17671      * @param curState The current state as returned from a view or the result
17672      * of combining multiple views.
17673      * @param newState The new view state to combine.
17674      * @return Returns a new integer reflecting the combination of the two
17675      * states.
17676      */
17677     public static int combineMeasuredStates(int curState, int newState) {
17678         return curState | newState;
17679     }
17680 
17681     /**
17682      * Version of {@link #resolveSizeAndState(int, int, int)}
17683      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
17684      */
17685     public static int resolveSize(int size, int measureSpec) {
17686         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
17687     }
17688 
17689     /**
17690      * Utility to reconcile a desired size and state, with constraints imposed
17691      * by a MeasureSpec.  Will take the desired size, unless a different size
17692      * is imposed by the constraints.  The returned value is a compound integer,
17693      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
17694      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
17695      * size is smaller than the size the view wants to be.
17696      *
17697      * @param size How big the view wants to be
17698      * @param measureSpec Constraints imposed by the parent
17699      * @return Size information bit mask as defined by
17700      * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17701      */
17702     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
17703         int result = size;
17704         int specMode = MeasureSpec.getMode(measureSpec);
17705         int specSize =  MeasureSpec.getSize(measureSpec);
17706         switch (specMode) {
17707         case MeasureSpec.UNSPECIFIED:
17708             result = size;
17709             break;
17710         case MeasureSpec.AT_MOST:
17711             if (specSize < size) {
17712                 result = specSize | MEASURED_STATE_TOO_SMALL;
17713             } else {
17714                 result = size;
17715             }
17716             break;
17717         case MeasureSpec.EXACTLY:
17718             result = specSize;
17719             break;
17720         }
17721         return result | (childMeasuredState&MEASURED_STATE_MASK);
17722     }
17723 
17724     /**
17725      * Utility to return a default size. Uses the supplied size if the
17726      * MeasureSpec imposed no constraints. Will get larger if allowed
17727      * by the MeasureSpec.
17728      *
17729      * @param size Default size for this view
17730      * @param measureSpec Constraints imposed by the parent
17731      * @return The size this view should be.
17732      */
17733     public static int getDefaultSize(int size, int measureSpec) {
17734         int result = size;
17735         int specMode = MeasureSpec.getMode(measureSpec);
17736         int specSize = MeasureSpec.getSize(measureSpec);
17737 
17738         switch (specMode) {
17739         case MeasureSpec.UNSPECIFIED:
17740             result = size;
17741             break;
17742         case MeasureSpec.AT_MOST:
17743         case MeasureSpec.EXACTLY:
17744             result = specSize;
17745             break;
17746         }
17747         return result;
17748     }
17749 
17750     /**
17751      * Returns the suggested minimum height that the view should use. This
17752      * returns the maximum of the view's minimum height
17753      * and the background's minimum height
17754      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
17755      * <p>
17756      * When being used in {@link #onMeasure(int, int)}, the caller should still
17757      * ensure the returned height is within the requirements of the parent.
17758      *
17759      * @return The suggested minimum height of the view.
17760      */
17761     protected int getSuggestedMinimumHeight() {
17762         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
17763 
17764     }
17765 
17766     /**
17767      * Returns the suggested minimum width that the view should use. This
17768      * returns the maximum of the view's minimum width)
17769      * and the background's minimum width
17770      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
17771      * <p>
17772      * When being used in {@link #onMeasure(int, int)}, the caller should still
17773      * ensure the returned width is within the requirements of the parent.
17774      *
17775      * @return The suggested minimum width of the view.
17776      */
17777     protected int getSuggestedMinimumWidth() {
17778         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
17779     }
17780 
17781     /**
17782      * Returns the minimum height of the view.
17783      *
17784      * @return the minimum height the view will try to be.
17785      *
17786      * @see #setMinimumHeight(int)
17787      *
17788      * @attr ref android.R.styleable#View_minHeight
17789      */
17790     public int getMinimumHeight() {
17791         return mMinHeight;
17792     }
17793 
17794     /**
17795      * Sets the minimum height of the view. It is not guaranteed the view will
17796      * be able to achieve this minimum height (for example, if its parent layout
17797      * constrains it with less available height).
17798      *
17799      * @param minHeight The minimum height the view will try to be.
17800      *
17801      * @see #getMinimumHeight()
17802      *
17803      * @attr ref android.R.styleable#View_minHeight
17804      */
17805     public void setMinimumHeight(int minHeight) {
17806         mMinHeight = minHeight;
17807         requestLayout();
17808     }
17809 
17810     /**
17811      * Returns the minimum width of the view.
17812      *
17813      * @return the minimum width the view will try to be.
17814      *
17815      * @see #setMinimumWidth(int)
17816      *
17817      * @attr ref android.R.styleable#View_minWidth
17818      */
17819     public int getMinimumWidth() {
17820         return mMinWidth;
17821     }
17822 
17823     /**
17824      * Sets the minimum width of the view. It is not guaranteed the view will
17825      * be able to achieve this minimum width (for example, if its parent layout
17826      * constrains it with less available width).
17827      *
17828      * @param minWidth The minimum width the view will try to be.
17829      *
17830      * @see #getMinimumWidth()
17831      *
17832      * @attr ref android.R.styleable#View_minWidth
17833      */
17834     public void setMinimumWidth(int minWidth) {
17835         mMinWidth = minWidth;
17836         requestLayout();
17837 
17838     }
17839 
17840     /**
17841      * Get the animation currently associated with this view.
17842      *
17843      * @return The animation that is currently playing or
17844      *         scheduled to play for this view.
17845      */
17846     public Animation getAnimation() {
17847         return mCurrentAnimation;
17848     }
17849 
17850     /**
17851      * Start the specified animation now.
17852      *
17853      * @param animation the animation to start now
17854      */
17855     public void startAnimation(Animation animation) {
17856         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
17857         setAnimation(animation);
17858         invalidateParentCaches();
17859         invalidate(true);
17860     }
17861 
17862     /**
17863      * Cancels any animations for this view.
17864      */
17865     public void clearAnimation() {
17866         if (mCurrentAnimation != null) {
17867             mCurrentAnimation.detach();
17868         }
17869         mCurrentAnimation = null;
17870         invalidateParentIfNeeded();
17871     }
17872 
17873     /**
17874      * Sets the next animation to play for this view.
17875      * If you want the animation to play immediately, use
17876      * {@link #startAnimation(android.view.animation.Animation)} instead.
17877      * This method provides allows fine-grained
17878      * control over the start time and invalidation, but you
17879      * must make sure that 1) the animation has a start time set, and
17880      * 2) the view's parent (which controls animations on its children)
17881      * will be invalidated when the animation is supposed to
17882      * start.
17883      *
17884      * @param animation The next animation, or null.
17885      */
17886     public void setAnimation(Animation animation) {
17887         mCurrentAnimation = animation;
17888 
17889         if (animation != null) {
17890             // If the screen is off assume the animation start time is now instead of
17891             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
17892             // would cause the animation to start when the screen turns back on
17893             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
17894                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
17895                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
17896             }
17897             animation.reset();
17898         }
17899     }
17900 
17901     /**
17902      * Invoked by a parent ViewGroup to notify the start of the animation
17903      * currently associated with this view. If you override this method,
17904      * always call super.onAnimationStart();
17905      *
17906      * @see #setAnimation(android.view.animation.Animation)
17907      * @see #getAnimation()
17908      */
17909     protected void onAnimationStart() {
17910         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
17911     }
17912 
17913     /**
17914      * Invoked by a parent ViewGroup to notify the end of the animation
17915      * currently associated with this view. If you override this method,
17916      * always call super.onAnimationEnd();
17917      *
17918      * @see #setAnimation(android.view.animation.Animation)
17919      * @see #getAnimation()
17920      */
17921     protected void onAnimationEnd() {
17922         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
17923     }
17924 
17925     /**
17926      * Invoked if there is a Transform that involves alpha. Subclass that can
17927      * draw themselves with the specified alpha should return true, and then
17928      * respect that alpha when their onDraw() is called. If this returns false
17929      * then the view may be redirected to draw into an offscreen buffer to
17930      * fulfill the request, which will look fine, but may be slower than if the
17931      * subclass handles it internally. The default implementation returns false.
17932      *
17933      * @param alpha The alpha (0..255) to apply to the view's drawing
17934      * @return true if the view can draw with the specified alpha.
17935      */
17936     protected boolean onSetAlpha(int alpha) {
17937         return false;
17938     }
17939 
17940     /**
17941      * This is used by the RootView to perform an optimization when
17942      * the view hierarchy contains one or several SurfaceView.
17943      * SurfaceView is always considered transparent, but its children are not,
17944      * therefore all View objects remove themselves from the global transparent
17945      * region (passed as a parameter to this function).
17946      *
17947      * @param region The transparent region for this ViewAncestor (window).
17948      *
17949      * @return Returns true if the effective visibility of the view at this
17950      * point is opaque, regardless of the transparent region; returns false
17951      * if it is possible for underlying windows to be seen behind the view.
17952      *
17953      * {@hide}
17954      */
17955     public boolean gatherTransparentRegion(Region region) {
17956         final AttachInfo attachInfo = mAttachInfo;
17957         if (region != null && attachInfo != null) {
17958             final int pflags = mPrivateFlags;
17959             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
17960                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
17961                 // remove it from the transparent region.
17962                 final int[] location = attachInfo.mTransparentLocation;
17963                 getLocationInWindow(location);
17964                 region.op(location[0], location[1], location[0] + mRight - mLeft,
17965                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
17966             } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
17967                     mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
17968                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
17969                 // exists, so we remove the background drawable's non-transparent
17970                 // parts from this transparent region.
17971                 applyDrawableToTransparentRegion(mBackground, region);
17972             }
17973         }
17974         return true;
17975     }
17976 
17977     /**
17978      * Play a sound effect for this view.
17979      *
17980      * <p>The framework will play sound effects for some built in actions, such as
17981      * clicking, but you may wish to play these effects in your widget,
17982      * for instance, for internal navigation.
17983      *
17984      * <p>The sound effect will only be played if sound effects are enabled by the user, and
17985      * {@link #isSoundEffectsEnabled()} is true.
17986      *
17987      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
17988      */
17989     public void playSoundEffect(int soundConstant) {
17990         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
17991             return;
17992         }
17993         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
17994     }
17995 
17996     /**
17997      * BZZZTT!!1!
17998      *
17999      * <p>Provide haptic feedback to the user for this view.
18000      *
18001      * <p>The framework will provide haptic feedback for some built in actions,
18002      * such as long presses, but you may wish to provide feedback for your
18003      * own widget.
18004      *
18005      * <p>The feedback will only be performed if
18006      * {@link #isHapticFeedbackEnabled()} is true.
18007      *
18008      * @param feedbackConstant One of the constants defined in
18009      * {@link HapticFeedbackConstants}
18010      */
18011     public boolean performHapticFeedback(int feedbackConstant) {
18012         return performHapticFeedback(feedbackConstant, 0);
18013     }
18014 
18015     /**
18016      * BZZZTT!!1!
18017      *
18018      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
18019      *
18020      * @param feedbackConstant One of the constants defined in
18021      * {@link HapticFeedbackConstants}
18022      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
18023      */
18024     public boolean performHapticFeedback(int feedbackConstant, int flags) {
18025         if (mAttachInfo == null) {
18026             return false;
18027         }
18028         //noinspection SimplifiableIfStatement
18029         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
18030                 && !isHapticFeedbackEnabled()) {
18031             return false;
18032         }
18033         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
18034                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
18035     }
18036 
18037     /**
18038      * Request that the visibility of the status bar or other screen/window
18039      * decorations be changed.
18040      *
18041      * <p>This method is used to put the over device UI into temporary modes
18042      * where the user's attention is focused more on the application content,
18043      * by dimming or hiding surrounding system affordances.  This is typically
18044      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
18045      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
18046      * to be placed behind the action bar (and with these flags other system
18047      * affordances) so that smooth transitions between hiding and showing them
18048      * can be done.
18049      *
18050      * <p>Two representative examples of the use of system UI visibility is
18051      * implementing a content browsing application (like a magazine reader)
18052      * and a video playing application.
18053      *
18054      * <p>The first code shows a typical implementation of a View in a content
18055      * browsing application.  In this implementation, the application goes
18056      * into a content-oriented mode by hiding the status bar and action bar,
18057      * and putting the navigation elements into lights out mode.  The user can
18058      * then interact with content while in this mode.  Such an application should
18059      * provide an easy way for the user to toggle out of the mode (such as to
18060      * check information in the status bar or access notifications).  In the
18061      * implementation here, this is done simply by tapping on the content.
18062      *
18063      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
18064      *      content}
18065      *
18066      * <p>This second code sample shows a typical implementation of a View
18067      * in a video playing application.  In this situation, while the video is
18068      * playing the application would like to go into a complete full-screen mode,
18069      * to use as much of the display as possible for the video.  When in this state
18070      * the user can not interact with the application; the system intercepts
18071      * touching on the screen to pop the UI out of full screen mode.  See
18072      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
18073      *
18074      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
18075      *      content}
18076      *
18077      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18078      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18079      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18080      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18081      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18082      */
18083     public void setSystemUiVisibility(int visibility) {
18084         if (visibility != mSystemUiVisibility) {
18085             mSystemUiVisibility = visibility;
18086             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18087                 mParent.recomputeViewAttributes(this);
18088             }
18089         }
18090     }
18091 
18092     /**
18093      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
18094      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18095      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18096      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18097      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18098      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18099      */
18100     public int getSystemUiVisibility() {
18101         return mSystemUiVisibility;
18102     }
18103 
18104     /**
18105      * Returns the current system UI visibility that is currently set for
18106      * the entire window.  This is the combination of the
18107      * {@link #setSystemUiVisibility(int)} values supplied by all of the
18108      * views in the window.
18109      */
18110     public int getWindowSystemUiVisibility() {
18111         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
18112     }
18113 
18114     /**
18115      * Override to find out when the window's requested system UI visibility
18116      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
18117      * This is different from the callbacks received through
18118      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
18119      * in that this is only telling you about the local request of the window,
18120      * not the actual values applied by the system.
18121      */
18122     public void onWindowSystemUiVisibilityChanged(int visible) {
18123     }
18124 
18125     /**
18126      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
18127      * the view hierarchy.
18128      */
18129     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
18130         onWindowSystemUiVisibilityChanged(visible);
18131     }
18132 
18133     /**
18134      * Set a listener to receive callbacks when the visibility of the system bar changes.
18135      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
18136      */
18137     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
18138         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
18139         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18140             mParent.recomputeViewAttributes(this);
18141         }
18142     }
18143 
18144     /**
18145      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
18146      * the view hierarchy.
18147      */
18148     public void dispatchSystemUiVisibilityChanged(int visibility) {
18149         ListenerInfo li = mListenerInfo;
18150         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
18151             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
18152                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
18153         }
18154     }
18155 
18156     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
18157         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
18158         if (val != mSystemUiVisibility) {
18159             setSystemUiVisibility(val);
18160             return true;
18161         }
18162         return false;
18163     }
18164 
18165     /** @hide */
18166     public void setDisabledSystemUiVisibility(int flags) {
18167         if (mAttachInfo != null) {
18168             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
18169                 mAttachInfo.mDisabledSystemUiVisibility = flags;
18170                 if (mParent != null) {
18171                     mParent.recomputeViewAttributes(this);
18172                 }
18173             }
18174         }
18175     }
18176 
18177     /**
18178      * Creates an image that the system displays during the drag and drop
18179      * operation. This is called a &quot;drag shadow&quot;. The default implementation
18180      * for a DragShadowBuilder based on a View returns an image that has exactly the same
18181      * appearance as the given View. The default also positions the center of the drag shadow
18182      * directly under the touch point. If no View is provided (the constructor with no parameters
18183      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
18184      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
18185      * default is an invisible drag shadow.
18186      * <p>
18187      * You are not required to use the View you provide to the constructor as the basis of the
18188      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
18189      * anything you want as the drag shadow.
18190      * </p>
18191      * <p>
18192      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
18193      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
18194      *  size and position of the drag shadow. It uses this data to construct a
18195      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
18196      *  so that your application can draw the shadow image in the Canvas.
18197      * </p>
18198      *
18199      * <div class="special reference">
18200      * <h3>Developer Guides</h3>
18201      * <p>For a guide to implementing drag and drop features, read the
18202      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18203      * </div>
18204      */
18205     public static class DragShadowBuilder {
18206         private final WeakReference<View> mView;
18207 
18208         /**
18209          * Constructs a shadow image builder based on a View. By default, the resulting drag
18210          * shadow will have the same appearance and dimensions as the View, with the touch point
18211          * over the center of the View.
18212          * @param view A View. Any View in scope can be used.
18213          */
18214         public DragShadowBuilder(View view) {
18215             mView = new WeakReference<View>(view);
18216         }
18217 
18218         /**
18219          * Construct a shadow builder object with no associated View.  This
18220          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18221          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18222          * to supply the drag shadow's dimensions and appearance without
18223          * reference to any View object. If they are not overridden, then the result is an
18224          * invisible drag shadow.
18225          */
18226         public DragShadowBuilder() {
18227             mView = new WeakReference<View>(null);
18228         }
18229 
18230         /**
18231          * Returns the View object that had been passed to the
18232          * {@link #View.DragShadowBuilder(View)}
18233          * constructor.  If that View parameter was {@code null} or if the
18234          * {@link #View.DragShadowBuilder()}
18235          * constructor was used to instantiate the builder object, this method will return
18236          * null.
18237          *
18238          * @return The View object associate with this builder object.
18239          */
18240         @SuppressWarnings({"JavadocReference"})
18241         final public View getView() {
18242             return mView.get();
18243         }
18244 
18245         /**
18246          * Provides the metrics for the shadow image. These include the dimensions of
18247          * the shadow image, and the point within that shadow that should
18248          * be centered under the touch location while dragging.
18249          * <p>
18250          * The default implementation sets the dimensions of the shadow to be the
18251          * same as the dimensions of the View itself and centers the shadow under
18252          * the touch point.
18253          * </p>
18254          *
18255          * @param shadowSize A {@link android.graphics.Point} containing the width and height
18256          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18257          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18258          * image.
18259          *
18260          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18261          * shadow image that should be underneath the touch point during the drag and drop
18262          * operation. Your application must set {@link android.graphics.Point#x} to the
18263          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18264          */
18265         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18266             final View view = mView.get();
18267             if (view != null) {
18268                 shadowSize.set(view.getWidth(), view.getHeight());
18269                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18270             } else {
18271                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
18272             }
18273         }
18274 
18275         /**
18276          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
18277          * based on the dimensions it received from the
18278          * {@link #onProvideShadowMetrics(Point, Point)} callback.
18279          *
18280          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
18281          */
18282         public void onDrawShadow(Canvas canvas) {
18283             final View view = mView.get();
18284             if (view != null) {
18285                 view.draw(canvas);
18286             } else {
18287                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
18288             }
18289         }
18290     }
18291 
18292     /**
18293      * Starts a drag and drop operation. When your application calls this method, it passes a
18294      * {@link android.view.View.DragShadowBuilder} object to the system. The
18295      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
18296      * to get metrics for the drag shadow, and then calls the object's
18297      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
18298      * <p>
18299      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
18300      *  drag events to all the View objects in your application that are currently visible. It does
18301      *  this either by calling the View object's drag listener (an implementation of
18302      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
18303      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
18304      *  Both are passed a {@link android.view.DragEvent} object that has a
18305      *  {@link android.view.DragEvent#getAction()} value of
18306      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
18307      * </p>
18308      * <p>
18309      * Your application can invoke startDrag() on any attached View object. The View object does not
18310      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
18311      * be related to the View the user selected for dragging.
18312      * </p>
18313      * @param data A {@link android.content.ClipData} object pointing to the data to be
18314      * transferred by the drag and drop operation.
18315      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
18316      * drag shadow.
18317      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
18318      * drop operation. This Object is put into every DragEvent object sent by the system during the
18319      * current drag.
18320      * <p>
18321      * myLocalState is a lightweight mechanism for the sending information from the dragged View
18322      * to the target Views. For example, it can contain flags that differentiate between a
18323      * a copy operation and a move operation.
18324      * </p>
18325      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
18326      * so the parameter should be set to 0.
18327      * @return {@code true} if the method completes successfully, or
18328      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
18329      * do a drag, and so no drag operation is in progress.
18330      */
18331     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
18332             Object myLocalState, int flags) {
18333         if (ViewDebug.DEBUG_DRAG) {
18334             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
18335         }
18336         boolean okay = false;
18337 
18338         Point shadowSize = new Point();
18339         Point shadowTouchPoint = new Point();
18340         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
18341 
18342         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
18343                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
18344             throw new IllegalStateException("Drag shadow dimensions must not be negative");
18345         }
18346 
18347         if (ViewDebug.DEBUG_DRAG) {
18348             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
18349                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
18350         }
18351         Surface surface = new Surface();
18352         try {
18353             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
18354                     flags, shadowSize.x, shadowSize.y, surface);
18355             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
18356                     + " surface=" + surface);
18357             if (token != null) {
18358                 Canvas canvas = surface.lockCanvas(null);
18359                 try {
18360                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
18361                     shadowBuilder.onDrawShadow(canvas);
18362                 } finally {
18363                     surface.unlockCanvasAndPost(canvas);
18364                 }
18365 
18366                 final ViewRootImpl root = getViewRootImpl();
18367 
18368                 // Cache the local state object for delivery with DragEvents
18369                 root.setLocalDragState(myLocalState);
18370 
18371                 // repurpose 'shadowSize' for the last touch point
18372                 root.getLastTouchPoint(shadowSize);
18373 
18374                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
18375                         shadowSize.x, shadowSize.y,
18376                         shadowTouchPoint.x, shadowTouchPoint.y, data);
18377                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
18378 
18379                 // Off and running!  Release our local surface instance; the drag
18380                 // shadow surface is now managed by the system process.
18381                 surface.release();
18382             }
18383         } catch (Exception e) {
18384             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
18385             surface.destroy();
18386         }
18387 
18388         return okay;
18389     }
18390 
18391     /**
18392      * Handles drag events sent by the system following a call to
18393      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
18394      *<p>
18395      * When the system calls this method, it passes a
18396      * {@link android.view.DragEvent} object. A call to
18397      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
18398      * in DragEvent. The method uses these to determine what is happening in the drag and drop
18399      * operation.
18400      * @param event The {@link android.view.DragEvent} sent by the system.
18401      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
18402      * in DragEvent, indicating the type of drag event represented by this object.
18403      * @return {@code true} if the method was successful, otherwise {@code false}.
18404      * <p>
18405      *  The method should return {@code true} in response to an action type of
18406      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
18407      *  operation.
18408      * </p>
18409      * <p>
18410      *  The method should also return {@code true} in response to an action type of
18411      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
18412      *  {@code false} if it didn't.
18413      * </p>
18414      */
18415     public boolean onDragEvent(DragEvent event) {
18416         return false;
18417     }
18418 
18419     /**
18420      * Detects if this View is enabled and has a drag event listener.
18421      * If both are true, then it calls the drag event listener with the
18422      * {@link android.view.DragEvent} it received. If the drag event listener returns
18423      * {@code true}, then dispatchDragEvent() returns {@code true}.
18424      * <p>
18425      * For all other cases, the method calls the
18426      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
18427      * method and returns its result.
18428      * </p>
18429      * <p>
18430      * This ensures that a drag event is always consumed, even if the View does not have a drag
18431      * event listener. However, if the View has a listener and the listener returns true, then
18432      * onDragEvent() is not called.
18433      * </p>
18434      */
18435     public boolean dispatchDragEvent(DragEvent event) {
18436         ListenerInfo li = mListenerInfo;
18437         //noinspection SimplifiableIfStatement
18438         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
18439                 && li.mOnDragListener.onDrag(this, event)) {
18440             return true;
18441         }
18442         return onDragEvent(event);
18443     }
18444 
18445     boolean canAcceptDrag() {
18446         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
18447     }
18448 
18449     /**
18450      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
18451      * it is ever exposed at all.
18452      * @hide
18453      */
18454     public void onCloseSystemDialogs(String reason) {
18455     }
18456 
18457     /**
18458      * Given a Drawable whose bounds have been set to draw into this view,
18459      * update a Region being computed for
18460      * {@link #gatherTransparentRegion(android.graphics.Region)} so
18461      * that any non-transparent parts of the Drawable are removed from the
18462      * given transparent region.
18463      *
18464      * @param dr The Drawable whose transparency is to be applied to the region.
18465      * @param region A Region holding the current transparency information,
18466      * where any parts of the region that are set are considered to be
18467      * transparent.  On return, this region will be modified to have the
18468      * transparency information reduced by the corresponding parts of the
18469      * Drawable that are not transparent.
18470      * {@hide}
18471      */
18472     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
18473         if (DBG) {
18474             Log.i("View", "Getting transparent region for: " + this);
18475         }
18476         final Region r = dr.getTransparentRegion();
18477         final Rect db = dr.getBounds();
18478         final AttachInfo attachInfo = mAttachInfo;
18479         if (r != null && attachInfo != null) {
18480             final int w = getRight()-getLeft();
18481             final int h = getBottom()-getTop();
18482             if (db.left > 0) {
18483                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
18484                 r.op(0, 0, db.left, h, Region.Op.UNION);
18485             }
18486             if (db.right < w) {
18487                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
18488                 r.op(db.right, 0, w, h, Region.Op.UNION);
18489             }
18490             if (db.top > 0) {
18491                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
18492                 r.op(0, 0, w, db.top, Region.Op.UNION);
18493             }
18494             if (db.bottom < h) {
18495                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
18496                 r.op(0, db.bottom, w, h, Region.Op.UNION);
18497             }
18498             final int[] location = attachInfo.mTransparentLocation;
18499             getLocationInWindow(location);
18500             r.translate(location[0], location[1]);
18501             region.op(r, Region.Op.INTERSECT);
18502         } else {
18503             region.op(db, Region.Op.DIFFERENCE);
18504         }
18505     }
18506 
18507     private void checkForLongClick(int delayOffset) {
18508         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
18509             mHasPerformedLongPress = false;
18510 
18511             if (mPendingCheckForLongPress == null) {
18512                 mPendingCheckForLongPress = new CheckForLongPress();
18513             }
18514             mPendingCheckForLongPress.rememberWindowAttachCount();
18515             postDelayed(mPendingCheckForLongPress,
18516                     ViewConfiguration.getLongPressTimeout() - delayOffset);
18517         }
18518     }
18519 
18520     /**
18521      * Inflate a view from an XML resource.  This convenience method wraps the {@link
18522      * LayoutInflater} class, which provides a full range of options for view inflation.
18523      *
18524      * @param context The Context object for your activity or application.
18525      * @param resource The resource ID to inflate
18526      * @param root A view group that will be the parent.  Used to properly inflate the
18527      * layout_* parameters.
18528      * @see LayoutInflater
18529      */
18530     public static View inflate(Context context, int resource, ViewGroup root) {
18531         LayoutInflater factory = LayoutInflater.from(context);
18532         return factory.inflate(resource, root);
18533     }
18534 
18535     /**
18536      * Scroll the view with standard behavior for scrolling beyond the normal
18537      * content boundaries. Views that call this method should override
18538      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
18539      * results of an over-scroll operation.
18540      *
18541      * Views can use this method to handle any touch or fling-based scrolling.
18542      *
18543      * @param deltaX Change in X in pixels
18544      * @param deltaY Change in Y in pixels
18545      * @param scrollX Current X scroll value in pixels before applying deltaX
18546      * @param scrollY Current Y scroll value in pixels before applying deltaY
18547      * @param scrollRangeX Maximum content scroll range along the X axis
18548      * @param scrollRangeY Maximum content scroll range along the Y axis
18549      * @param maxOverScrollX Number of pixels to overscroll by in either direction
18550      *          along the X axis.
18551      * @param maxOverScrollY Number of pixels to overscroll by in either direction
18552      *          along the Y axis.
18553      * @param isTouchEvent true if this scroll operation is the result of a touch event.
18554      * @return true if scrolling was clamped to an over-scroll boundary along either
18555      *          axis, false otherwise.
18556      */
18557     @SuppressWarnings({"UnusedParameters"})
18558     protected boolean overScrollBy(int deltaX, int deltaY,
18559             int scrollX, int scrollY,
18560             int scrollRangeX, int scrollRangeY,
18561             int maxOverScrollX, int maxOverScrollY,
18562             boolean isTouchEvent) {
18563         final int overScrollMode = mOverScrollMode;
18564         final boolean canScrollHorizontal =
18565                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
18566         final boolean canScrollVertical =
18567                 computeVerticalScrollRange() > computeVerticalScrollExtent();
18568         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
18569                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
18570         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
18571                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
18572 
18573         int newScrollX = scrollX + deltaX;
18574         if (!overScrollHorizontal) {
18575             maxOverScrollX = 0;
18576         }
18577 
18578         int newScrollY = scrollY + deltaY;
18579         if (!overScrollVertical) {
18580             maxOverScrollY = 0;
18581         }
18582 
18583         // Clamp values if at the limits and record
18584         final int left = -maxOverScrollX;
18585         final int right = maxOverScrollX + scrollRangeX;
18586         final int top = -maxOverScrollY;
18587         final int bottom = maxOverScrollY + scrollRangeY;
18588 
18589         boolean clampedX = false;
18590         if (newScrollX > right) {
18591             newScrollX = right;
18592             clampedX = true;
18593         } else if (newScrollX < left) {
18594             newScrollX = left;
18595             clampedX = true;
18596         }
18597 
18598         boolean clampedY = false;
18599         if (newScrollY > bottom) {
18600             newScrollY = bottom;
18601             clampedY = true;
18602         } else if (newScrollY < top) {
18603             newScrollY = top;
18604             clampedY = true;
18605         }
18606 
18607         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
18608 
18609         return clampedX || clampedY;
18610     }
18611 
18612     /**
18613      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
18614      * respond to the results of an over-scroll operation.
18615      *
18616      * @param scrollX New X scroll value in pixels
18617      * @param scrollY New Y scroll value in pixels
18618      * @param clampedX True if scrollX was clamped to an over-scroll boundary
18619      * @param clampedY True if scrollY was clamped to an over-scroll boundary
18620      */
18621     protected void onOverScrolled(int scrollX, int scrollY,
18622             boolean clampedX, boolean clampedY) {
18623         // Intentionally empty.
18624     }
18625 
18626     /**
18627      * Returns the over-scroll mode for this view. The result will be
18628      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18629      * (allow over-scrolling only if the view content is larger than the container),
18630      * or {@link #OVER_SCROLL_NEVER}.
18631      *
18632      * @return This view's over-scroll mode.
18633      */
18634     public int getOverScrollMode() {
18635         return mOverScrollMode;
18636     }
18637 
18638     /**
18639      * Set the over-scroll mode for this view. Valid over-scroll modes are
18640      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18641      * (allow over-scrolling only if the view content is larger than the container),
18642      * or {@link #OVER_SCROLL_NEVER}.
18643      *
18644      * Setting the over-scroll mode of a view will have an effect only if the
18645      * view is capable of scrolling.
18646      *
18647      * @param overScrollMode The new over-scroll mode for this view.
18648      */
18649     public void setOverScrollMode(int overScrollMode) {
18650         if (overScrollMode != OVER_SCROLL_ALWAYS &&
18651                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
18652                 overScrollMode != OVER_SCROLL_NEVER) {
18653             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
18654         }
18655         mOverScrollMode = overScrollMode;
18656     }
18657 
18658     /**
18659      * Enable or disable nested scrolling for this view.
18660      *
18661      * <p>If this property is set to true the view will be permitted to initiate nested
18662      * scrolling operations with a compatible parent view in the current hierarchy. If this
18663      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
18664      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
18665      * the nested scroll.</p>
18666      *
18667      * @param enabled true to enable nested scrolling, false to disable
18668      *
18669      * @see #isNestedScrollingEnabled()
18670      */
18671     public void setNestedScrollingEnabled(boolean enabled) {
18672         if (enabled) {
18673             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
18674         } else {
18675             stopNestedScroll();
18676             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
18677         }
18678     }
18679 
18680     /**
18681      * Returns true if nested scrolling is enabled for this view.
18682      *
18683      * <p>If nested scrolling is enabled and this View class implementation supports it,
18684      * this view will act as a nested scrolling child view when applicable, forwarding data
18685      * about the scroll operation in progress to a compatible and cooperating nested scrolling
18686      * parent.</p>
18687      *
18688      * @return true if nested scrolling is enabled
18689      *
18690      * @see #setNestedScrollingEnabled(boolean)
18691      */
18692     public boolean isNestedScrollingEnabled() {
18693         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
18694                 PFLAG3_NESTED_SCROLLING_ENABLED;
18695     }
18696 
18697     /**
18698      * Begin a nestable scroll operation along the given axes.
18699      *
18700      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
18701      *
18702      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
18703      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
18704      * In the case of touch scrolling the nested scroll will be terminated automatically in
18705      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
18706      * In the event of programmatic scrolling the caller must explicitly call
18707      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
18708      *
18709      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
18710      * If it returns false the caller may ignore the rest of this contract until the next scroll.
18711      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
18712      *
18713      * <p>At each incremental step of the scroll the caller should invoke
18714      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
18715      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
18716      * parent at least partially consumed the scroll and the caller should adjust the amount it
18717      * scrolls by.</p>
18718      *
18719      * <p>After applying the remainder of the scroll delta the caller should invoke
18720      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
18721      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
18722      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
18723      * </p>
18724      *
18725      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
18726      *             {@link #SCROLL_AXIS_VERTICAL}.
18727      * @return true if a cooperative parent was found and nested scrolling has been enabled for
18728      *         the current gesture.
18729      *
18730      * @see #stopNestedScroll()
18731      * @see #dispatchNestedPreScroll(int, int, int[], int[])
18732      * @see #dispatchNestedScroll(int, int, int, int, int[])
18733      */
18734     public boolean startNestedScroll(int axes) {
18735         if (hasNestedScrollingParent()) {
18736             // Already in progress
18737             return true;
18738         }
18739         if (isNestedScrollingEnabled()) {
18740             ViewParent p = getParent();
18741             View child = this;
18742             while (p != null) {
18743                 try {
18744                     if (p.onStartNestedScroll(child, this, axes)) {
18745                         mNestedScrollingParent = p;
18746                         p.onNestedScrollAccepted(child, this, axes);
18747                         return true;
18748                     }
18749                 } catch (AbstractMethodError e) {
18750                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
18751                             "method onStartNestedScroll", e);
18752                     // Allow the search upward to continue
18753                 }
18754                 if (p instanceof View) {
18755                     child = (View) p;
18756                 }
18757                 p = p.getParent();
18758             }
18759         }
18760         return false;
18761     }
18762 
18763     /**
18764      * Stop a nested scroll in progress.
18765      *
18766      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
18767      *
18768      * @see #startNestedScroll(int)
18769      */
18770     public void stopNestedScroll() {
18771         if (mNestedScrollingParent != null) {
18772             mNestedScrollingParent.onStopNestedScroll(this);
18773             mNestedScrollingParent = null;
18774         }
18775     }
18776 
18777     /**
18778      * Returns true if this view has a nested scrolling parent.
18779      *
18780      * <p>The presence of a nested scrolling parent indicates that this view has initiated
18781      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
18782      *
18783      * @return whether this view has a nested scrolling parent
18784      */
18785     public boolean hasNestedScrollingParent() {
18786         return mNestedScrollingParent != null;
18787     }
18788 
18789     /**
18790      * Dispatch one step of a nested scroll in progress.
18791      *
18792      * <p>Implementations of views that support nested scrolling should call this to report
18793      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
18794      * is not currently in progress or nested scrolling is not
18795      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
18796      *
18797      * <p>Compatible View implementations should also call
18798      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
18799      * consuming a component of the scroll event themselves.</p>
18800      *
18801      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
18802      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
18803      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
18804      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
18805      * @param offsetInWindow Optional. If not null, on return this will contain the offset
18806      *                       in local view coordinates of this view from before this operation
18807      *                       to after it completes. View implementations may use this to adjust
18808      *                       expected input coordinate tracking.
18809      * @return true if the event was dispatched, false if it could not be dispatched.
18810      * @see #dispatchNestedPreScroll(int, int, int[], int[])
18811      */
18812     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
18813             int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
18814         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18815             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
18816                 int startX = 0;
18817                 int startY = 0;
18818                 if (offsetInWindow != null) {
18819                     getLocationInWindow(offsetInWindow);
18820                     startX = offsetInWindow[0];
18821                     startY = offsetInWindow[1];
18822                 }
18823 
18824                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
18825                         dxUnconsumed, dyUnconsumed);
18826 
18827                 if (offsetInWindow != null) {
18828                     getLocationInWindow(offsetInWindow);
18829                     offsetInWindow[0] -= startX;
18830                     offsetInWindow[1] -= startY;
18831                 }
18832                 return true;
18833             } else if (offsetInWindow != null) {
18834                 // No motion, no dispatch. Keep offsetInWindow up to date.
18835                 offsetInWindow[0] = 0;
18836                 offsetInWindow[1] = 0;
18837             }
18838         }
18839         return false;
18840     }
18841 
18842     /**
18843      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
18844      *
18845      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
18846      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
18847      * scrolling operation to consume some or all of the scroll operation before the child view
18848      * consumes it.</p>
18849      *
18850      * @param dx Horizontal scroll distance in pixels
18851      * @param dy Vertical scroll distance in pixels
18852      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
18853      *                 and consumed[1] the consumed dy.
18854      * @param offsetInWindow Optional. If not null, on return this will contain the offset
18855      *                       in local view coordinates of this view from before this operation
18856      *                       to after it completes. View implementations may use this to adjust
18857      *                       expected input coordinate tracking.
18858      * @return true if the parent consumed some or all of the scroll delta
18859      * @see #dispatchNestedScroll(int, int, int, int, int[])
18860      */
18861     public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
18862         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18863             if (dx != 0 || dy != 0) {
18864                 int startX = 0;
18865                 int startY = 0;
18866                 if (offsetInWindow != null) {
18867                     getLocationInWindow(offsetInWindow);
18868                     startX = offsetInWindow[0];
18869                     startY = offsetInWindow[1];
18870                 }
18871 
18872                 if (consumed == null) {
18873                     if (mTempNestedScrollConsumed == null) {
18874                         mTempNestedScrollConsumed = new int[2];
18875                     }
18876                     consumed = mTempNestedScrollConsumed;
18877                 }
18878                 consumed[0] = 0;
18879                 consumed[1] = 0;
18880                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
18881 
18882                 if (offsetInWindow != null) {
18883                     getLocationInWindow(offsetInWindow);
18884                     offsetInWindow[0] -= startX;
18885                     offsetInWindow[1] -= startY;
18886                 }
18887                 return consumed[0] != 0 || consumed[1] != 0;
18888             } else if (offsetInWindow != null) {
18889                 offsetInWindow[0] = 0;
18890                 offsetInWindow[1] = 0;
18891             }
18892         }
18893         return false;
18894     }
18895 
18896     /**
18897      * Dispatch a fling to a nested scrolling parent.
18898      *
18899      * <p>This method should be used to indicate that a nested scrolling child has detected
18900      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
18901      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
18902      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
18903      * along a scrollable axis.</p>
18904      *
18905      * <p>If a nested scrolling child view would normally fling but it is at the edge of
18906      * its own content, it can use this method to delegate the fling to its nested scrolling
18907      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
18908      *
18909      * @param velocityX Horizontal fling velocity in pixels per second
18910      * @param velocityY Vertical fling velocity in pixels per second
18911      * @param consumed true if the child consumed the fling, false otherwise
18912      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
18913      */
18914     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
18915         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18916             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
18917         }
18918         return false;
18919     }
18920 
18921     /**
18922      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
18923      *
18924      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
18925      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
18926      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
18927      * before the child view consumes it. If this method returns <code>true</code>, a nested
18928      * parent view consumed the fling and this view should not scroll as a result.</p>
18929      *
18930      * <p>For a better user experience, only one view in a nested scrolling chain should consume
18931      * the fling at a time. If a parent view consumed the fling this method will return false.
18932      * Custom view implementations should account for this in two ways:</p>
18933      *
18934      * <ul>
18935      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
18936      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
18937      *     position regardless.</li>
18938      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
18939      *     even to settle back to a valid idle position.</li>
18940      * </ul>
18941      *
18942      * <p>Views should also not offer fling velocities to nested parent views along an axis
18943      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
18944      * should not offer a horizontal fling velocity to its parents since scrolling along that
18945      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
18946      *
18947      * @param velocityX Horizontal fling velocity in pixels per second
18948      * @param velocityY Vertical fling velocity in pixels per second
18949      * @return true if a nested scrolling parent consumed the fling
18950      */
18951     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
18952         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18953             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
18954         }
18955         return false;
18956     }
18957 
18958     /**
18959      * Gets a scale factor that determines the distance the view should scroll
18960      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
18961      * @return The vertical scroll scale factor.
18962      * @hide
18963      */
18964     protected float getVerticalScrollFactor() {
18965         if (mVerticalScrollFactor == 0) {
18966             TypedValue outValue = new TypedValue();
18967             if (!mContext.getTheme().resolveAttribute(
18968                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
18969                 throw new IllegalStateException(
18970                         "Expected theme to define listPreferredItemHeight.");
18971             }
18972             mVerticalScrollFactor = outValue.getDimension(
18973                     mContext.getResources().getDisplayMetrics());
18974         }
18975         return mVerticalScrollFactor;
18976     }
18977 
18978     /**
18979      * Gets a scale factor that determines the distance the view should scroll
18980      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
18981      * @return The horizontal scroll scale factor.
18982      * @hide
18983      */
18984     protected float getHorizontalScrollFactor() {
18985         // TODO: Should use something else.
18986         return getVerticalScrollFactor();
18987     }
18988 
18989     /**
18990      * Return the value specifying the text direction or policy that was set with
18991      * {@link #setTextDirection(int)}.
18992      *
18993      * @return the defined text direction. It can be one of:
18994      *
18995      * {@link #TEXT_DIRECTION_INHERIT},
18996      * {@link #TEXT_DIRECTION_FIRST_STRONG}
18997      * {@link #TEXT_DIRECTION_ANY_RTL},
18998      * {@link #TEXT_DIRECTION_LTR},
18999      * {@link #TEXT_DIRECTION_RTL},
19000      * {@link #TEXT_DIRECTION_LOCALE}
19001      *
19002      * @attr ref android.R.styleable#View_textDirection
19003      *
19004      * @hide
19005      */
19006     @ViewDebug.ExportedProperty(category = "text", mapping = {
19007             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19008             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19009             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19010             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19011             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19012             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19013     })
19014     public int getRawTextDirection() {
19015         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
19016     }
19017 
19018     /**
19019      * Set the text direction.
19020      *
19021      * @param textDirection the direction to set. Should be one of:
19022      *
19023      * {@link #TEXT_DIRECTION_INHERIT},
19024      * {@link #TEXT_DIRECTION_FIRST_STRONG}
19025      * {@link #TEXT_DIRECTION_ANY_RTL},
19026      * {@link #TEXT_DIRECTION_LTR},
19027      * {@link #TEXT_DIRECTION_RTL},
19028      * {@link #TEXT_DIRECTION_LOCALE}
19029      *
19030      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
19031      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
19032      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
19033      *
19034      * @attr ref android.R.styleable#View_textDirection
19035      */
19036     public void setTextDirection(int textDirection) {
19037         if (getRawTextDirection() != textDirection) {
19038             // Reset the current text direction and the resolved one
19039             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
19040             resetResolvedTextDirection();
19041             // Set the new text direction
19042             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
19043             // Do resolution
19044             resolveTextDirection();
19045             // Notify change
19046             onRtlPropertiesChanged(getLayoutDirection());
19047             // Refresh
19048             requestLayout();
19049             invalidate(true);
19050         }
19051     }
19052 
19053     /**
19054      * Return the resolved text direction.
19055      *
19056      * @return the resolved text direction. Returns one of:
19057      *
19058      * {@link #TEXT_DIRECTION_FIRST_STRONG}
19059      * {@link #TEXT_DIRECTION_ANY_RTL},
19060      * {@link #TEXT_DIRECTION_LTR},
19061      * {@link #TEXT_DIRECTION_RTL},
19062      * {@link #TEXT_DIRECTION_LOCALE}
19063      *
19064      * @attr ref android.R.styleable#View_textDirection
19065      */
19066     @ViewDebug.ExportedProperty(category = "text", mapping = {
19067             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19068             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19069             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19070             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19071             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19072             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19073     })
19074     public int getTextDirection() {
19075         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
19076     }
19077 
19078     /**
19079      * Resolve the text direction.
19080      *
19081      * @return true if resolution has been done, false otherwise.
19082      *
19083      * @hide
19084      */
19085     public boolean resolveTextDirection() {
19086         // Reset any previous text direction resolution
19087         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19088 
19089         if (hasRtlSupport()) {
19090             // Set resolved text direction flag depending on text direction flag
19091             final int textDirection = getRawTextDirection();
19092             switch(textDirection) {
19093                 case TEXT_DIRECTION_INHERIT:
19094                     if (!canResolveTextDirection()) {
19095                         // We cannot do the resolution if there is no parent, so use the default one
19096                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19097                         // Resolution will need to happen again later
19098                         return false;
19099                     }
19100 
19101                     // Parent has not yet resolved, so we still return the default
19102                     try {
19103                         if (!mParent.isTextDirectionResolved()) {
19104                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19105                             // Resolution will need to happen again later
19106                             return false;
19107                         }
19108                     } catch (AbstractMethodError e) {
19109                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19110                                 " does not fully implement ViewParent", e);
19111                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
19112                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19113                         return true;
19114                     }
19115 
19116                     // Set current resolved direction to the same value as the parent's one
19117                     int parentResolvedDirection;
19118                     try {
19119                         parentResolvedDirection = mParent.getTextDirection();
19120                     } catch (AbstractMethodError e) {
19121                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19122                                 " does not fully implement ViewParent", e);
19123                         parentResolvedDirection = TEXT_DIRECTION_LTR;
19124                     }
19125                     switch (parentResolvedDirection) {
19126                         case TEXT_DIRECTION_FIRST_STRONG:
19127                         case TEXT_DIRECTION_ANY_RTL:
19128                         case TEXT_DIRECTION_LTR:
19129                         case TEXT_DIRECTION_RTL:
19130                         case TEXT_DIRECTION_LOCALE:
19131                             mPrivateFlags2 |=
19132                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19133                             break;
19134                         default:
19135                             // Default resolved direction is "first strong" heuristic
19136                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19137                     }
19138                     break;
19139                 case TEXT_DIRECTION_FIRST_STRONG:
19140                 case TEXT_DIRECTION_ANY_RTL:
19141                 case TEXT_DIRECTION_LTR:
19142                 case TEXT_DIRECTION_RTL:
19143                 case TEXT_DIRECTION_LOCALE:
19144                     // Resolved direction is the same as text direction
19145                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19146                     break;
19147                 default:
19148                     // Default resolved direction is "first strong" heuristic
19149                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19150             }
19151         } else {
19152             // Default resolved direction is "first strong" heuristic
19153             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19154         }
19155 
19156         // Set to resolved
19157         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
19158         return true;
19159     }
19160 
19161     /**
19162      * Check if text direction resolution can be done.
19163      *
19164      * @return true if text direction resolution can be done otherwise return false.
19165      */
19166     public boolean canResolveTextDirection() {
19167         switch (getRawTextDirection()) {
19168             case TEXT_DIRECTION_INHERIT:
19169                 if (mParent != null) {
19170                     try {
19171                         return mParent.canResolveTextDirection();
19172                     } catch (AbstractMethodError e) {
19173                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19174                                 " does not fully implement ViewParent", e);
19175                     }
19176                 }
19177                 return false;
19178 
19179             default:
19180                 return true;
19181         }
19182     }
19183 
19184     /**
19185      * Reset resolved text direction. Text direction will be resolved during a call to
19186      * {@link #onMeasure(int, int)}.
19187      *
19188      * @hide
19189      */
19190     public void resetResolvedTextDirection() {
19191         // Reset any previous text direction resolution
19192         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19193         // Set to default value
19194         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19195     }
19196 
19197     /**
19198      * @return true if text direction is inherited.
19199      *
19200      * @hide
19201      */
19202     public boolean isTextDirectionInherited() {
19203         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19204     }
19205 
19206     /**
19207      * @return true if text direction is resolved.
19208      */
19209     public boolean isTextDirectionResolved() {
19210         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19211     }
19212 
19213     /**
19214      * Return the value specifying the text alignment or policy that was set with
19215      * {@link #setTextAlignment(int)}.
19216      *
19217      * @return the defined text alignment. It can be one of:
19218      *
19219      * {@link #TEXT_ALIGNMENT_INHERIT},
19220      * {@link #TEXT_ALIGNMENT_GRAVITY},
19221      * {@link #TEXT_ALIGNMENT_CENTER},
19222      * {@link #TEXT_ALIGNMENT_TEXT_START},
19223      * {@link #TEXT_ALIGNMENT_TEXT_END},
19224      * {@link #TEXT_ALIGNMENT_VIEW_START},
19225      * {@link #TEXT_ALIGNMENT_VIEW_END}
19226      *
19227      * @attr ref android.R.styleable#View_textAlignment
19228      *
19229      * @hide
19230      */
19231     @ViewDebug.ExportedProperty(category = "text", mapping = {
19232             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19233             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19234             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19235             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19236             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19237             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19238             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19239     })
19240     @TextAlignment
19241     public int getRawTextAlignment() {
19242         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19243     }
19244 
19245     /**
19246      * Set the text alignment.
19247      *
19248      * @param textAlignment The text alignment to set. Should be one of
19249      *
19250      * {@link #TEXT_ALIGNMENT_INHERIT},
19251      * {@link #TEXT_ALIGNMENT_GRAVITY},
19252      * {@link #TEXT_ALIGNMENT_CENTER},
19253      * {@link #TEXT_ALIGNMENT_TEXT_START},
19254      * {@link #TEXT_ALIGNMENT_TEXT_END},
19255      * {@link #TEXT_ALIGNMENT_VIEW_START},
19256      * {@link #TEXT_ALIGNMENT_VIEW_END}
19257      *
19258      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19259      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19260      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
19261      *
19262      * @attr ref android.R.styleable#View_textAlignment
19263      */
19264     public void setTextAlignment(@TextAlignment int textAlignment) {
19265         if (textAlignment != getRawTextAlignment()) {
19266             // Reset the current and resolved text alignment
19267             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
19268             resetResolvedTextAlignment();
19269             // Set the new text alignment
19270             mPrivateFlags2 |=
19271                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
19272             // Do resolution
19273             resolveTextAlignment();
19274             // Notify change
19275             onRtlPropertiesChanged(getLayoutDirection());
19276             // Refresh
19277             requestLayout();
19278             invalidate(true);
19279         }
19280     }
19281 
19282     /**
19283      * Return the resolved text alignment.
19284      *
19285      * @return the resolved text alignment. Returns one of:
19286      *
19287      * {@link #TEXT_ALIGNMENT_GRAVITY},
19288      * {@link #TEXT_ALIGNMENT_CENTER},
19289      * {@link #TEXT_ALIGNMENT_TEXT_START},
19290      * {@link #TEXT_ALIGNMENT_TEXT_END},
19291      * {@link #TEXT_ALIGNMENT_VIEW_START},
19292      * {@link #TEXT_ALIGNMENT_VIEW_END}
19293      *
19294      * @attr ref android.R.styleable#View_textAlignment
19295      */
19296     @ViewDebug.ExportedProperty(category = "text", mapping = {
19297             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19298             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19299             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19300             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19301             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19302             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19303             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19304     })
19305     @TextAlignment
19306     public int getTextAlignment() {
19307         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
19308                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
19309     }
19310 
19311     /**
19312      * Resolve the text alignment.
19313      *
19314      * @return true if resolution has been done, false otherwise.
19315      *
19316      * @hide
19317      */
19318     public boolean resolveTextAlignment() {
19319         // Reset any previous text alignment resolution
19320         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19321 
19322         if (hasRtlSupport()) {
19323             // Set resolved text alignment flag depending on text alignment flag
19324             final int textAlignment = getRawTextAlignment();
19325             switch (textAlignment) {
19326                 case TEXT_ALIGNMENT_INHERIT:
19327                     // Check if we can resolve the text alignment
19328                     if (!canResolveTextAlignment()) {
19329                         // We cannot do the resolution if there is no parent so use the default
19330                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19331                         // Resolution will need to happen again later
19332                         return false;
19333                     }
19334 
19335                     // Parent has not yet resolved, so we still return the default
19336                     try {
19337                         if (!mParent.isTextAlignmentResolved()) {
19338                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19339                             // Resolution will need to happen again later
19340                             return false;
19341                         }
19342                     } catch (AbstractMethodError e) {
19343                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19344                                 " does not fully implement ViewParent", e);
19345                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
19346                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19347                         return true;
19348                     }
19349 
19350                     int parentResolvedTextAlignment;
19351                     try {
19352                         parentResolvedTextAlignment = mParent.getTextAlignment();
19353                     } catch (AbstractMethodError e) {
19354                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19355                                 " does not fully implement ViewParent", e);
19356                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
19357                     }
19358                     switch (parentResolvedTextAlignment) {
19359                         case TEXT_ALIGNMENT_GRAVITY:
19360                         case TEXT_ALIGNMENT_TEXT_START:
19361                         case TEXT_ALIGNMENT_TEXT_END:
19362                         case TEXT_ALIGNMENT_CENTER:
19363                         case TEXT_ALIGNMENT_VIEW_START:
19364                         case TEXT_ALIGNMENT_VIEW_END:
19365                             // Resolved text alignment is the same as the parent resolved
19366                             // text alignment
19367                             mPrivateFlags2 |=
19368                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19369                             break;
19370                         default:
19371                             // Use default resolved text alignment
19372                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19373                     }
19374                     break;
19375                 case TEXT_ALIGNMENT_GRAVITY:
19376                 case TEXT_ALIGNMENT_TEXT_START:
19377                 case TEXT_ALIGNMENT_TEXT_END:
19378                 case TEXT_ALIGNMENT_CENTER:
19379                 case TEXT_ALIGNMENT_VIEW_START:
19380                 case TEXT_ALIGNMENT_VIEW_END:
19381                     // Resolved text alignment is the same as text alignment
19382                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19383                     break;
19384                 default:
19385                     // Use default resolved text alignment
19386                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19387             }
19388         } else {
19389             // Use default resolved text alignment
19390             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19391         }
19392 
19393         // Set the resolved
19394         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19395         return true;
19396     }
19397 
19398     /**
19399      * Check if text alignment resolution can be done.
19400      *
19401      * @return true if text alignment resolution can be done otherwise return false.
19402      */
19403     public boolean canResolveTextAlignment() {
19404         switch (getRawTextAlignment()) {
19405             case TEXT_DIRECTION_INHERIT:
19406                 if (mParent != null) {
19407                     try {
19408                         return mParent.canResolveTextAlignment();
19409                     } catch (AbstractMethodError e) {
19410                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19411                                 " does not fully implement ViewParent", e);
19412                     }
19413                 }
19414                 return false;
19415 
19416             default:
19417                 return true;
19418         }
19419     }
19420 
19421     /**
19422      * Reset resolved text alignment. Text alignment will be resolved during a call to
19423      * {@link #onMeasure(int, int)}.
19424      *
19425      * @hide
19426      */
19427     public void resetResolvedTextAlignment() {
19428         // Reset any previous text alignment resolution
19429         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19430         // Set to default
19431         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19432     }
19433 
19434     /**
19435      * @return true if text alignment is inherited.
19436      *
19437      * @hide
19438      */
19439     public boolean isTextAlignmentInherited() {
19440         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
19441     }
19442 
19443     /**
19444      * @return true if text alignment is resolved.
19445      */
19446     public boolean isTextAlignmentResolved() {
19447         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19448     }
19449 
19450     /**
19451      * Generate a value suitable for use in {@link #setId(int)}.
19452      * This value will not collide with ID values generated at build time by aapt for R.id.
19453      *
19454      * @return a generated ID value
19455      */
19456     public static int generateViewId() {
19457         for (;;) {
19458             final int result = sNextGeneratedId.get();
19459             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
19460             int newValue = result + 1;
19461             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
19462             if (sNextGeneratedId.compareAndSet(result, newValue)) {
19463                 return result;
19464             }
19465         }
19466     }
19467 
19468     /**
19469      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
19470      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
19471      *                           a normal View or a ViewGroup with
19472      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
19473      * @hide
19474      */
19475     public void captureTransitioningViews(List<View> transitioningViews) {
19476         if (getVisibility() == View.VISIBLE) {
19477             transitioningViews.add(this);
19478         }
19479     }
19480 
19481     /**
19482      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
19483      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
19484      * @hide
19485      */
19486     public void findNamedViews(Map<String, View> namedElements) {
19487         if (getVisibility() == VISIBLE || mGhostView != null) {
19488             String transitionName = getTransitionName();
19489             if (transitionName != null) {
19490                 namedElements.put(transitionName, this);
19491             }
19492         }
19493     }
19494 
19495     //
19496     // Properties
19497     //
19498     /**
19499      * A Property wrapper around the <code>alpha</code> functionality handled by the
19500      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
19501      */
19502     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
19503         @Override
19504         public void setValue(View object, float value) {
19505             object.setAlpha(value);
19506         }
19507 
19508         @Override
19509         public Float get(View object) {
19510             return object.getAlpha();
19511         }
19512     };
19513 
19514     /**
19515      * A Property wrapper around the <code>translationX</code> functionality handled by the
19516      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
19517      */
19518     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
19519         @Override
19520         public void setValue(View object, float value) {
19521             object.setTranslationX(value);
19522         }
19523 
19524                 @Override
19525         public Float get(View object) {
19526             return object.getTranslationX();
19527         }
19528     };
19529 
19530     /**
19531      * A Property wrapper around the <code>translationY</code> functionality handled by the
19532      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
19533      */
19534     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
19535         @Override
19536         public void setValue(View object, float value) {
19537             object.setTranslationY(value);
19538         }
19539 
19540         @Override
19541         public Float get(View object) {
19542             return object.getTranslationY();
19543         }
19544     };
19545 
19546     /**
19547      * A Property wrapper around the <code>translationZ</code> functionality handled by the
19548      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
19549      */
19550     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
19551         @Override
19552         public void setValue(View object, float value) {
19553             object.setTranslationZ(value);
19554         }
19555 
19556         @Override
19557         public Float get(View object) {
19558             return object.getTranslationZ();
19559         }
19560     };
19561 
19562     /**
19563      * A Property wrapper around the <code>x</code> functionality handled by the
19564      * {@link View#setX(float)} and {@link View#getX()} methods.
19565      */
19566     public static final Property<View, Float> X = new FloatProperty<View>("x") {
19567         @Override
19568         public void setValue(View object, float value) {
19569             object.setX(value);
19570         }
19571 
19572         @Override
19573         public Float get(View object) {
19574             return object.getX();
19575         }
19576     };
19577 
19578     /**
19579      * A Property wrapper around the <code>y</code> functionality handled by the
19580      * {@link View#setY(float)} and {@link View#getY()} methods.
19581      */
19582     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
19583         @Override
19584         public void setValue(View object, float value) {
19585             object.setY(value);
19586         }
19587 
19588         @Override
19589         public Float get(View object) {
19590             return object.getY();
19591         }
19592     };
19593 
19594     /**
19595      * A Property wrapper around the <code>z</code> functionality handled by the
19596      * {@link View#setZ(float)} and {@link View#getZ()} methods.
19597      */
19598     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
19599         @Override
19600         public void setValue(View object, float value) {
19601             object.setZ(value);
19602         }
19603 
19604         @Override
19605         public Float get(View object) {
19606             return object.getZ();
19607         }
19608     };
19609 
19610     /**
19611      * A Property wrapper around the <code>rotation</code> functionality handled by the
19612      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
19613      */
19614     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
19615         @Override
19616         public void setValue(View object, float value) {
19617             object.setRotation(value);
19618         }
19619 
19620         @Override
19621         public Float get(View object) {
19622             return object.getRotation();
19623         }
19624     };
19625 
19626     /**
19627      * A Property wrapper around the <code>rotationX</code> functionality handled by the
19628      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
19629      */
19630     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
19631         @Override
19632         public void setValue(View object, float value) {
19633             object.setRotationX(value);
19634         }
19635 
19636         @Override
19637         public Float get(View object) {
19638             return object.getRotationX();
19639         }
19640     };
19641 
19642     /**
19643      * A Property wrapper around the <code>rotationY</code> functionality handled by the
19644      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
19645      */
19646     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
19647         @Override
19648         public void setValue(View object, float value) {
19649             object.setRotationY(value);
19650         }
19651 
19652         @Override
19653         public Float get(View object) {
19654             return object.getRotationY();
19655         }
19656     };
19657 
19658     /**
19659      * A Property wrapper around the <code>scaleX</code> functionality handled by the
19660      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
19661      */
19662     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
19663         @Override
19664         public void setValue(View object, float value) {
19665             object.setScaleX(value);
19666         }
19667 
19668         @Override
19669         public Float get(View object) {
19670             return object.getScaleX();
19671         }
19672     };
19673 
19674     /**
19675      * A Property wrapper around the <code>scaleY</code> functionality handled by the
19676      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
19677      */
19678     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
19679         @Override
19680         public void setValue(View object, float value) {
19681             object.setScaleY(value);
19682         }
19683 
19684         @Override
19685         public Float get(View object) {
19686             return object.getScaleY();
19687         }
19688     };
19689 
19690     /**
19691      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
19692      * Each MeasureSpec represents a requirement for either the width or the height.
19693      * A MeasureSpec is comprised of a size and a mode. There are three possible
19694      * modes:
19695      * <dl>
19696      * <dt>UNSPECIFIED</dt>
19697      * <dd>
19698      * The parent has not imposed any constraint on the child. It can be whatever size
19699      * it wants.
19700      * </dd>
19701      *
19702      * <dt>EXACTLY</dt>
19703      * <dd>
19704      * The parent has determined an exact size for the child. The child is going to be
19705      * given those bounds regardless of how big it wants to be.
19706      * </dd>
19707      *
19708      * <dt>AT_MOST</dt>
19709      * <dd>
19710      * The child can be as large as it wants up to the specified size.
19711      * </dd>
19712      * </dl>
19713      *
19714      * MeasureSpecs are implemented as ints to reduce object allocation. This class
19715      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
19716      */
19717     public static class MeasureSpec {
19718         private static final int MODE_SHIFT = 30;
19719         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
19720 
19721         /**
19722          * Measure specification mode: The parent has not imposed any constraint
19723          * on the child. It can be whatever size it wants.
19724          */
19725         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
19726 
19727         /**
19728          * Measure specification mode: The parent has determined an exact size
19729          * for the child. The child is going to be given those bounds regardless
19730          * of how big it wants to be.
19731          */
19732         public static final int EXACTLY     = 1 << MODE_SHIFT;
19733 
19734         /**
19735          * Measure specification mode: The child can be as large as it wants up
19736          * to the specified size.
19737          */
19738         public static final int AT_MOST     = 2 << MODE_SHIFT;
19739 
19740         /**
19741          * Creates a measure specification based on the supplied size and mode.
19742          *
19743          * The mode must always be one of the following:
19744          * <ul>
19745          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
19746          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
19747          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
19748          * </ul>
19749          *
19750          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
19751          * implementation was such that the order of arguments did not matter
19752          * and overflow in either value could impact the resulting MeasureSpec.
19753          * {@link android.widget.RelativeLayout} was affected by this bug.
19754          * Apps targeting API levels greater than 17 will get the fixed, more strict
19755          * behavior.</p>
19756          *
19757          * @param size the size of the measure specification
19758          * @param mode the mode of the measure specification
19759          * @return the measure specification based on size and mode
19760          */
19761         public static int makeMeasureSpec(int size, int mode) {
19762             if (sUseBrokenMakeMeasureSpec) {
19763                 return size + mode;
19764             } else {
19765                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
19766             }
19767         }
19768 
19769         /**
19770          * Extracts the mode from the supplied measure specification.
19771          *
19772          * @param measureSpec the measure specification to extract the mode from
19773          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
19774          *         {@link android.view.View.MeasureSpec#AT_MOST} or
19775          *         {@link android.view.View.MeasureSpec#EXACTLY}
19776          */
19777         public static int getMode(int measureSpec) {
19778             return (measureSpec & MODE_MASK);
19779         }
19780 
19781         /**
19782          * Extracts the size from the supplied measure specification.
19783          *
19784          * @param measureSpec the measure specification to extract the size from
19785          * @return the size in pixels defined in the supplied measure specification
19786          */
19787         public static int getSize(int measureSpec) {
19788             return (measureSpec & ~MODE_MASK);
19789         }
19790 
19791         static int adjust(int measureSpec, int delta) {
19792             final int mode = getMode(measureSpec);
19793             if (mode == UNSPECIFIED) {
19794                 // No need to adjust size for UNSPECIFIED mode.
19795                 return makeMeasureSpec(0, UNSPECIFIED);
19796             }
19797             int size = getSize(measureSpec) + delta;
19798             if (size < 0) {
19799                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
19800                         ") spec: " + toString(measureSpec) + " delta: " + delta);
19801                 size = 0;
19802             }
19803             return makeMeasureSpec(size, mode);
19804         }
19805 
19806         /**
19807          * Returns a String representation of the specified measure
19808          * specification.
19809          *
19810          * @param measureSpec the measure specification to convert to a String
19811          * @return a String with the following format: "MeasureSpec: MODE SIZE"
19812          */
19813         public static String toString(int measureSpec) {
19814             int mode = getMode(measureSpec);
19815             int size = getSize(measureSpec);
19816 
19817             StringBuilder sb = new StringBuilder("MeasureSpec: ");
19818 
19819             if (mode == UNSPECIFIED)
19820                 sb.append("UNSPECIFIED ");
19821             else if (mode == EXACTLY)
19822                 sb.append("EXACTLY ");
19823             else if (mode == AT_MOST)
19824                 sb.append("AT_MOST ");
19825             else
19826                 sb.append(mode).append(" ");
19827 
19828             sb.append(size);
19829             return sb.toString();
19830         }
19831     }
19832 
19833     private final class CheckForLongPress implements Runnable {
19834         private int mOriginalWindowAttachCount;
19835 
19836         @Override
19837         public void run() {
19838             if (isPressed() && (mParent != null)
19839                     && mOriginalWindowAttachCount == mWindowAttachCount) {
19840                 if (performLongClick()) {
19841                     mHasPerformedLongPress = true;
19842                 }
19843             }
19844         }
19845 
19846         public void rememberWindowAttachCount() {
19847             mOriginalWindowAttachCount = mWindowAttachCount;
19848         }
19849     }
19850 
19851     private final class CheckForTap implements Runnable {
19852         public float x;
19853         public float y;
19854 
19855         @Override
19856         public void run() {
19857             mPrivateFlags &= ~PFLAG_PREPRESSED;
19858             setPressed(true, x, y);
19859             checkForLongClick(ViewConfiguration.getTapTimeout());
19860         }
19861     }
19862 
19863     private final class PerformClick implements Runnable {
19864         @Override
19865         public void run() {
19866             performClick();
19867         }
19868     }
19869 
19870     /** @hide */
19871     public void hackTurnOffWindowResizeAnim(boolean off) {
19872         mAttachInfo.mTurnOffWindowResizeAnim = off;
19873     }
19874 
19875     /**
19876      * This method returns a ViewPropertyAnimator object, which can be used to animate
19877      * specific properties on this View.
19878      *
19879      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
19880      */
19881     public ViewPropertyAnimator animate() {
19882         if (mAnimator == null) {
19883             mAnimator = new ViewPropertyAnimator(this);
19884         }
19885         return mAnimator;
19886     }
19887 
19888     /**
19889      * Sets the name of the View to be used to identify Views in Transitions.
19890      * Names should be unique in the View hierarchy.
19891      *
19892      * @param transitionName The name of the View to uniquely identify it for Transitions.
19893      */
19894     public final void setTransitionName(String transitionName) {
19895         mTransitionName = transitionName;
19896     }
19897 
19898     /**
19899      * Returns the name of the View to be used to identify Views in Transitions.
19900      * Names should be unique in the View hierarchy.
19901      *
19902      * <p>This returns null if the View has not been given a name.</p>
19903      *
19904      * @return The name used of the View to be used to identify Views in Transitions or null
19905      * if no name has been given.
19906      */
19907     @ViewDebug.ExportedProperty
19908     public String getTransitionName() {
19909         return mTransitionName;
19910     }
19911 
19912     /**
19913      * Interface definition for a callback to be invoked when a hardware key event is
19914      * dispatched to this view. The callback will be invoked before the key event is
19915      * given to the view. This is only useful for hardware keyboards; a software input
19916      * method has no obligation to trigger this listener.
19917      */
19918     public interface OnKeyListener {
19919         /**
19920          * Called when a hardware key is dispatched to a view. This allows listeners to
19921          * get a chance to respond before the target view.
19922          * <p>Key presses in software keyboards will generally NOT trigger this method,
19923          * although some may elect to do so in some situations. Do not assume a
19924          * software input method has to be key-based; even if it is, it may use key presses
19925          * in a different way than you expect, so there is no way to reliably catch soft
19926          * input key presses.
19927          *
19928          * @param v The view the key has been dispatched to.
19929          * @param keyCode The code for the physical key that was pressed
19930          * @param event The KeyEvent object containing full information about
19931          *        the event.
19932          * @return True if the listener has consumed the event, false otherwise.
19933          */
19934         boolean onKey(View v, int keyCode, KeyEvent event);
19935     }
19936 
19937     /**
19938      * Interface definition for a callback to be invoked when a touch event is
19939      * dispatched to this view. The callback will be invoked before the touch
19940      * event is given to the view.
19941      */
19942     public interface OnTouchListener {
19943         /**
19944          * Called when a touch event is dispatched to a view. This allows listeners to
19945          * get a chance to respond before the target view.
19946          *
19947          * @param v The view the touch event has been dispatched to.
19948          * @param event The MotionEvent object containing full information about
19949          *        the event.
19950          * @return True if the listener has consumed the event, false otherwise.
19951          */
19952         boolean onTouch(View v, MotionEvent event);
19953     }
19954 
19955     /**
19956      * Interface definition for a callback to be invoked when a hover event is
19957      * dispatched to this view. The callback will be invoked before the hover
19958      * event is given to the view.
19959      */
19960     public interface OnHoverListener {
19961         /**
19962          * Called when a hover event is dispatched to a view. This allows listeners to
19963          * get a chance to respond before the target view.
19964          *
19965          * @param v The view the hover event has been dispatched to.
19966          * @param event The MotionEvent object containing full information about
19967          *        the event.
19968          * @return True if the listener has consumed the event, false otherwise.
19969          */
19970         boolean onHover(View v, MotionEvent event);
19971     }
19972 
19973     /**
19974      * Interface definition for a callback to be invoked when a generic motion event is
19975      * dispatched to this view. The callback will be invoked before the generic motion
19976      * event is given to the view.
19977      */
19978     public interface OnGenericMotionListener {
19979         /**
19980          * Called when a generic motion event is dispatched to a view. This allows listeners to
19981          * get a chance to respond before the target view.
19982          *
19983          * @param v The view the generic motion event has been dispatched to.
19984          * @param event The MotionEvent object containing full information about
19985          *        the event.
19986          * @return True if the listener has consumed the event, false otherwise.
19987          */
19988         boolean onGenericMotion(View v, MotionEvent event);
19989     }
19990 
19991     /**
19992      * Interface definition for a callback to be invoked when a view has been clicked and held.
19993      */
19994     public interface OnLongClickListener {
19995         /**
19996          * Called when a view has been clicked and held.
19997          *
19998          * @param v The view that was clicked and held.
19999          *
20000          * @return true if the callback consumed the long click, false otherwise.
20001          */
20002         boolean onLongClick(View v);
20003     }
20004 
20005     /**
20006      * Interface definition for a callback to be invoked when a drag is being dispatched
20007      * to this view.  The callback will be invoked before the hosting view's own
20008      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
20009      * onDrag(event) behavior, it should return 'false' from this callback.
20010      *
20011      * <div class="special reference">
20012      * <h3>Developer Guides</h3>
20013      * <p>For a guide to implementing drag and drop features, read the
20014      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20015      * </div>
20016      */
20017     public interface OnDragListener {
20018         /**
20019          * Called when a drag event is dispatched to a view. This allows listeners
20020          * to get a chance to override base View behavior.
20021          *
20022          * @param v The View that received the drag event.
20023          * @param event The {@link android.view.DragEvent} object for the drag event.
20024          * @return {@code true} if the drag event was handled successfully, or {@code false}
20025          * if the drag event was not handled. Note that {@code false} will trigger the View
20026          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
20027          */
20028         boolean onDrag(View v, DragEvent event);
20029     }
20030 
20031     /**
20032      * Interface definition for a callback to be invoked when the focus state of
20033      * a view changed.
20034      */
20035     public interface OnFocusChangeListener {
20036         /**
20037          * Called when the focus state of a view has changed.
20038          *
20039          * @param v The view whose state has changed.
20040          * @param hasFocus The new focus state of v.
20041          */
20042         void onFocusChange(View v, boolean hasFocus);
20043     }
20044 
20045     /**
20046      * Interface definition for a callback to be invoked when a view is clicked.
20047      */
20048     public interface OnClickListener {
20049         /**
20050          * Called when a view has been clicked.
20051          *
20052          * @param v The view that was clicked.
20053          */
20054         void onClick(View v);
20055     }
20056 
20057     /**
20058      * Interface definition for a callback to be invoked when the context menu
20059      * for this view is being built.
20060      */
20061     public interface OnCreateContextMenuListener {
20062         /**
20063          * Called when the context menu for this view is being built. It is not
20064          * safe to hold onto the menu after this method returns.
20065          *
20066          * @param menu The context menu that is being built
20067          * @param v The view for which the context menu is being built
20068          * @param menuInfo Extra information about the item for which the
20069          *            context menu should be shown. This information will vary
20070          *            depending on the class of v.
20071          */
20072         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
20073     }
20074 
20075     /**
20076      * Interface definition for a callback to be invoked when the status bar changes
20077      * visibility.  This reports <strong>global</strong> changes to the system UI
20078      * state, not what the application is requesting.
20079      *
20080      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
20081      */
20082     public interface OnSystemUiVisibilityChangeListener {
20083         /**
20084          * Called when the status bar changes visibility because of a call to
20085          * {@link View#setSystemUiVisibility(int)}.
20086          *
20087          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20088          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
20089          * This tells you the <strong>global</strong> state of these UI visibility
20090          * flags, not what your app is currently applying.
20091          */
20092         public void onSystemUiVisibilityChange(int visibility);
20093     }
20094 
20095     /**
20096      * Interface definition for a callback to be invoked when this view is attached
20097      * or detached from its window.
20098      */
20099     public interface OnAttachStateChangeListener {
20100         /**
20101          * Called when the view is attached to a window.
20102          * @param v The view that was attached
20103          */
20104         public void onViewAttachedToWindow(View v);
20105         /**
20106          * Called when the view is detached from a window.
20107          * @param v The view that was detached
20108          */
20109         public void onViewDetachedFromWindow(View v);
20110     }
20111 
20112     /**
20113      * Listener for applying window insets on a view in a custom way.
20114      *
20115      * <p>Apps may choose to implement this interface if they want to apply custom policy
20116      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
20117      * is set, its
20118      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
20119      * method will be called instead of the View's own
20120      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
20121      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
20122      * the View's normal behavior as part of its own.</p>
20123      */
20124     public interface OnApplyWindowInsetsListener {
20125         /**
20126          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
20127          * on a View, this listener method will be called instead of the view's own
20128          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
20129          *
20130          * @param v The view applying window insets
20131          * @param insets The insets to apply
20132          * @return The insets supplied, minus any insets that were consumed
20133          */
20134         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
20135     }
20136 
20137     private final class UnsetPressedState implements Runnable {
20138         @Override
20139         public void run() {
20140             setPressed(false);
20141         }
20142     }
20143 
20144     /**
20145      * Base class for derived classes that want to save and restore their own
20146      * state in {@link android.view.View#onSaveInstanceState()}.
20147      */
20148     public static class BaseSavedState extends AbsSavedState {
20149         /**
20150          * Constructor used when reading from a parcel. Reads the state of the superclass.
20151          *
20152          * @param source
20153          */
20154         public BaseSavedState(Parcel source) {
20155             super(source);
20156         }
20157 
20158         /**
20159          * Constructor called by derived classes when creating their SavedState objects
20160          *
20161          * @param superState The state of the superclass of this view
20162          */
20163         public BaseSavedState(Parcelable superState) {
20164             super(superState);
20165         }
20166 
20167         public static final Parcelable.Creator<BaseSavedState> CREATOR =
20168                 new Parcelable.Creator<BaseSavedState>() {
20169             public BaseSavedState createFromParcel(Parcel in) {
20170                 return new BaseSavedState(in);
20171             }
20172 
20173             public BaseSavedState[] newArray(int size) {
20174                 return new BaseSavedState[size];
20175             }
20176         };
20177     }
20178 
20179     /**
20180      * A set of information given to a view when it is attached to its parent
20181      * window.
20182      */
20183     final static class AttachInfo {
20184         interface Callbacks {
20185             void playSoundEffect(int effectId);
20186             boolean performHapticFeedback(int effectId, boolean always);
20187         }
20188 
20189         /**
20190          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
20191          * to a Handler. This class contains the target (View) to invalidate and
20192          * the coordinates of the dirty rectangle.
20193          *
20194          * For performance purposes, this class also implements a pool of up to
20195          * POOL_LIMIT objects that get reused. This reduces memory allocations
20196          * whenever possible.
20197          */
20198         static class InvalidateInfo {
20199             private static final int POOL_LIMIT = 10;
20200 
20201             private static final SynchronizedPool<InvalidateInfo> sPool =
20202                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20203 
20204             View target;
20205 
20206             int left;
20207             int top;
20208             int right;
20209             int bottom;
20210 
20211             public static InvalidateInfo obtain() {
20212                 InvalidateInfo instance = sPool.acquire();
20213                 return (instance != null) ? instance : new InvalidateInfo();
20214             }
20215 
20216             public void recycle() {
20217                 target = null;
20218                 sPool.release(this);
20219             }
20220         }
20221 
20222         final IWindowSession mSession;
20223 
20224         final IWindow mWindow;
20225 
20226         final IBinder mWindowToken;
20227 
20228         final Display mDisplay;
20229 
20230         final Callbacks mRootCallbacks;
20231 
20232         IWindowId mIWindowId;
20233         WindowId mWindowId;
20234 
20235         /**
20236          * The top view of the hierarchy.
20237          */
20238         View mRootView;
20239 
20240         IBinder mPanelParentWindowToken;
20241 
20242         boolean mHardwareAccelerated;
20243         boolean mHardwareAccelerationRequested;
20244         HardwareRenderer mHardwareRenderer;
20245         List<RenderNode> mPendingAnimatingRenderNodes;
20246 
20247         /**
20248          * The state of the display to which the window is attached, as reported
20249          * by {@link Display#getState()}.  Note that the display state constants
20250          * declared by {@link Display} do not exactly line up with the screen state
20251          * constants declared by {@link View} (there are more display states than
20252          * screen states).
20253          */
20254         int mDisplayState = Display.STATE_UNKNOWN;
20255 
20256         /**
20257          * Scale factor used by the compatibility mode
20258          */
20259         float mApplicationScale;
20260 
20261         /**
20262          * Indicates whether the application is in compatibility mode
20263          */
20264         boolean mScalingRequired;
20265 
20266         /**
20267          * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
20268          */
20269         boolean mTurnOffWindowResizeAnim;
20270 
20271         /**
20272          * Left position of this view's window
20273          */
20274         int mWindowLeft;
20275 
20276         /**
20277          * Top position of this view's window
20278          */
20279         int mWindowTop;
20280 
20281         /**
20282          * Indicates whether views need to use 32-bit drawing caches
20283          */
20284         boolean mUse32BitDrawingCache;
20285 
20286         /**
20287          * For windows that are full-screen but using insets to layout inside
20288          * of the screen areas, these are the current insets to appear inside
20289          * the overscan area of the display.
20290          */
20291         final Rect mOverscanInsets = new Rect();
20292 
20293         /**
20294          * For windows that are full-screen but using insets to layout inside
20295          * of the screen decorations, these are the current insets for the
20296          * content of the window.
20297          */
20298         final Rect mContentInsets = new Rect();
20299 
20300         /**
20301          * For windows that are full-screen but using insets to layout inside
20302          * of the screen decorations, these are the current insets for the
20303          * actual visible parts of the window.
20304          */
20305         final Rect mVisibleInsets = new Rect();
20306 
20307         /**
20308          * For windows that are full-screen but using insets to layout inside
20309          * of the screen decorations, these are the current insets for the
20310          * stable system windows.
20311          */
20312         final Rect mStableInsets = new Rect();
20313 
20314         /**
20315          * The internal insets given by this window.  This value is
20316          * supplied by the client (through
20317          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
20318          * be given to the window manager when changed to be used in laying
20319          * out windows behind it.
20320          */
20321         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
20322                 = new ViewTreeObserver.InternalInsetsInfo();
20323 
20324         /**
20325          * Set to true when mGivenInternalInsets is non-empty.
20326          */
20327         boolean mHasNonEmptyGivenInternalInsets;
20328 
20329         /**
20330          * All views in the window's hierarchy that serve as scroll containers,
20331          * used to determine if the window can be resized or must be panned
20332          * to adjust for a soft input area.
20333          */
20334         final ArrayList<View> mScrollContainers = new ArrayList<View>();
20335 
20336         final KeyEvent.DispatcherState mKeyDispatchState
20337                 = new KeyEvent.DispatcherState();
20338 
20339         /**
20340          * Indicates whether the view's window currently has the focus.
20341          */
20342         boolean mHasWindowFocus;
20343 
20344         /**
20345          * The current visibility of the window.
20346          */
20347         int mWindowVisibility;
20348 
20349         /**
20350          * Indicates the time at which drawing started to occur.
20351          */
20352         long mDrawingTime;
20353 
20354         /**
20355          * Indicates whether or not ignoring the DIRTY_MASK flags.
20356          */
20357         boolean mIgnoreDirtyState;
20358 
20359         /**
20360          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
20361          * to avoid clearing that flag prematurely.
20362          */
20363         boolean mSetIgnoreDirtyState = false;
20364 
20365         /**
20366          * Indicates whether the view's window is currently in touch mode.
20367          */
20368         boolean mInTouchMode;
20369 
20370         /**
20371          * Indicates whether the view has requested unbuffered input dispatching for the current
20372          * event stream.
20373          */
20374         boolean mUnbufferedDispatchRequested;
20375 
20376         /**
20377          * Indicates that ViewAncestor should trigger a global layout change
20378          * the next time it performs a traversal
20379          */
20380         boolean mRecomputeGlobalAttributes;
20381 
20382         /**
20383          * Always report new attributes at next traversal.
20384          */
20385         boolean mForceReportNewAttributes;
20386 
20387         /**
20388          * Set during a traveral if any views want to keep the screen on.
20389          */
20390         boolean mKeepScreenOn;
20391 
20392         /**
20393          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
20394          */
20395         int mSystemUiVisibility;
20396 
20397         /**
20398          * Hack to force certain system UI visibility flags to be cleared.
20399          */
20400         int mDisabledSystemUiVisibility;
20401 
20402         /**
20403          * Last global system UI visibility reported by the window manager.
20404          */
20405         int mGlobalSystemUiVisibility;
20406 
20407         /**
20408          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
20409          * attached.
20410          */
20411         boolean mHasSystemUiListeners;
20412 
20413         /**
20414          * Set if the window has requested to extend into the overscan region
20415          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
20416          */
20417         boolean mOverscanRequested;
20418 
20419         /**
20420          * Set if the visibility of any views has changed.
20421          */
20422         boolean mViewVisibilityChanged;
20423 
20424         /**
20425          * Set to true if a view has been scrolled.
20426          */
20427         boolean mViewScrollChanged;
20428 
20429         /**
20430          * Set to true if high contrast mode enabled
20431          */
20432         boolean mHighContrastText;
20433 
20434         /**
20435          * Global to the view hierarchy used as a temporary for dealing with
20436          * x/y points in the transparent region computations.
20437          */
20438         final int[] mTransparentLocation = new int[2];
20439 
20440         /**
20441          * Global to the view hierarchy used as a temporary for dealing with
20442          * x/y points in the ViewGroup.invalidateChild implementation.
20443          */
20444         final int[] mInvalidateChildLocation = new int[2];
20445 
20446         /**
20447          * Global to the view hierarchy used as a temporary for dealng with
20448          * computing absolute on-screen location.
20449          */
20450         final int[] mTmpLocation = new int[2];
20451 
20452         /**
20453          * Global to the view hierarchy used as a temporary for dealing with
20454          * x/y location when view is transformed.
20455          */
20456         final float[] mTmpTransformLocation = new float[2];
20457 
20458         /**
20459          * The view tree observer used to dispatch global events like
20460          * layout, pre-draw, touch mode change, etc.
20461          */
20462         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
20463 
20464         /**
20465          * A Canvas used by the view hierarchy to perform bitmap caching.
20466          */
20467         Canvas mCanvas;
20468 
20469         /**
20470          * The view root impl.
20471          */
20472         final ViewRootImpl mViewRootImpl;
20473 
20474         /**
20475          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
20476          * handler can be used to pump events in the UI events queue.
20477          */
20478         final Handler mHandler;
20479 
20480         /**
20481          * Temporary for use in computing invalidate rectangles while
20482          * calling up the hierarchy.
20483          */
20484         final Rect mTmpInvalRect = new Rect();
20485 
20486         /**
20487          * Temporary for use in computing hit areas with transformed views
20488          */
20489         final RectF mTmpTransformRect = new RectF();
20490 
20491         /**
20492          * Temporary for use in computing hit areas with transformed views
20493          */
20494         final RectF mTmpTransformRect1 = new RectF();
20495 
20496         /**
20497          * Temporary list of rectanges.
20498          */
20499         final List<RectF> mTmpRectList = new ArrayList<>();
20500 
20501         /**
20502          * Temporary for use in transforming invalidation rect
20503          */
20504         final Matrix mTmpMatrix = new Matrix();
20505 
20506         /**
20507          * Temporary for use in transforming invalidation rect
20508          */
20509         final Transformation mTmpTransformation = new Transformation();
20510 
20511         /**
20512          * Temporary for use in querying outlines from OutlineProviders
20513          */
20514         final Outline mTmpOutline = new Outline();
20515 
20516         /**
20517          * Temporary list for use in collecting focusable descendents of a view.
20518          */
20519         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
20520 
20521         /**
20522          * The id of the window for accessibility purposes.
20523          */
20524         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
20525 
20526         /**
20527          * Flags related to accessibility processing.
20528          *
20529          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
20530          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
20531          */
20532         int mAccessibilityFetchFlags;
20533 
20534         /**
20535          * The drawable for highlighting accessibility focus.
20536          */
20537         Drawable mAccessibilityFocusDrawable;
20538 
20539         /**
20540          * Show where the margins, bounds and layout bounds are for each view.
20541          */
20542         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
20543 
20544         /**
20545          * Point used to compute visible regions.
20546          */
20547         final Point mPoint = new Point();
20548 
20549         /**
20550          * Used to track which View originated a requestLayout() call, used when
20551          * requestLayout() is called during layout.
20552          */
20553         View mViewRequestingLayout;
20554 
20555         /**
20556          * Creates a new set of attachment information with the specified
20557          * events handler and thread.
20558          *
20559          * @param handler the events handler the view must use
20560          */
20561         AttachInfo(IWindowSession session, IWindow window, Display display,
20562                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
20563             mSession = session;
20564             mWindow = window;
20565             mWindowToken = window.asBinder();
20566             mDisplay = display;
20567             mViewRootImpl = viewRootImpl;
20568             mHandler = handler;
20569             mRootCallbacks = effectPlayer;
20570         }
20571     }
20572 
20573     /**
20574      * <p>ScrollabilityCache holds various fields used by a View when scrolling
20575      * is supported. This avoids keeping too many unused fields in most
20576      * instances of View.</p>
20577      */
20578     private static class ScrollabilityCache implements Runnable {
20579 
20580         /**
20581          * Scrollbars are not visible
20582          */
20583         public static final int OFF = 0;
20584 
20585         /**
20586          * Scrollbars are visible
20587          */
20588         public static final int ON = 1;
20589 
20590         /**
20591          * Scrollbars are fading away
20592          */
20593         public static final int FADING = 2;
20594 
20595         public boolean fadeScrollBars;
20596 
20597         public int fadingEdgeLength;
20598         public int scrollBarDefaultDelayBeforeFade;
20599         public int scrollBarFadeDuration;
20600 
20601         public int scrollBarSize;
20602         public ScrollBarDrawable scrollBar;
20603         public float[] interpolatorValues;
20604         public View host;
20605 
20606         public final Paint paint;
20607         public final Matrix matrix;
20608         public Shader shader;
20609 
20610         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
20611 
20612         private static final float[] OPAQUE = { 255 };
20613         private static final float[] TRANSPARENT = { 0.0f };
20614 
20615         /**
20616          * When fading should start. This time moves into the future every time
20617          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
20618          */
20619         public long fadeStartTime;
20620 
20621 
20622         /**
20623          * The current state of the scrollbars: ON, OFF, or FADING
20624          */
20625         public int state = OFF;
20626 
20627         private int mLastColor;
20628 
20629         public ScrollabilityCache(ViewConfiguration configuration, View host) {
20630             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
20631             scrollBarSize = configuration.getScaledScrollBarSize();
20632             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
20633             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
20634 
20635             paint = new Paint();
20636             matrix = new Matrix();
20637             // use use a height of 1, and then wack the matrix each time we
20638             // actually use it.
20639             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20640             paint.setShader(shader);
20641             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20642 
20643             this.host = host;
20644         }
20645 
20646         public void setFadeColor(int color) {
20647             if (color != mLastColor) {
20648                 mLastColor = color;
20649 
20650                 if (color != 0) {
20651                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
20652                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
20653                     paint.setShader(shader);
20654                     // Restore the default transfer mode (src_over)
20655                     paint.setXfermode(null);
20656                 } else {
20657                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20658                     paint.setShader(shader);
20659                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20660                 }
20661             }
20662         }
20663 
20664         public void run() {
20665             long now = AnimationUtils.currentAnimationTimeMillis();
20666             if (now >= fadeStartTime) {
20667 
20668                 // the animation fades the scrollbars out by changing
20669                 // the opacity (alpha) from fully opaque to fully
20670                 // transparent
20671                 int nextFrame = (int) now;
20672                 int framesCount = 0;
20673 
20674                 Interpolator interpolator = scrollBarInterpolator;
20675 
20676                 // Start opaque
20677                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
20678 
20679                 // End transparent
20680                 nextFrame += scrollBarFadeDuration;
20681                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
20682 
20683                 state = FADING;
20684 
20685                 // Kick off the fade animation
20686                 host.invalidate(true);
20687             }
20688         }
20689     }
20690 
20691     /**
20692      * Resuable callback for sending
20693      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
20694      */
20695     private class SendViewScrolledAccessibilityEvent implements Runnable {
20696         public volatile boolean mIsPending;
20697 
20698         public void run() {
20699             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
20700             mIsPending = false;
20701         }
20702     }
20703 
20704     /**
20705      * <p>
20706      * This class represents a delegate that can be registered in a {@link View}
20707      * to enhance accessibility support via composition rather via inheritance.
20708      * It is specifically targeted to widget developers that extend basic View
20709      * classes i.e. classes in package android.view, that would like their
20710      * applications to be backwards compatible.
20711      * </p>
20712      * <div class="special reference">
20713      * <h3>Developer Guides</h3>
20714      * <p>For more information about making applications accessible, read the
20715      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
20716      * developer guide.</p>
20717      * </div>
20718      * <p>
20719      * A scenario in which a developer would like to use an accessibility delegate
20720      * is overriding a method introduced in a later API version then the minimal API
20721      * version supported by the application. For example, the method
20722      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
20723      * in API version 4 when the accessibility APIs were first introduced. If a
20724      * developer would like his application to run on API version 4 devices (assuming
20725      * all other APIs used by the application are version 4 or lower) and take advantage
20726      * of this method, instead of overriding the method which would break the application's
20727      * backwards compatibility, he can override the corresponding method in this
20728      * delegate and register the delegate in the target View if the API version of
20729      * the system is high enough i.e. the API version is same or higher to the API
20730      * version that introduced
20731      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
20732      * </p>
20733      * <p>
20734      * Here is an example implementation:
20735      * </p>
20736      * <code><pre><p>
20737      * if (Build.VERSION.SDK_INT >= 14) {
20738      *     // If the API version is equal of higher than the version in
20739      *     // which onInitializeAccessibilityNodeInfo was introduced we
20740      *     // register a delegate with a customized implementation.
20741      *     View view = findViewById(R.id.view_id);
20742      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
20743      *         public void onInitializeAccessibilityNodeInfo(View host,
20744      *                 AccessibilityNodeInfo info) {
20745      *             // Let the default implementation populate the info.
20746      *             super.onInitializeAccessibilityNodeInfo(host, info);
20747      *             // Set some other information.
20748      *             info.setEnabled(host.isEnabled());
20749      *         }
20750      *     });
20751      * }
20752      * </code></pre></p>
20753      * <p>
20754      * This delegate contains methods that correspond to the accessibility methods
20755      * in View. If a delegate has been specified the implementation in View hands
20756      * off handling to the corresponding method in this delegate. The default
20757      * implementation the delegate methods behaves exactly as the corresponding
20758      * method in View for the case of no accessibility delegate been set. Hence,
20759      * to customize the behavior of a View method, clients can override only the
20760      * corresponding delegate method without altering the behavior of the rest
20761      * accessibility related methods of the host view.
20762      * </p>
20763      */
20764     public static class AccessibilityDelegate {
20765 
20766         /**
20767          * Sends an accessibility event of the given type. If accessibility is not
20768          * enabled this method has no effect.
20769          * <p>
20770          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
20771          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
20772          * been set.
20773          * </p>
20774          *
20775          * @param host The View hosting the delegate.
20776          * @param eventType The type of the event to send.
20777          *
20778          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
20779          */
20780         public void sendAccessibilityEvent(View host, int eventType) {
20781             host.sendAccessibilityEventInternal(eventType);
20782         }
20783 
20784         /**
20785          * Performs the specified accessibility action on the view. For
20786          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
20787          * <p>
20788          * The default implementation behaves as
20789          * {@link View#performAccessibilityAction(int, Bundle)
20790          *  View#performAccessibilityAction(int, Bundle)} for the case of
20791          *  no accessibility delegate been set.
20792          * </p>
20793          *
20794          * @param action The action to perform.
20795          * @return Whether the action was performed.
20796          *
20797          * @see View#performAccessibilityAction(int, Bundle)
20798          *      View#performAccessibilityAction(int, Bundle)
20799          */
20800         public boolean performAccessibilityAction(View host, int action, Bundle args) {
20801             return host.performAccessibilityActionInternal(action, args);
20802         }
20803 
20804         /**
20805          * Sends an accessibility event. This method behaves exactly as
20806          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
20807          * empty {@link AccessibilityEvent} and does not perform a check whether
20808          * accessibility is enabled.
20809          * <p>
20810          * The default implementation behaves as
20811          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20812          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
20813          * the case of no accessibility delegate been set.
20814          * </p>
20815          *
20816          * @param host The View hosting the delegate.
20817          * @param event The event to send.
20818          *
20819          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20820          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20821          */
20822         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
20823             host.sendAccessibilityEventUncheckedInternal(event);
20824         }
20825 
20826         /**
20827          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
20828          * to its children for adding their text content to the event.
20829          * <p>
20830          * The default implementation behaves as
20831          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20832          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
20833          * the case of no accessibility delegate been set.
20834          * </p>
20835          *
20836          * @param host The View hosting the delegate.
20837          * @param event The event.
20838          * @return True if the event population was completed.
20839          *
20840          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20841          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20842          */
20843         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20844             return host.dispatchPopulateAccessibilityEventInternal(event);
20845         }
20846 
20847         /**
20848          * Gives a chance to the host View to populate the accessibility event with its
20849          * text content.
20850          * <p>
20851          * The default implementation behaves as
20852          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
20853          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
20854          * the case of no accessibility delegate been set.
20855          * </p>
20856          *
20857          * @param host The View hosting the delegate.
20858          * @param event The accessibility event which to populate.
20859          *
20860          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
20861          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
20862          */
20863         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20864             host.onPopulateAccessibilityEventInternal(event);
20865         }
20866 
20867         /**
20868          * Initializes an {@link AccessibilityEvent} with information about the
20869          * the host View which is the event source.
20870          * <p>
20871          * The default implementation behaves as
20872          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
20873          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
20874          * the case of no accessibility delegate been set.
20875          * </p>
20876          *
20877          * @param host The View hosting the delegate.
20878          * @param event The event to initialize.
20879          *
20880          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
20881          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
20882          */
20883         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
20884             host.onInitializeAccessibilityEventInternal(event);
20885         }
20886 
20887         /**
20888          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
20889          * <p>
20890          * The default implementation behaves as
20891          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20892          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
20893          * the case of no accessibility delegate been set.
20894          * </p>
20895          *
20896          * @param host The View hosting the delegate.
20897          * @param info The instance to initialize.
20898          *
20899          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20900          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20901          */
20902         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
20903             host.onInitializeAccessibilityNodeInfoInternal(info);
20904         }
20905 
20906         /**
20907          * Called when a child of the host View has requested sending an
20908          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
20909          * to augment the event.
20910          * <p>
20911          * The default implementation behaves as
20912          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20913          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
20914          * the case of no accessibility delegate been set.
20915          * </p>
20916          *
20917          * @param host The View hosting the delegate.
20918          * @param child The child which requests sending the event.
20919          * @param event The event to be sent.
20920          * @return True if the event should be sent
20921          *
20922          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20923          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20924          */
20925         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
20926                 AccessibilityEvent event) {
20927             return host.onRequestSendAccessibilityEventInternal(child, event);
20928         }
20929 
20930         /**
20931          * Gets the provider for managing a virtual view hierarchy rooted at this View
20932          * and reported to {@link android.accessibilityservice.AccessibilityService}s
20933          * that explore the window content.
20934          * <p>
20935          * The default implementation behaves as
20936          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
20937          * the case of no accessibility delegate been set.
20938          * </p>
20939          *
20940          * @return The provider.
20941          *
20942          * @see AccessibilityNodeProvider
20943          */
20944         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
20945             return null;
20946         }
20947 
20948         /**
20949          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
20950          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
20951          * This method is responsible for obtaining an accessibility node info from a
20952          * pool of reusable instances and calling
20953          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
20954          * view to initialize the former.
20955          * <p>
20956          * <strong>Note:</strong> The client is responsible for recycling the obtained
20957          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
20958          * creation.
20959          * </p>
20960          * <p>
20961          * The default implementation behaves as
20962          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
20963          * the case of no accessibility delegate been set.
20964          * </p>
20965          * @return A populated {@link AccessibilityNodeInfo}.
20966          *
20967          * @see AccessibilityNodeInfo
20968          *
20969          * @hide
20970          */
20971         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
20972             return host.createAccessibilityNodeInfoInternal();
20973         }
20974     }
20975 
20976     private class MatchIdPredicate implements Predicate<View> {
20977         public int mId;
20978 
20979         @Override
20980         public boolean apply(View view) {
20981             return (view.mID == mId);
20982         }
20983     }
20984 
20985     private class MatchLabelForPredicate implements Predicate<View> {
20986         private int mLabeledId;
20987 
20988         @Override
20989         public boolean apply(View view) {
20990             return (view.mLabelForId == mLabeledId);
20991         }
20992     }
20993 
20994     private class SendViewStateChangedAccessibilityEvent implements Runnable {
20995         private int mChangeTypes = 0;
20996         private boolean mPosted;
20997         private boolean mPostedWithDelay;
20998         private long mLastEventTimeMillis;
20999 
21000         @Override
21001         public void run() {
21002             mPosted = false;
21003             mPostedWithDelay = false;
21004             mLastEventTimeMillis = SystemClock.uptimeMillis();
21005             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21006                 final AccessibilityEvent event = AccessibilityEvent.obtain();
21007                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
21008                 event.setContentChangeTypes(mChangeTypes);
21009                 sendAccessibilityEventUnchecked(event);
21010             }
21011             mChangeTypes = 0;
21012         }
21013 
21014         public void runOrPost(int changeType) {
21015             mChangeTypes |= changeType;
21016 
21017             // If this is a live region or the child of a live region, collect
21018             // all events from this frame and send them on the next frame.
21019             if (inLiveRegion()) {
21020                 // If we're already posted with a delay, remove that.
21021                 if (mPostedWithDelay) {
21022                     removeCallbacks(this);
21023                     mPostedWithDelay = false;
21024                 }
21025                 // Only post if we're not already posted.
21026                 if (!mPosted) {
21027                     post(this);
21028                     mPosted = true;
21029                 }
21030                 return;
21031             }
21032 
21033             if (mPosted) {
21034                 return;
21035             }
21036 
21037             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
21038             final long minEventIntevalMillis =
21039                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
21040             if (timeSinceLastMillis >= minEventIntevalMillis) {
21041                 removeCallbacks(this);
21042                 run();
21043             } else {
21044                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
21045                 mPostedWithDelay = true;
21046             }
21047         }
21048     }
21049 
21050     private boolean inLiveRegion() {
21051         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21052             return true;
21053         }
21054 
21055         ViewParent parent = getParent();
21056         while (parent instanceof View) {
21057             if (((View) parent).getAccessibilityLiveRegion()
21058                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21059                 return true;
21060             }
21061             parent = parent.getParent();
21062         }
21063 
21064         return false;
21065     }
21066 
21067     /**
21068      * Dump all private flags in readable format, useful for documentation and
21069      * sanity checking.
21070      */
21071     private static void dumpFlags() {
21072         final HashMap<String, String> found = Maps.newHashMap();
21073         try {
21074             for (Field field : View.class.getDeclaredFields()) {
21075                 final int modifiers = field.getModifiers();
21076                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
21077                     if (field.getType().equals(int.class)) {
21078                         final int value = field.getInt(null);
21079                         dumpFlag(found, field.getName(), value);
21080                     } else if (field.getType().equals(int[].class)) {
21081                         final int[] values = (int[]) field.get(null);
21082                         for (int i = 0; i < values.length; i++) {
21083                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
21084                         }
21085                     }
21086                 }
21087             }
21088         } catch (IllegalAccessException e) {
21089             throw new RuntimeException(e);
21090         }
21091 
21092         final ArrayList<String> keys = Lists.newArrayList();
21093         keys.addAll(found.keySet());
21094         Collections.sort(keys);
21095         for (String key : keys) {
21096             Log.d(VIEW_LOG_TAG, found.get(key));
21097         }
21098     }
21099 
21100     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
21101         // Sort flags by prefix, then by bits, always keeping unique keys
21102         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
21103         final int prefix = name.indexOf('_');
21104         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
21105         final String output = bits + " " + name;
21106         found.put(key, output);
21107     }
21108 }
21109